├── .gitignore
├── README.md
├── prior_art
├── generate-rfc4193-addr
└── gen-ula.sh
└── gen-ula.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | oui.txt
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Bash ULA Generator
2 | Generate an IPv6 Unique Local Address prefix
3 |
4 | Alexandre de Verteuil
5 | 2017-06-20
6 |
7 | Based on scripts from **Shinsuke Suzuki** and **Holger Zuleger**, available under the `prior_art` directory.
8 |
9 | ## Usage
10 |
11 | Simply run in a bash shell. You will be prompted for your physical MAC address (guessing "eth0" is no longer relevant in 2017).
12 |
13 | ## Requirements
14 |
15 | `wget`, `ntpq`
16 |
17 | ## Improvements over other scripts
18 |
19 | - Not a CGI script
20 | - Computes the SHA1 hash of bytes, not their hex representation
21 | - Better text output
22 |
23 | ## References
24 |
25 | - [RFC 4193 — Unique Local IPv6 Unicast Addresses](https://tools.ietf.org/html/rfc4193)
26 | - [Unique local address](https://en.wikipedia.org/wiki/Unique_local_address) on Wikipedia
27 |
--------------------------------------------------------------------------------
/prior_art/generate-rfc4193-addr:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # @(#) generate-rfc4193-addr.sh (ULA) (c) Sep 2004 - Jun 2011 Holger Zuleger
4 | #
5 | # do what the name suggest
6 | #
7 | # firstpart = 64-Bit NTP time
8 | # secondpart = EUI-64 Identifier or 48 Bit MAC-Adress
9 | # sha1sum ($firstpart | $secondpart )
10 | # use least significant 40 Bits of sha1sum
11 | # build global prefix (locally assigned == FD00::/8)
12 | #
13 | # (M1) 11. May 2006
14 | # - a check added to complain if firstpart or secondpart is empty
15 | # - firstpart calculation changed in such a way, that only one transmit
16 | # time is stored (ntpdate since version 4.2.0 use a list of ntp servers)
17 | #
18 | # (M2) 27. Aug 2006
19 | # Fixed bug in using reference time instead of transmit timestamp.
20 | # Thanks to Marc A. Donges for finding this out
21 | #
22 | # (M3) 4. Sep 2006
23 | # Use ntpq instead of ntpdate because the latter is deprecated.
24 | # This requires a local running and syncronized ntpd, but
25 | # speeds up the execution time
26 | #
27 | # (M4) 29. Dec 2006
28 | # set LC_ALL=C at the beginning of the script, to be sure the grep command
29 | # used to scan the output of the ifconfig command finds the expected string
30 | # Thanks to Ted Percival for finding this out
31 | #
32 | # (M5) 5. Jun 2011
33 | # tr command added to remove the trailing newline from the sha1 calculation
34 | # Thanks to Reinard Max for the fix
35 | #
36 | PATH=/usr/local/bin:/bin:/usr/bin:/usr/sbin:/sbin
37 |
38 | debug=0
39 | USE_NTPQ=1
40 | NTPSERVER=pool.ntp.org
41 |
42 | #(M4)
43 | LC_ALL=C
44 | export LC_ALL
45 |
46 | #(M3)
47 | if test $USE_NTPQ -eq 1
48 | then
49 | if time=`ntpq -c rv | grep clock=`
50 | then
51 | test $debug -eq 1 && echo "$time"
52 | firstpart=`echo $time | sed -e "s/clock=//" -e "s/ .*//" -e "s/\.//"`
53 | else
54 | echo "no local ntpd running" 1>&2
55 | exit 1
56 | fi
57 | else
58 | #(M1)
59 | #(M2)
60 | firstpart=`ntpdate -d -q $NTPSERVER 2>/dev/null | sed "/transmit timestamp/q" |
61 | sed -n "/transmit time/s/^transmit timestamp: *\([^ ]*\) .*/\1/p" |
62 | tr -d "."`
63 | fi
64 |
65 | secondpart=`ifconfig eth0 |
66 | grep "inet6 addr: fe80" |
67 | sed -n "s|^.*::\([^/]*\)/.*|\1|p" |
68 | tr -d ":"`
69 |
70 | #(M1)
71 | if test -z "$firstpart" -o -z "$secondpart"
72 | then
73 | echo "$0: installation error: check if ntpdate and ifconfig is in search path"
74 | exit 1
75 | fi
76 |
77 | test $debug -eq 1 && echo "Firstpart: $firstpart"
78 | test $debug -eq 1 && echo "Secondpart: $secondpart"
79 | test $debug -eq 1 && echo "123456789o123456789o123456789o123456789o123456789o123456789o"
80 | test $debug -eq 1 && echo ${firstpart}${secondpart} | sha1sum
81 |
82 | #(M5)
83 | globalid=`echo ${firstpart}${secondpart} | tr -d "\012" | sha1sum | cut -c31-40`
84 | test $debug -eq 1 && echo $globalid
85 |
86 |
87 | echo fd${globalid} | sed "s|\(....\)\(....\)\(....\)|\1:\2:\3::/48|"
88 |
--------------------------------------------------------------------------------
/gen-ula.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # ULA Generator
4 | # Alexandre de Verteuil
5 | # 2017-06-20
6 | #
7 | # Based on scripts from Shinsuke Suzuki and Holger Zuleger,
8 | # available under the prior_art directory.
9 | #
10 | # Usage: simply run in a bash shell. You will be prompted for your
11 | # physical MAC address. Guessing eth0 is no longer relevant in 2017.
12 | #
13 | # Requirements: wget, ntpq
14 | #
15 | # Improvements over other scripts:
16 | # - Not a CGI script
17 | # - Computes the SHA1 hash of bytes, not their hex representation
18 | # - Better text output
19 | #
20 | # References:
21 | #
22 | # RFC 4193 -- Unique Local IPv6 Unicast Addresses
23 | # https://tools.ietf.org/html/rfc4193
24 | #
25 | # Unique local address
26 | # https://en.wikipedia.org/wiki/Unique_local_address
27 |
28 |
29 | function die() {
30 | echo
31 | echo "== Error =="
32 | echo "$@"
33 | exit 1
34 | }
35 |
36 | read -p "MAC address: " mac
37 | mac=$(echo $mac | tr -d :-)
38 | if [ ${#mac} -ne 12 ]; then
39 | die "MAC address \"${mac}\" is invalid"
40 | fi
41 |
42 | echo "For a deterministic calculation, you may enter the ntp clock time."
43 | echo "Leave empty to query an NTP server."
44 | read -p "Clock: " clock
45 | if [ -z "${clock}" ]; then
46 | clock=$(ntpq -c "rv 0 clock" 0.pool.ntp.org | cut -c7-23)
47 | # Input: "clock=dcf4268b.208dd000 Tue, Jun 20 2017 18:56:11.127"
48 | # Output: "dcf4268b.208dd000"
49 | fi
50 | clock=$(tr -d . <<< "${clock}")
51 | if [ "${#clock}" -ne 16 ]; then
52 | die "Time in NTP format is 64 bits, "\
53 | "or 16 characters in hex representation. "\
54 | "You entered: \"${clock}\"."
55 | fi
56 |
57 |
58 | if [ ! -r "oui.txt" ]; then
59 | wget "http://standards-oui.ieee.org/oui.txt"
60 | fi
61 |
62 | # MAC Vendor check
63 | machexvendor=$(tr a-f A-F <<< "${mac:0:6}")
64 | macvendor=$(grep "^$machexvendor" oui.txt | sed -r "s/.*\t([^\r\n]*).*/\1/")
65 | if [ -z "$macvendor" ]; then
66 | die "MAC address \"${mac}\" is not registered to IEEE. "\
67 | "Please use a REAL MAC address."
68 | fi
69 |
70 | # Generate an EUI64 from the MAC address
71 | # as described in RFC 3513
72 | # https://tools.ietf.org/html/rfc3513
73 |
74 | first=`echo $mac | cut -c1-1`
75 | second=`echo $mac | cut -c2-2`
76 | macu=`echo $mac | cut -c3-6`
77 | macl=`echo $mac | cut -c7-12`
78 |
79 | # reversing u/l bit
80 | case $second in
81 | [13579bdf])
82 | die "MAC-address \"${mac}\" is a group MAC address"
83 | ;;
84 | 0)
85 | second_rev=2
86 | ;;
87 | 2)
88 | second_rev=0
89 | ;;
90 | 4)
91 | second_rev=6;
92 | ;;
93 | 6)
94 | second_rev=4;
95 | ;;
96 | 8)
97 | second_rev=a;
98 | ;;
99 | a)
100 | second_rev=8;
101 | ;;
102 | c)
103 | second_rev=e;
104 | ;;
105 | e)
106 | second_rev=c;
107 | ;;
108 | *)
109 | #impossible
110 | die "MAC address \"${mac}\" is registered to the IEEE database, "\
111 | "but the first octet (${first}${second}) is regarded as invalid. "\
112 | "(probably a bug in this script...)"
113 | esac
114 | eui64="${first}${second_rev}${macu}fffe${macl}"
115 |
116 | # Convert from hex string representation to bytes before sha1sum
117 | # https://unix.stackexchange.com/a/82766
118 | globalid=$(echo -ne $(sed "s/../\\x&/g" <<< ${date}${eui64}) | sha1sum | cut -c23-32)
119 | ula=$(echo fd${globalid} | sed "s|\(....\)\(....\)\(....\)|\1:\2:\3::/48|")
120 |
121 | echo
122 | echo "## Inputs ##"
123 | echo "MAC address = ${mac} (${macvendor})"
124 | echo "NTP time = ${clock}"
125 | echo
126 | echo "## Intermediary values ##"
127 | echo "EUI64 address = ${eui64}"
128 | echo
129 | echo "## Generated ULA ##"
130 | echo "${ula}"
131 | echo
132 |
--------------------------------------------------------------------------------
/prior_art/gen-ula.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # ULA Generator
4 | # SUZUKI, Shinsuke
5 | # based on Holger Zuleger's script
6 | # @(#) generate-uniq-local-ipv6-unicast-addr.sh
7 | # (c) Sep 2004 Holger Zuleger
8 | #
9 | # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, and 2002 WIDE Project.
10 | # All rights reserved.
11 | #
12 | # Redistribution and use in source and binary forms, with or without
13 | # modification, are permitted provided that the following conditions
14 | # are met:
15 | # 1. Redistributions of source code must retain the above copyright
16 | # notice, this list of conditions and the following disclaimer.
17 | # 2. Redistributions in binary form must reproduce the above copyright
18 | # notice, this list of conditions and the following disclaimer in the
19 | # documentation and/or other materials provided with the distribution.
20 | # 3. Neither the name of the project nor the names of its contributors
21 | # may be used to endorse or promote products derived from this software
22 | # without specific prior written permission.
23 | #
24 | # THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
25 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 | # ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
28 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 | # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 | # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 | # SUCH DAMAGE.
35 | #
36 | # $Id: gen-ula.cgi,v 1.11 2013/05/20 22:43:57 suz Exp $
37 | #
38 |
39 |
40 | #
41 | #site-specific parameters
42 | #
43 |
44 | #NTP server name
45 | ntpserv="clk.notemachi.wide.ad.jp"
46 |
47 | #ntpdate program
48 | ntpdate=/usr/sbin/ntpdate
49 |
50 | #the caller of this CGI script
51 | url="http://www.kame.net/~suz/gen-ula.html"
52 |
53 | #list of typical bogus lower 24-bits in MAC address
54 | typical_mac_list="010203 000000 000001 000102 123456"
55 |
56 | #SHA hash calculator
57 | sha=/usr/local/bin/sha
58 |
59 | #IEEE OUI Database (available at http::/standards.ieee.org/regauth/oui/oui.txt)
60 | ieeeoui=oui.txt
61 |
62 | #
63 | # main routine
64 | #
65 | #print-out header
66 | echo Content-type: text/html
67 | echo
68 |
69 | cat << EOH
70 |
71 |
72 |
73 | Generated ULA
74 |
75 |
76 |
77 | EOH
78 |
79 | #main routine
80 |
81 | #1. NTP-date
82 | date=`$ntpdate -dq $ntpserv 2> /dev/null |
83 | sed -n 's/^transmit timestamp: *\([^ ]*\) .*/\1/p' |
84 | tr -d "."`
85 |
86 | #2. EUI64
87 | # obtains a MAC address
88 | # sed 's/\(.*\)=\(..:..:..:..:..:..\).*$/\2/' |
89 | mac=`echo $QUERY_STRING | sed 's/%3A/:/g' |
90 | tr '[:lower:]' '[:upper:]' |
91 | sed 's/\(.*\)=\(..:..:..:..:..:..\).*$/\2/'`;
92 | machex=`echo $mac | tr -d ':'`
93 | #length check
94 | len1=`echo $machex | wc -m`
95 | #character check
96 | len2=`echo $machex | tr -d [:xdigit:] | wc -m`
97 | if [ $len1 != 13 -o $len2 != 1 ]; then
98 | echo "Error
"
99 | echo "MAC-address $mac is invalid"
100 | echo "
Please take care of the following points:
101 |
102 | - each octet must be separeted by colon (e.g. 00-01-02-03-04-05 is not permitted)
103 |
- leading 0 of each octet cannot be omitted (e.g. 3:4:5:4:5:9 is not permitted)
104 |
- each octet consists of 0-9 and A-F.
105 |
"
106 | echo "go back to the previous page"
107 | exit
108 | fi
109 |
110 | # MAC Vendor check
111 | machexvendor=`echo $machex | cut -c1-6`
112 | macvendor=`grep "^ $machexvendor" $ieeeoui | cut -c23-`
113 | if [ -z "$macvendor" ]; then
114 | echo "Error
"
115 | echo "MAC-address $mac"
116 | echo "is not registered to IEEE
"
117 | echo "Please use the REAL MAC address
"
118 | echo "go back to the previous page"
119 | exit
120 | fi
121 |
122 | # booby trap:-)
123 | machexid=`echo $machex | cut -c7-12`
124 | for i in $typical_mac_list; do
125 | if [ $machexid = $i ]; then
126 | echo "Error
"
127 | echo "MAC-address $mac"
128 | echo "is a typical non-existing MAC address that is frequently used when a user is reluctant to find his/her own MAC address:-)
"
129 | echo "Please use the REAL MAC address
"
130 | echo "go back to the previous page