MikeDexter has asked for the wisdom of the Perl Monks concerning the following question:

My output prints with a warning. I was told yesterday in cb to put the following code into an if statement.
"if (the ipv4 stuff is defined) {do all the fun printing}"
The sub does a push @nics, \%nic; return @nics; So my question is should the if be the outer loop or the for statement?

for my $nic (networkInfo()) { if ($nic->{device}) { print "DeviceMain: $nic->{device} has IP Address $nic->{ip}\n" . "\tMask: $nic->{mask}\n" . "\tBroadcast: $nic->{bcast}\n"; print "DeviceMain: $nic->{device} also IPv6 address $nic->{ip6}\n" +; } }

The output I am getting is as follows:

Are you sure you would like to delete all *.bak files that exist in: / +dir/etc-test [yes/no] yes No files were found >>> Oper Sys: linux >>> Platform: RedHat >>> Hostname: host1 Device: eth0 also has IPv6 address of xxxx::219:x9xx:xxxx:8091/64 Device: eth1 has the IP Address of xx.xx.xx.xx Mask: xx.xx.xx.xx Broadcast: xx.xx.xx.xx Device: eth1 also has IPv6 address of xxxx:80x0:22x:225:219:xxxx:xxxx: +808x/64 Use of uninitialized value in concatenation (.) or string at ./sec-tes +t.pl line 20 (#1) (W uninitialized) An undefined value was used as if it were alread +y defined. It was interpreted as a "" or a 0, but maybe it was a mi +stake. To suppress this warning assign a defined value to your variables. To help you figure out what was undefined, perl tells you what ope +ration you used the undefined value in. Note, however, that perl optimiz +es your program and the operation displayed in the warning may not necessa +rily appear literally in your program. For example, "that $foo" is usually optimized into "that " . $foo, and the warning will refer +to the concatenation (.) operator, even though there is no . in your program. DeviceMain: eth0 has IP Address Mask: Broadcast: DeviceMain: eth0 also IPv6 address xxxx::219:x9xx:feeb:8091/64 DeviceMain: eth1 has IP Address xx.xx.xx.xx Mask: xx.xx.xx.xx Broadcast: xx.xx.xx.xx DeviceMain: eth1 also IPv6 address xxxx:xxc0:22x:225:219:x9xx:xxxx:808 +x/64

Replies are listed 'Best First'.
Re: Need help with small IF statement
by ikegami (Patriarch) on Jan 20, 2010 at 16:07 UTC

    Take two seconds to think what you want to check. All the nics have a device, so that's obviously not it.

    for my $nic (networkInfo()) { if (defined($nic->{ip}) { print "DeviceMain: $nic->{device} " . "has IP Address $nic->{ip}\n" . "\tMask: $nic->{mask}\n" . "\tBroadcast: $nic->{bcast}\n"; } if (defined($nic->{ip6}) { print "DeviceMain: $nic->{device} " . "has IPv6 address $nic->{ip6}\n"; } }

    (Made the lines shorter to avoid PM's wrapping.)

Re: Need help with small IF statement
by kennethk (Abbot) on Jan 20, 2010 at 15:59 UTC
    You should reference existing threads for interested monks: Data::Dumper is returning empty ([id://818253]) for example.

    For your desired result, you should use the structure as written above. The idea is that the networkInfo() subroutine returns a list, which you iterate over. For every entry in that list, you want to perform your tests. Examining your output, I note blank entries in your output for $nic->{ip}, $nic->{mask} and $nic->{bcast}. This means the bug is where you assign those values in the networkInfo() subroutine.

      I will reference in the future. Good point. Sometimes too much information just muddies the water and I try to ask clear questions as much as possible. If I throw too much at someone they may run and hide.

      As for the code eth0 has no IPv4 information in it, but does have IPv6, so that is why the data returns empty. Here is the output of ifconfig

      eth0 Link encap:Ethernet HWaddr 00:19:B9:EB:80:91 inet6 addr: fe80::219:b9ff:xxxx:8091/64 Scope:Link UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) Interrupt:169 Memory:f4000000-f4011100 eth1 Link encap:Ethernet HWaddr xx:19:xx:xx:80:xx inet addr:xx.xx.xx.xx Bcast:xx.xx.xx.xx Mask:xx.xx.xx.xx inet6 addr: 3xxx:80c0:22c:225:219:b9ff:xxxx:80xx/64 Scope:Gl +obal inet6 addr: fexx::219:b9ff:feeb:80xx/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:4173511549 errors:0 dropped:0 overruns:0 frame:0 TX packets:4181891776 errors:0 dropped:0 overruns:0 carrier: +0 collisions:0 txqueuelen:1000 RX bytes:696505594365 (648.6 GiB) TX bytes:630337964502 (58 +7.0 GiB) Interrupt:169 Memory:f8000000-f8011100 lo Link encap:Local Loopback inet addr:xx.xx.xx.xx Mask:xx.xx.xx.xx inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:4698160 errors:0 dropped:0 overruns:0 frame:0 TX packets:4698160 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:611857168 (583.5 MiB) TX bytes:611857168 (583.5 Mi +B)

      I need this thing to not care about who has what. Not be dependant on IPv4 being satisifed. If IPv4 info is there print it. if IPv6 info is there print that too. Frustrated trying to figure that out.

      yesterday I mistakenly said What is garanteed is v4 data. What is not garanteed is which NIC the v4 data will be on and if there will be any v6 data and now I am realizing some nic devices could have IPv4 only, IPv6 only, or both.
      Can you or someone help me get that piece fixed?

        If there are multiple conditions (IPv4 may or may not be there, IPv6 may or may not be there), then there should be multiple conditionals. So rather than testing if the key device is defined, you should test if ip and if ip6 are defined, like:

        for my $nic (networkInfo()) { if (defined $nic->{ip}) { print "DeviceMain: $nic->{device} has IP Address $nic->{ip}\n" . "\tMask: $nic->{mask}\n" . "\tBroadcast: $nic->{bcast}\n"; } if (defined $nic->{ip6}) { print "DeviceMain: $nic->{device} has IPv6 address $nic->{ip6}\n"; } }

        Note I also added defined tests. This has no real impact here (unless these values can be meaningfully defined to empty strings or the value 0), but it is probably a good habit to get into since later it will avoid unwanted autovivification side effects for complex structures as well as weird bugs when those values are legal.

Re: Need help with small IF statement
by molecules (Monk) on Jan 20, 2010 at 16:01 UTC
    Try using the "defined" keyword:
    if defined($nic->{ip}){ print "DeviceMain: $nic->{device} has IP Address $nic->{ip}\n"; } if defined($nic->{mask}){ print "\tMask: $nic->{mask}\n"; }
    etc...
Re: Need help with small IF statement
by Ratazong (Monsignor) on Jan 20, 2010 at 16:02 UTC

    Hi

    You state you want to
    "if (the ipv4 stuff is defined) {do all the fun printing}".
    However what you do is
    if (the device is existing) { print all the IP4 and IP6-stuff }

    However if the ip4-part isn't existing, you'll get the error you describe accessing it.

    You might want to

    • change the condition inside the loop (e.g. check if $nic->{ip} is defined)
    • change the brackets of the if - I'm not sure what you want to print, however I assume you want to print the ip6-part always, but the ip4-part only if it is there

    HTH, Rata