1#!/usr/bin/perl 2 3############################################### 4# Netmagis tool 5# Parse the network configurations of the host 6# and convert them to IOS pseudo CLI 7############################################### 8 9use strict; 10 11############################################### 12# IMPORTANT ! 13# LOCAL settings 14# 15# set here the SNMP community used by the snmp 16# agent of this serveur 17our $snmp_community = "public"; 18# 19# enable here the portmac collection 20# set 0 to disable 21# set 1 to enable 22our $portmac = 0; 23# 24# enable here the ipmac collection 25# set 0 to disable 26# set 1 to enable 27our $ipmac = 0; 28# 29# enable here the traffic statistics collectiona 30# set 0 to disable 31# set 1 to enable 32our $traffic_stats = 0; 33############################################### 34 35# Special tunning for local settings 36# To alter values of $snmp_community, $portmac, $ipmac and $traffic_stats 37# variables you must create the following file and set %sensor_type fields. 38# This is very usefull is case of script upgrade. 39if(-e "/home/conf/parsenet-options.pl") 40{ 41 require "/home/conf/parsenet-options.pl"; 42} 43 44 45our %net_struct; 46our %host; 47my $ifname; 48my $router; 49 50my $ifconfig = `ifconfig`; 51my $routage = `sysctl net.inet.ip.forwarding`; 52my $hostname = `hostname`; 53my $systype=`uname -s`; 54chomp($systype); 55 56# parsing du hostname 57chomp $hostname; 58 59if($hostname =~ /\./) 60{ 61 my @fqdn = split(/\./,$hostname); 62 $host{name} = $fqdn[0]; 63 $host{domain} = $fqdn[1]; 64 65 for(my $i = 2; $i < @fqdn; $i++) 66 { 67 $host{domain} = "$host{domain}.$fqdn[$i]"; 68 } 69} 70else 71{ 72 $host{name} = $hostname; 73 $host{domain} = ""; 74} 75 76 77# is the server a router? 78if($routage=~/net.inet.ip.forwarding.*([0-1])/) 79{ 80 $router = $1; 81 $net_struct{router}{status} = $1; 82 $net_struct{router}{type} = "router"; 83} 84 85# parsing de de la commande ifconfig 86my @l = split(/\n/,$ifconfig); 87 88for(my $i=0;$i<@l;$i++) 89{ 90 if($l[$i]=~/^(.*): flags=[0-9a-zA-Z]+<([A-Za-z0-9]+),/) 91 { 92 $ifname = $1; 93 if ($2 eq "UP") 94 { 95 $net_struct{$ifname}{status} = $2; 96 } 97 else 98 { 99 $net_struct{$ifname}{status} = "DOWN"; 100 } 101 } 102 if($l[$i]=~/^(.*): flags=[0-9a-zA-Z]+<>/) 103 { 104 $ifname = $1; 105 $net_struct{$ifname}{status} = "UNKNOWN"; 106 } 107 if($l[$i]=~/vlan: ([0-9]+) .*parent interface: ([A-Za-z0-9]+)/) 108 { 109 #vlan: 977 priority: 0 parent interface: em0 110 $net_struct{$ifname}{type} = "vlan"; 111 $net_struct{$ifname}{vlanid} = $1; 112 $net_struct{$ifname}{parent} = $2; 113 } 114 if($l[$i]=~/media: Ethernet/) 115 { 116 $net_struct{$ifname}{type} = "Ethernet"; 117 } 118 if($l[$i]=~/groups: ([A-Za-z0-9]+)/) 119 { 120 $net_struct{$ifname}{type} = $1; 121 } 122 if($l[$i]=~/(vlan[0-9]+) flags=[0-9a-zA-Z]+/) 123 { 124 $net_struct{$ifname}{vlanif}{$1} = 1; 125 } 126 if($l[$i]=~/inet ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) netmask ([0-9a-fA-FxX\.]+)/) 127 { 128 my $ip = $1; 129 my $nm = $2; 130 if($nm =~ s/^0x([\da-f]{8})/\1/i) 131 { 132 $nm = join '.', unpack "C*", pack "H*", $nm; 133 } 134 $net_struct{$ifname}{inet}{"$ip $nm"} = 1; 135 } 136 if($l[$i]=~/inet6 ([0-9a-fA-F:]+) prefixlen ([0-9]+)/ && $l[$i]!~/inet6 fe80:/) 137 { 138 $net_struct{$ifname}{inet6}{"$1/$2"} = 1; 139 } 140 if($l[$i]=~/lladdr ([0-9a-fA-F:]+)/) 141 { 142 $net_struct{$ifname}{mac} = $1; 143 } 144 if($l[$i]=~/ether ([0-9a-fA-F:]+)/) 145 { 146 $net_struct{$ifname}{mac} = $1; 147 } 148 if($l[$i]=~/trunkport ([0-9a-zA-Z]+)/) 149 { 150 $net_struct{$ifname}{trunk}{$1} = 1; 151 $net_struct{$1}{trunkmember} = $ifname; 152 } 153} 154 155read_tab_asso(); 156 157print "!\n!\n! uname: $systype\n"; 158print "!\n!\n! IOS like : \n! ----------\n!\n!\n"; 159 160gen_ios_output(); 161 162############################################################# 163# lecture d'un tableau associatif a 2 dimensions 164# 165sub read_tab_asso 166{ 167 foreach my $key (sort keys %net_struct) 168 { 169 print "! $key {\n"; 170 foreach my $kkey (sort keys %{$net_struct{$key}}) 171 { 172 if($kkey eq "vlanif" || $kkey eq "inet" || $kkey eq "inet6" || $kkey eq "trunk") 173 { 174 print "! \t$kkey -> \n"; 175 foreach my $kkkey (sort keys %{$net_struct{$key}{$kkey}}) 176 { 177 print "! \t\t -> $kkkey\n"; 178 } 179 } 180 else 181 { 182 print "! \t$kkey -> $net_struct{$key}{$kkey}\n"; 183 } 184 } 185 print "! }\n"; 186 } 187} 188 189sub gen_ios_output 190{ 191 printhost(); 192 193 my $bridge_group = 0; 194 195 # traitement des routers 196 foreach my $key (sort keys %net_struct) 197 { 198 if($net_struct{$key}{type} eq "router" && $net_struct{$key}{wr} != 1) 199 { 200 if($net_struct{$key}{status} == 1) 201 { 202 print "ip-routing\n!\n"; 203 } 204 else 205 { 206 print "no ip-routing\n!\n"; 207 } 208 209 $net_struct{$key}{wr} = 1; 210 } 211 } 212 213 # traitement des bridges 214 foreach my $key (sort keys %net_struct) 215 { 216 # si on trouve un bridge 217 if($net_struct{$key}{'type'} eq "bridge" && $net_struct{$key}{wr} != 1) 218 { 219 # equipement en mode bridge 220 print "bridge irb\n!\n"; 221 222 $bridge_group ++; 223 224 # interface bridge 225 print "interface BVI$bridge_group\n"; 226 # ecriture adresses IP associees au bridge 227 foreach my $ip (sort keys %{$net_struct{$key}{inet}}) 228 { 229 print " ip address $ip\n"; 230 } 231 foreach my $ip6 (sort keys %{$net_struct{$key}{inet6}}) 232 { 233 print " ip address $ip6\n"; 234 } 235 236 print "!\n"; 237 238 foreach my $kkey (sort keys %{$net_struct{$key}{vlanif}}) 239 { 240 printiface($kkey,$bridge_group); 241 } 242 243 $net_struct{$key}{wr} = 1; 244 } 245 } 246 247 # les interfaces qui suivent ne font pas partie d'un bridge-group 248 $bridge_group = 0; 249 250 # ecriture des autres interfaces 251 foreach my $key (sort keys %net_struct) 252 { 253 if(($net_struct{$key}{'type'} eq "Ethernet" || $net_struct{$key}{'type'} eq "vlan") 254 && $net_struct{$key}{wr} != 1) 255 { 256 printiface($key,$bridge_group); 257 } 258 } 259 260 # ecriture des parametrages SNMP 261 print "snmp-server community $snmp_community RO\n"; 262 print "snmp-server chassis-id $host{name}\n"; 263 264 my $sysloc_string = "snmp-server location"; 265 my $print_loc = 0; 266 if($portmac == 1) 267 { 268 $sysloc_string = "$sysloc_string <P>"; 269 $print_loc = 1; 270 } 271 if($ipmac == 1) 272 { 273 $sysloc_string = "$sysloc_string <I>"; 274 $print_loc = 1; 275 } 276 if($print_loc == 1) 277 { 278 print "$sysloc_string\n"; 279 } 280 print "!\n"; 281} 282 283sub printiface 284{ 285 my ($name,$bridge_group) = @_; 286 287 if($net_struct{$name}{wr} != 1) 288 { 289 # si on est en presence d'une interface vlan 290 if($net_struct{$name}{type} eq "vlan") 291 { 292 print "interface $name\n"; 293 294 if($traffic_stats == 1) 295 { 296 my $link = $net_struct{$net_struct{$name}{parent}}{mac}; 297 $link =~ s/://g; 298 print " description <X M$host{name}$link\.$net_struct{$name}{vlanid}>\n"; 299 } 300 else 301 { 302 print " description X\n"; 303 } 304 #print " description <X M$host{name}$link\.$net_struct{$name}{vlanid}>\n"; 305 print " parent-iface $net_struct{$name}{parent}\n"; 306 print " encapsulation dot1Q $net_struct{$name}{vlanid}\n"; 307 } 308 # si on est en presence d'un trunk 309 elsif($net_struct{$name}{type} eq "Ethernet" && exists $net_struct{$name}{trunk}) 310 { 311 print "interface $name\n"; 312 313 if($traffic_stats == 1) 314 { 315 print " description <X M$host{name}.$name>\n"; 316 } 317 else 318 { 319 print " description X\n"; 320 } 321 } 322 else 323 { 324 print "interface $name\n"; 325 if($net_struct{$name}{status} eq "UP" && $net_struct{$name}{mac} =~ /[0-9a-fA-F:]+/) 326 { 327 my $link = $net_struct{$name}{mac}; 328 $link =~ s/://g; 329 330 if(exists $net_struct{$name}{trunkmember}) 331 { 332 $link = "$link-$name"; 333 } 334 335 if($traffic_stats == 1) 336 { 337 print " description <L$link M$host{name}$link>\n"; 338 } 339 else 340 { 341 print " description L$link\n"; 342 } 343 } 344 else 345 { 346 print " description X\n"; 347 } 348 349 if(exists $net_struct{$name}{trunkmember}) 350 { 351 print " channel-group $net_struct{$name}{trunkmember} mode auto\n" 352 } 353 354 } 355 # ajout dans le bridge group de l'interface 356 if($bridge_group > 0) 357 { 358 print " bridge-group $bridge_group\n" 359 } 360 361 # ecriture adresses IP 362 foreach my $ip (sort keys %{$net_struct{$name}{inet}}) 363 { 364 print " ip address $ip\n"; 365 } 366 foreach my $ip6 (sort keys %{$net_struct{$name}{inet6}}) 367 { 368 print " ip address $ip6\n"; 369 } 370 371 print "!\n"; 372 373 $net_struct{$name}{wr} = 1; 374 } 375} 376 377sub printhost 378{ 379 if($host{name} ne "") 380 { 381 print "hostname $host{name}\n!\n"; 382 } 383 if($host{domain} ne "") 384 { 385 print "ip domain name $host{domain}\n!\n"; 386 } 387} 388