62 lines
1.3 KiB
Perl
62 lines
1.3 KiB
Perl
|
#!/usr/bin/env perl
|
||
|
# env
|
||
|
# Written in 2021 by Lucas
|
||
|
# CC0 1.0 Universal/Public domain - No rights reserved
|
||
|
#
|
||
|
# To the extent possible under law, the author(s) have dedicated all
|
||
|
# copyright and related and neighboring rights to this software to the
|
||
|
# public domain worldwide. This software is distributed without any
|
||
|
# warranty. You should have received a copy of the CC0 Public Domain
|
||
|
# Dedication along with this software. If not, see
|
||
|
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||
|
|
||
|
use v5.14;
|
||
|
use strict;
|
||
|
use warnings;
|
||
|
|
||
|
use Digest::SHA qw(sha1_hex);
|
||
|
use Time::HiRes qw(gettimeofday);
|
||
|
|
||
|
use constant {
|
||
|
UNIX_NTP_EPOCH_OFFSET => 2208988800,
|
||
|
};
|
||
|
|
||
|
my $__progname = ($0 =~ s,^.*/,,r);
|
||
|
|
||
|
sub usage
|
||
|
{
|
||
|
say STDERR "usage: $__progname MAC";
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
sub err
|
||
|
{
|
||
|
say STDERR "$__progname: @_";
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
sub main
|
||
|
{
|
||
|
usage if @ARGV != 1;
|
||
|
|
||
|
my $mac = shift @ARGV;
|
||
|
my @bytes = split(/[-:]/, $mac);
|
||
|
|
||
|
err "$mac: invalid MAC address" if @bytes != 6 ||
|
||
|
grep {!m/^[0-9a-fA-F]{1,2}$/} @bytes;
|
||
|
|
||
|
my @eui64 = map {hex} (@bytes[0..2], "ff", "fe", @bytes[3..5]);
|
||
|
$eui64[0] ^= 0x02;
|
||
|
|
||
|
my ($sec, $usec) = gettimeofday();
|
||
|
$sec = ($sec + UNIX_NTP_EPOCH_OFFSET) & 0xffffffff;
|
||
|
$usec = int(($usec / 1e6) * 0xffffffff);
|
||
|
|
||
|
my $gid = substr(sha1_hex(pack("N2C8", $sec, $usec, @eui64)), 30, 10);
|
||
|
|
||
|
my $ula_prefix = join(":", "fd$gid" =~ m/.{4}/g);
|
||
|
say "${ula_prefix}::/48";
|
||
|
}
|
||
|
|
||
|
main();
|