#!/usr/bin/perl

use strict;

my $in=shift;

# see iana.org for authoritative list.

my %Types=("00:01"=>"Time+Link Layer (DUID-LLT)",
	   "00:02"=>"Vendor Assigned (DUID-EN)",
	   "00:03"=>"Link Layer (DUID-LLT)");
	   

my %HWTypes=("00:00"=>"Reserved",
	     "00:01"=>"Ethernet",
	     "00:02"=>"Exp. Ethernet",
	     "00:03"=>"Amateur Radio",
	     "00:04"=>"Token Ring",
	     "00:05"=>"Chaos",
	     "00:06"=>"IEEE 802",
	     "00:07"=>"ARCNET",
	     "00:08"=>"Hyperchannel",
	     "00:09"=>"Lanstart",
	     "00:0a"=>"Autonet",
	     "00:0b"=>"Localtalk",
	     "00:0c"=>"LocalNet",
	     "00:0d"=>"Ultra link",
	     "00:0e"=>"SMDS",
	     "00:0f"=>"Frame Relay",
	     "00:10"=>"ATM",
	     "00:11"=>"HDLC",
	     "00:12"=>"Fiber Channel",
	     "00:13"=>"ATM",
	     "00:14"=>"Serial",
	     "00:15"=>"ATM",
	     "00:16"=>"MIL-STD-88-220",
	     "00:17"=>"Metricom",
	     "00:18"=>"IEEE 1394",
	     "00:19"=>"MAPOS",
	     "00:1a"=>"Twinaxial",
	     "00:1b"=>"EUI-64",
	     "00:1c"=>"HIPARP",
	     "00:1d"=>"ISO 7816-3",
	     "00:1e"=>"ARPSec",
	     "00:1f"=>"IPSec",
	     "00:20"=>"Infiniband",
	     "00:21"=>"TIA-102",
	     "00:22"=>"Wiegand",
	     "00:23"=>"Pure IP");

# windows uses - instead of : 
$in=~ s/\-/:/;

if ( $in =~ /^:?([a-f0-9]{1,2}:)+([a-f0-9]{1,2})?$/i ) {
    print "Linux String: ".hextostring($in)."\n";
    print "Time + MAC: ".hextorfc($in)."\n";
}

if ( $in =~ /^\\/ ) {
    print "Hex: ".stringtohex($in)."\n";
    print "Time + MAC: ".stringtorfc($in)."\n";
}




#
# Convert "hex" to "string"
#

sub hextostring {
    my $hex=shift;
    $hex=lc($hex);
    my $out='';
    my $num;
    if ( $hex =~ /^:?([a-f0-9]{1,2}:)+([a-f0-9]{1,2})?$/ ) {
	foreach ( split /:/,$hex ) {
	    $num=hex($_);
	    if ( $num < 127 and $num > 31 ) {
		$out.=chr($num);
	    } else {
		$out.=sprintf"\\%03o",$num;
	    }
	}
	return $out;
    } else {
	return 0;
    }
}

#
# Convert "string" to "hex"
#

sub stringtohex {
# sample \002\317g)\000\001\000\001\032\336\306\373\000\014)g\317\002

    my $string=shift;
    my $out='';
    while ( $string ne '' ) {
	if ( $string =~ s/^\\([0-9]{3})// ) {
	    $out.=sprintf('%02x',oct($1)).":";
	} else {
	    $string =~ s/.// ;
	    $out.=sprintf('%02x',ord($&)).":";
	}
    }
    $out=~ s/:$//;
    $out=lc($out);
    return $out;
}

#
# Convert "hex" to "time + MAC"
#

sub hextorfc {
    my $hex=shift;
    my $error='';
    my $type='unknown';
    my $hwtype='unknown';
    my $hwhex='';
    my $timehex='';
    my $mac='';
    my $enthex='';
    $hex=~ s/([0-9]{1,2}:){2}//;
    $type=$&;
    $type= s/:$//;
    my $time;
    if ( $type=='00:01' || $type=='00:03' ) {
	$hex =~ s/([0-9a-f]{1,2}:){2}//;
	my $hwhex=$&;
	$hwhex=~s/:$//;
	if ( $type=='00:01' ) {
	    $hex=~ s/([0-9a-f]{1,2}:){4}//;
	    $timehex=$&;
	    
	    $time=$timehex;

	    $time=~s/://g;
	    $time=hex($time);
	}
	my $mac=$hex;
	return "DUID-LLT (Time+Link Layer) Hardware: $hwhex ".$HWTypes{$hwhex}."; Time: $timehex ".$time.' '.localtime($time)." Link Layer $mac";
    }
    if ( $type=='00:02' ) {
	$hex=~ s/([0-9a-f]{2}:){4}//;
	$enthex=$&;
	$enthex=~s/:$//;
	return "DUID-EN (Vendor Defined) Enterprise ID $enthex Identified $hex";
    }
    return "Unknown Format $type - $hex";

}

#
# convert "string" to "time+mac"
#

sub stringtorfc {
    my $string=shift;
    my $hex=stringtohex($string);
    return hextorfc($hex);

}
