diff --git a/utils/scripts/ulagen.pl b/utils/scripts/ulagen.pl new file mode 100644 index 0000000..6d631bb --- /dev/null +++ b/utils/scripts/ulagen.pl @@ -0,0 +1,61 @@ +#!/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 +# . + +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();