Skip to content

Instantly share code, notes, and snippets.

@se35710
Last active November 16, 2023 15:52
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save se35710/6fe9512301781dd12c42da7dc6749ed3 to your computer and use it in GitHub Desktop.
Save se35710/6fe9512301781dd12c42da7dc6749ed3 to your computer and use it in GitHub Desktop.
Script that generates a unique local address (ULA) with a /48 prefix using a Pseudo-Random Global ID Algorithm from RFC 4193
#!/bin/bash
# The script generates a unique local address (ULA) with a /48 prefix
# using a Pseudo-Random Global ID Algorithm from RFC 4193
PATH=/usr/local/bin:/bin:/usr/bin:/usr/sbin:/sbin
DEBUG=0
log () {
if [ ! -z "${DEBUG}" ] && [ "${DEBUG}" == "1" ]; then
echo "$1" >&2
fi
}
INTERFACE=$1
if [ -z "${INTERFACE}" ]; then
echo "Usage: ${0} interface"
exit 1
fi
if [ ! -f "/sys/class/net/${INTERFACE}/address" ]; then
echo "Interface ${INTERFACE} not found!"
exit 1
fi
for CMD in date sha1sum sed cut; do
if hash "${CMD}" 2>/dev/null; then
eval "${CMD^^}"='$(command -v ${CMD})'
log "Command ${CMD} found!"
else
echo "${CMD} not found!"
exit 1
fi
done
# The algorithm described below is intended to be used for locally
# assigned Global IDs. In each case the resulting global ID will be
# used in the appropriate prefix as defined in RFC 4193 Section 3.2.
# 1) Obtain the current time of day in 64-bit NTP format (RFC 1305).
NTPDATE=$(printf "%08x%08x\n" $(($(${DATE} +%s) + 2208988800)) $(${DATE} +%N | ${SED} "s/0*//"))
log "64-bit NTP format: ${NTPDATE}"
# 2) Obtain an EUI-64 identifier from the system running this
# algorithm. If an EUI-64 does not exist, one can be created from
# a 48-bit MAC address as specified in RFC 3513. If an EUI-64
# cannot be obtained or created, a suitably unique identifier,
# local to the node, should be used (e.g., system serial number).
IFS=':'; set $(</sys/class/net/${INTERFACE}/address); unset IFS
EUI64=$(printf "fe80%x%x%x%x%x" 0x$(( 0x${1} ^ 0x02 )) 0x${2} 0x${3}ff 0xfe${4} 0x${5}${6})
log "EUI-64: ${EUI64}"
# 3) Concatenate the time of day with the system-specific identifier
# in order to create a key.
CONCAT="${NTPDATE}${EUI64}"
log "Concatenated: ${CONCAT}"
# 4) Compute an SHA-1 digest on the key as specified in RFC 3174;
# the resulting value is 160 bits.
DIGEST=$(echo ${CONCAT} | ${SHA1SUM} | ${CUT} -c1-40)
log "SHA-1 digest: ${DIGEST}"
# 5) Use the least significant 40 bits as the Global ID.
GLOBALID=$(echo ${DIGEST} | ${CUT} -c31-40)
log "Global ID: ${GLOBALID}"
# 6) Concatenate FC00::/7, the L bit set to 1, and the 40-bit Global
# ID to create a Local IPv6 address prefix.
IPV6=$(echo fd${GLOBALID} | ${SED} "s|\(....\)\(....\)\(....\)|\1:\2:\3::/48|" | ${SED} "s/:0*/:/g")
log "IPv6: ${IPV6}"
echo ${IPV6}
@rdempseyidb
Copy link

Line 51 should be:
EUI64=$(printf "fe80%x%x%x%x%x" $(( 0x${1} ^ 0x02 )) 0x${2} 0x${3}ff 0xfe${4} 0x${5}${6})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment