#!/bin/sh
# Give specific interfaces unique ipv4 & ipv6 link local address

RETRIES=10
TESTS=2

mac=$(cat /sys/class/net/${DEVICE}/address)
if [ "$mac" = "" ]; then
    if [ "${INTERFACE:0:2}" = "wg" ]; then
        # For tunnels, use the interface name (which is based on a public key) to generate a mac. We try to keep the mac constant if we can.
        mac=$( echo ${INTERFACE} | awk '{
            for (i = 4; i <= 11; i++) b[i % 4] += index("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", substr($0, i, 1))
            printf "02:00:%02x:%02x:%02x:%02x\n", b[1] % 256, b[2] % 256, b[3] % 256, b[0] % 256
            }' )
    else
        mac=$( printf '%02x:%02x:%02x:%02x:%02x:%02x\n' \
            $((RANDOM % 256 & 0xFE | 0x02)) $((RANDOM % 256)) $((RANDOM % 256)) \
            $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) )
    fi
fi

if "${ACTION}" = "ifup"; then
    # IPv4
    case "${INTERFACE}" in
        wifi*|dtdlink|fast|wg*|xlink*)
            if ! ip -4 -o addr show dev ${DEVICE} scope link | grep -q "inet "; then
                n=0
                IP=$(printf '169.254.%d.%d' 0x$(echo $mac | cut -d: -f5) 0x$(echo $mac | cut -d: -f6))
                while [ ${n} -lt ${RETRIES} ]; do
                    if ! ip -4 -o addr show | grep -qw ${IP} && arping -q -c ${TESTS} -D -I ${DEVICE} ${IP}; then
                        ip -4 addr add ${IP}/16 dev ${DEVICE} brd + scope link
                        break
                    fi
                    n=$((n+1))
                    IP=$(printf 169.254.$(((${RANDOM} % 254) + 1)).$((${RANDOM} % 256)))
                done
            fi
            ;;
        *)
            ;;
    esac
    # IPv6
    case "${INTERFACE}" in
        wg*|xlink*)
            if ! ip -6 -o addr show dev ${DEVICE} scope link | grep -q "inet6 fe80:"; then
                IP=$(printf "fe80::%02x%s:%sff:fe%s:%s%s" $(( 0x${mac%%:*} ^ 2 )) $(echo "$mac" | cut -d: -f2) $(echo "$mac" | cut -d: -f3) $(echo "$mac" | cut -d: -f4) $(echo "$mac" | cut -d: -f5) $(echo "$mac" | cut -d: -f6))
                if ip -6 -o addr show | grep -qw ${IP}; then
                    IP=$(printf "fe80::%04x:%04x:%04x:%04x" ${RANDOM} ${RANDOM} ${RANDOM} ${RANDOM})
                fi
                ip -6 addr add ${IP}/64 dev ${DEVICE} scope link 2>/dev/null
            fi
            ;;
        *)
            ;;
    esac
fi
