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

Fellow Monks !

I tried to increment MAC address as follows:
my $mac = '0000000000b4'+1;
I meant that the $mac would get the value '0000000000b5'.
Of course it wasn't work:
"Argument "0000000000b4" isn't numeric in addition(+)..."

My searches for a module that do it, gives nothing...
Do anyone have an idea how should I do it ?

Thanks,
Mosh.

Replies are listed 'Best First'.
Re: Increment MAC address
by Forsaken (Friar) on Jun 19, 2005 at 13:55 UTC
    Nothing like a little intellectual exercise on a sunny sunday afternoon when normal people are at the beach :-)
    package MAC; use strict; use warnings; use Carp; sub new { #constructor. Takes 1 argument besides the Class name, a MAC address + separated by colons(:) # returns an object ref my($class, $mac) = @_; my $self = bless([], $class); @{$self} = split(':', $mac); unless($#{$self} == 5) { carp "failure to create MAC Object: address not composed of 6 byte +s"; return; } my $c = 0; foreach my $byte (@{$self}) { #check for proper input values unless($byte =~ /[0-9a-fA-F]{2}/) { carp "failure creating MAC Object: invalid address"; return; } #convert it to decimal, borrowed straight from the source of Data: +:Translate $byte = ord(unpack("A", pack("H*", $byte))); @{$self}[$c] = $byte; $c++; } return $self; } sub showdec { #takes no arguments. returns the mac address in decimal format, most +ly for reference my $self = shift; return join(":", @{$self}); } sub showhex { #takes no arguments. returns the mac address in hexadecimal format my $self = shift; return $self->_dectohex; } sub increase { #increases the mac address by argument. returns the newly increased +address in hexadecimal format my($self, $increase) = @_; unless($increase =~ /^\d+$/) { carp "argument to \'increase\' must be a positive integer"; return; } $$self[5] += $increase; for(my $c = 5; $c >= 1; $c--) { while($$self[$c] > 255) { $$self[$c] -= 256; $$self[$c - 1] += 1; } } return $self->_dectohex; } sub decrease { #decreases the mac address by argument. returns the newly decreased +address in hexadecimal format my($self, $decrease) = @_; unless($decrease =~ /^\d+$/) { carp "argument to \'decrease\' must be a positive integer"; return; } $$self[5] -= $decrease; for(my $c = 5; $c >= 1; $c--) { while($$self[$c] < 0) { $$self[$c] += 256; $$self[$c - 1] -= 1; } } return $self->_dectohex; } sub _dectohex { my $self = shift; my @hexmac; my $c = 0; foreach my $byte (@{$self}) { #convert to hex, this also borrowed (almost) straight from Data::T +ranslate $hexmac[$c] = sprintf("%02X", $byte); $c++; } return join(":", @hexmac); } 1;
    and here's pretty much what I used to test it, which can also serve as a tiny example. Note that the module has 1 major shortcoming, neither increase nor decrease check whether the final address ends up below 00:00:00:00:00:00 or above FF:FF:FF:FF:FF:FF. I'll leave that as an exercise for the OP :-)
    use strict; use warnings; use MAC; my $mac = MAC->new('10:BE:AF:1C:06:1F'); print $mac->showdec . "\n"; print $mac->showhex . "\n"; print $mac->increase(10) . "\n"; print $mac->increase(65536) . "\n"; print $mac->decrease(256) . "\n"; print $mac->decrease(16777216) . "\n";


    Remember rule one...
Re: Increment MAC address
by BrowserUk (Patriarch) on Jun 19, 2005 at 09:32 UTC

    Deja vu. An assignment question?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re: Increment MAC address
by bart (Canon) on Jun 19, 2005 at 10:34 UTC
    Note that a MAC address and an IP address are actually not related, except as if through a row in a table.

    As for a solution: try turning the hexadicimal string into a number, increment, and convert it back to a hex string:

    $next = sprintf "%012x", hex($ip)+1;

      Problem.

      printf "%012x\n", hex( 'fffffffffff0')+1;; Integer overflow in hexadecimal number at (eval 23) line 1, <STDIN> li +ne 22. Hexadecimal number > 0xffffffff non-portable at (eval 23) line 1, <STD +IN> line 22. 0000ffffffff

      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re: Increment MAC address
by fauria (Deacon) on Jun 19, 2005 at 16:42 UTC
    my $mac = 0xB4; $mac++; my $mac_addr = pack 'C6', $mac; #Or whatever... printf "0x%X\n", unpack 'C6', $mac_addr;
MAC Address Incrementor
by wilcoxc (Initiate) on Mar 10, 2008 at 17:33 UTC
    Mosh,
    I chose to use the Perl substr() function.

    I take a decimal string, convert it into a hex value,
    and format it to 12 hex digits (6 octets for Mac Addy).
    I segment the hex string by using the substr() function which
    takes a string, start value, and distance argument. Then I
    shove it into an array, and use join() to fuse it back together
    into MAC Address format.

    A for loop is then issued to increment the MAC address for the
    iteration agrument value that is passed into the script.

    Usage: macIncrementor.pl <MAC_START> <MAC_INCREMENT> <ITERATIONS>

    The script is as follows:

    This gives you the following output:

    Enjoy!!!! Let me know how it works for you!
      • You have an off-by-one error. Specifying one increment shows the start value and no increments.

        >perl macIncrementor.pl 65535 1 2 00:00:00:00:FF:FF <-- Should be 00:00:00:01:00:00 00:00:00:01:00:00 <-- Should be 00:00:00:01:00:01
      • It really sucks to have to convert the address to decimal before being able to use the program.

        >perl macIncrementor.pl 999 1 2 00:00:00:00:03:E7 00:00:00:00:03:E8 <-- Should be 00:00:00:00:09:9A
      • And most importantly, it only works for 0.000015 of the address space on a 32-bit Perl.

        >perl macIncrementor.pl 17179869184 1 2 00:00:FF:FF:FF:FF 00:00:FF:FF:FF:FF <-- Should be 00:04:00:00:00:01
        Ikegami, thanks a ton for the comments!

        I designed this script for testing where I wanted to use contiguous MAC addresses on a traffic generator. To give it an easy naming convention, I based it on a decimal for a subnet feel. I had intended to print the start value into a hex/MAC format, and then increment from there.
        My solution for the one-off error will be to not include the start value as an increment iteration.

        Any ideas on how to correct the conversion beyond 17179869184. I'm not sure
        how to fix this one.

        Again, I greatly appreciate the feedback!!!