#!/usr/bin/perl # randmal.pl - random MAC address generator # Copyright (C) 2013 Ian Campbell # my $agpl = <http://www.gnu.org/licenses/. EOL use strict; use warnings; use CGI qw/:standard -nosticky/; use CGI::Carp qw(fatalsToBrowser); ### Parameters if ( defined param("source") ) { print header( -type => 'text/plain', -charset => 'utf-8' ); open SELF, "<$0" or die "cannot open self"; print ; close SELF; exit 0; } my $default_scope = "local"; my %scope_labels = ( 'local' => "Locally Administered", 'global' => "Globally Unique (OUI Enforced)" ); my $default_type = "unicast"; my %type_labels = ( 'multicast' => "Multicast", 'unicast' => "Unicast" ); my $scope = param("scope") || $default_scope; $scope = $default_scope unless $scope_labels{$scope}; my $local = $scope eq "local"; my $global = $scope eq "global"; my $type = param("type") || $default_type; $type = $default_type unless $type_labels{$type}; my $unicast = $type eq "unicast"; my $multicast = $type eq "multicast"; ### Generate the address my ( @bytes, @address, $warning ); if ($local) { @bytes = map { int( rand(256) ) } ( 0 .. 5 ); #$warning = sprintf( "%#08b", $bytes[0] ); } elsif ($global) { if ( defined param("oui") ) { @bytes = ( 0, 0, 0 ); push @bytes, map { int( rand(256) ) } ( 0 .. 2 ); # Pairs of hex digits, seperated by any character or none. Accepts common formats: # aa:bb:cc # aa-bb-cc # aabb.cc # etc if ( param("oui") =~ m/^\s*([[:xdigit:]]{2}).?([[:xdigit:]]{2}).?([[:xdigit:]]{2}).*/ ) { $bytes[0] = hex($1); $bytes[1] = hex($2); $bytes[2] = hex($3); $warning = "OUI had locally administered bit set, will clear" if $bytes[0] & 0x2; } else { $warning = "Failed to parse OUI"; } } else { $warning = "You need to specify an OUI " . param("oui"); } } else { $warning = "Unknown address scope ‘$scope’"; } $bytes[0] &= 0xfc; $bytes[0] |= 0x1 if $multicast; $bytes[0] |= 0x2 if $local; my @fmts = ( "%02x:%02x:%02x:%02x:%02x:%02x", "%02x-%02x-%02x-%02x-%02x-%02x", "%02x%02x.%02x%02x.%02x%02x" ); @address = map { sprintf( "$_", @bytes ) } @fmts if @bytes == 6; ### Print the page my $script = < 'utf-8', ); print start_html( -title => "Random MAC Address Generator", -script => $script, ); print h1( { -align => "center", }, [ "Random " . $scope_labels{$scope} . " " . $type_labels{$type} . " MAC Address:", @address, $warning ? "WARNING: $warning" : "", ] ); my %textparams = ( -id => "oui", ); $textparams{-disabled} = "disabled" if $scope eq "local"; print start_form( -method => "GET", -enctype => "application/x-www-form-urlencoded" ), p( { -align => "center" }, label("Address Scope:"), popup_menu( -name => "scope", -values => [ "local", "global" ], -labels => \%scope_labels, -default => $default_scope, -onChange => "updateOUI(this.value)", ), label("OUI:"), textfield( %textparams, -name => "oui", -value => scalar param("local") ), label("Address Class:"), popup_menu( -name => "type", -values => [ "unicast", "multicast" ], -labels => \%type_labels, -default => $default_type, ), button( -name => "Generate Another", -onClick => "submit()" ), ), end_form, hr, p( { -align => "center" }, small( "Copyright © 2013 Ian Campbell — Licensed under the " . a( { -href => "javascript:toggleLicense();" }, "AGPL" ) . "; " . a( { -href => url() . "?source=1" }, "Get Source" ) ) ), pre( { -id => 'license', -style => "display: None" }, $agpl ); end_form(); print end_html();