#!/usr/bin/perl # tooltje om wleiden.conf's om te zetten naar wleiden.xml's volgens # wleiden.dtd # # lodewijk use XML::DOM; #use warnings; if ($#ARGV eq -1) { die "Usage: convert.pl \n"; } #######IP bereken gedeelte (speciaal voor static dhcp)###### $nGlobal=0; sub Len2MaskCalc { #bereken subnet my $nMask = $_[0]; if( $nMask < 1 ) { return 0; } my $nCalc = 0; for( my $nX = 7; $nX > -1; $nX-- ) { $nCalc = $nCalc + 2**$nX; $nMask = $nMask - 1; $nGlobal = $nMask; if( $nMask < 1 ) { return( $nCalc ); } } return $nCalc; } sub CalcSubnet { #geef handelingen tot het maken van subnet my @subnet; $subnet[0]=Len2MaskCalc( $_[0] ); $subnet[1]=Len2MaskCalc( $nGlobal ); $subnet[2]=Len2MaskCalc( $nGlobal ); $subnet[3]=Len2MaskCalc( $nGlobal ); return( join( ".", @subnet) ); } sub CalcOnNetwork { # Split into array # Convert to int # bitwise and operaties # vergelijken # CalcOnNetwork( $tmp_ip1, $tmp_ip2, CalcSubnet( 24 ) ); my $tmpIp1 = 0; my $tmpIp2 = 0; my $tmpSub = 0; my @ip1 = split( /\./ , $_[0] ); my @ip2 = split( /\./ , $_[1] ); my @subnet = split( /\./ , $_[2] ); for( my $ctr=0; $ctr < 4; $ctr++ ) { $tmpIp1 = 0 + $ip1[$ctr]; $tmpIp2 = 0 + $ip2[$ctr]; $tmpSub = 0 + $subnet[$ctr]; $tmpIp1 = $tmpIp1 & $tmpSub; $tmpIp2 = $tmpIp2 & $tmpSub; if( $tmpIp1 != $tmpIp2 ) { return(0); } } return(1); } #######End IP bereken gedeelte###### sub set_attrs($%) { local ($em, %attrs) = @_; foreach $k (keys %attrs) { if ($attrs{$k} ne '') { $em->setAttribute($k, $attrs{$k}); } } } sub do_node { local $node = $doc->createElement("node"); if ($nodetype eq 'proxy') { $nodename = $nodetype . $nodename; } local %map = ( name => $nodename, type => $nodetype, status => $status, location => $location, master_ip => $master_ip, x => $X, y => $Y, n => $N, e => $E ); set_attrs($node, %map); return $node; } # gegeven een interface naam, bouw een XML node uit de info in # de verschillende globale dicts sub extract_iface($) { local ($if) = @_; local $iface = $doc->createElement($TYPE{$if}); local %commonmap = ( iface => $if, desc => $DESC{$if}, sdesc => $SDESC{$if}, status => "up" ); local @wirelessattrs = qw(essid antenna gain direction beamwidth cable height); set_attrs($iface, %commonmap); if ($TYPE{$if} eq "wireless") { $iface->setAttribute("mode", "b"); # de polar enum is lowercase in de DTD if (exists $POLAR{$if}) { $s = lc $POLAR{$if}; if ($s =~ /hor/) { $s = 'hor'; $iface->setAttribute("polar", $s); } elsif ($s =~ /ver/) { $s = 'ver'; $iface->setAttribute("polar", $s); } } # zet channel alleen als dit een master is if (exists $MODE{$if} and $MODE{$if} eq "master") { $iface->setAttribute("channel", $CHANNEL{$if}); } # de rest kan rechtstreeks uit de relevante dict gekopieerd # worden als het daar in staat foreach $a (@wirelessattrs) { $b = uc $a; if (exists $$b{$if}) { $iface->setAttribute($a, $$b{$if}); } } set_attrs($iface, %wirelessmap); } return $iface; } sub extract_link($) { local ($if) = @_; local $link = $doc->createElement("link"); local $iface = $if; $iface =~ s/:.*//; $IP{$if} =~ s/ //g; ($ip, $mask) = split /\//, $IP{$if}; $type = $ip =~ /172.16/ ? "interlink" : "public"; local %map = ( desc => $DESC{$if}, sdesc => $SDESC{$if}, status => "up", iface => $iface, type => $type, ip => $ip, mask => $mask ); set_attrs($link, %map); if ($type eq 'public' and $DHCP{$if} ne 'no') { $link->setAttribute("dhcp", $DHCP{$if}); # if ((lc $DHCP_STATIC{$if}) =~ /host (\w+){hardware ethernet ([0-9a-f:]+); fixed-address ([0-9.]+);}/) { foreach $static_entry (@static) { (my $static_name, my $static_ip, my $static_mac) = split('\=',$static_entry); if ($static_mac) { if( CalcOnNetwork($ip, $static_ip, CalcSubnet($mask)) ) { local $static = $doc->createElement("dhcp_static"); $static->setAttribute('name', $static_name); $static->setAttribute('mac', $static_mac); $static->setAttribute('addr', $static_ip); $link->appendChild($static); } } } # # local $static = $doc->createElement("dhcp_static"); # $static->setAttribute('name', $1); # $static->setAttribute('mac', $2); # $static->setAttribute('addr', $3); # $link->appendChild($static); # } } return $link; } foreach $file (@ARGV) { print "Working on: $file\n"; @$_ = () foreach qw(static); $$_ = "" foreach qw(location master_ip gw_open nodetype nodename OS status X Y N E OS DISK AGGREGATE); %$_ = () foreach qw(config TYPE IP DESC SDESC SPEED DHCP DHCP_STATIC OSPF_BROADCAST OSPF_NEIGHBORS MODE ESSID CHANNEL POLAR ANTENNA GAIN DIRECTION BEAMWIDTH CABLE HEIGHT ROUTE); do($file) || die "Could not parse filename: $file\n"; parse_config(); $doc = XML::DOM::Document->new(); $doc->setDoctype($doc->createDocumentType(qw(node), "wleiden.dtd")); $doc->setXMLDecl($doc->createXMLDecl("1.0")); $node = do_node(); $doc->appendChild($node); @ifaces = (); @links = (); foreach $if (keys %config) { if ($if !~ /:/) { unshift @ifaces, extract_iface($if); } unshift @links, extract_link($if); } foreach $iface (@ifaces) { $node->appendChild($iface); } foreach $link (@links) { $node->appendChild($link); } $xmlf = $file; $xmlf =~ s/conf/xml/; $doc->printToFile ($xmlf); `tidy -m -i -xml -wrap 1000000 $xmlf`; post_process($xmlf); } # gesnaaid van ../genesis2xml.pl en aangepast sub parse_config { foreach $if (keys %config) { $cfg = $config{$if}; while ($cfg) { $cfg =~ s/^([^\n\r]+)[\r\n]*//m; $line = $1; $line =~ s/\s*#.*//; if ((($name, $value) = split(/=/, $line)) eq 2) { if ($name eq 'ESSID') { $value = lc($value); } # pff, d'r zit een spelfout in alle # wleiden.conf's ! if ($name eq 'HEIGTH') { $name = 'HEIGHT'; } $doit = "if (exists(\$$name\{\"$if\"\})) {\$$name\{\"$if\"\}.=\" $value\";} else {\$$name\{\"$if\"\}.=\"$value\";}"; eval($doit); } $cfg =~ s/[\r\n]*$//m; } } } # reformat de XML uitvoer zodat de attributen onder elkaar terecht komen sub post_process { local ($fname) = @_; open INFILE, $fname or die $!; open OUTFILE, "> $fname.tmp" or die $!; $spaces = " "; while () { $line = $_; if ($line !~ /^([ ]*<[^?!][^ ]*) (.*)/) { # regels zonder elements kunnen direct door print OUTFILE $line; } else { # $1 is nu het eerste stuk, $2 het staart stuk # dus geeft voor $2. $numspaces = (length $1) + 1; print OUTFILE $1 . "\n"; # splits het staart stuk @fields = split / /, $2; $len = @fields; # itereer over de delen, maar kijk uit, 1 attribuut # met spaties in de waarde zal nu meerdere delen zijn. $i = 0; while ($i < $len) { $s = substr $spaces, 0, $numspaces; if ($fields[$i] =~ /.*".*".*/) { # dit veld heeft twee quotes en is dus # een compleet deel. print het. print OUTFILE $s . $fields[$i] . "\n"; $i++; } else { # dit veld heeft maar 1 quote. deze # waarde gaat door tot het volgende # veld met maar 1 quote. print OUTFILE $s . $fields[$i]; $j = $i + 1; while ($j < $len and $fields[$j] !~ /.*".*/) { print OUTFILE " " . $fields[$j]; $j++; } if ($j < $len) { print OUTFILE " " . $fields[$j]; } print OUTFILE "\n"; $i = $j + 1; } } } } rename "$fname.tmp", $fname }