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

hi all, i'm building some fun perl one-liners for use with external programs and such.. i found a cool perl script that i converted to a single-liner that computes the network address of a unix machine:
this computes the network address..
perl -e '$ip=""; $mask=""; @maskbyte=split /\ +./,$mask; @ipbyte=split /\./, $ip; for($i=0;$i<4;$i++) { $b1=$maskbyt +e[$i]+0; $b2=$ipbyte[$i]+0;$NetByte=$b1&$b2; if($i != 0) {$NetAddr = +$NetAddr . "." . $NetByte; } else { $NetAddr=$NetByte ;}} print "$Net +Addr\n";'
now i'm trying to get the broadcast address, but i'm having some problems converting the 1's complement of the subnet mask back to something readable..
here's what i have so far:
perl -e '$ip=""; $mask=""; @maskbyte=split /\ +./,$mask; @ipbyte=split /\./, $ip; for($i=0;$i<4;$i++) { $b1=$maskbyt +e[$i]+0; $b2=$ipbyte[$i]+0; $NetByte=$b2 || ~$b1 ; if($i != 0) {$Ne +tAddr = $NetAddr . "." . $NetByte; }else { $NetAddr=$NetByte ;}} prin +t "$NetAddr\n";'
the one's complement of the subnet mask orred with the network address (formula for broadcast) gives a funky number..

Replies are listed 'Best First'.
Re: perl ipcalc oneliners
by Fletch (Bishop) on Jun 09, 2005 at 23:56 UTC

    You might want to look into Net::NetMask rather than trying to do the conversion yourself. And use <code></code> tags next time.

    We're looking for people in ATL

Re: perl ipcalc oneliners
by monarch (Priest) on Jun 09, 2005 at 23:55 UTC
    Sometimes one can make these things more complicated than they are.

    The first one liner I would write as the following:

    # convert IP addresses to unsigned long integers my $addr=""; my @addrb=split("[.]",$addr); my ( $addrval ) = unpack( "N", pack( "C4",@addrb ) ); my $mask=""; my @maskb=split("[.]",$mask); my ( $maskval ) = unpack( "N", pack( "C4",@maskb ) ); # calculate network address my $netwval = ( $addrval & $maskval ); # convert network address to IP address my @netwb=unpack( "C4", pack( "N",$netwval ) ); my $netw=join(".",@netwb); # print print( $netw );

    What I'm doing is converting the dot notation into an integer. That way I can do bit manipulation on the address as a whole rather than trying to deal with individual bytes.

    To get the broadcast address should be just as easy. Although I haven't done bit inversions in Perl before..

    # calculate broadcast address my $brodval = ( $addrval & $maskval ) + ( ~ $maskval );

    So the whole file together looks like this:

    The output is:

    Network: Broadcast:

    One lining this is left as an exercise for the reader.

    Update: on a more personal note I would caution against the byte-at-a-time approach because of the possible error whereby the third byte should be different to what you expect for the broadcast address.. using the netmask supplied ( both the 3rd and 4th bytes are affected, not just the 4th.

    Update 2: Just making this more sexy, an alternative presentation of the code is as follows:

    Update 3: Just letting everyone know I added readmore tags to update 2. I have to put in lots of update notices cause I was told off by a Saint yesterday for not putting update notices in every single time I make an update, no matter how small, and no matter how frequently.