#!/usr/bin/env bash set -eu has() { command -v "$1" >/dev/null 2>&1 } die() { echo $1 &>2 exit 1 } set_mac() { local interface=$1 local mac_address=$2 if has ifconfig; then current_mac=$(ifconfig "$interface" | awk '/ether/ {print $2}') if [[ "${current_mac,,}" == "${mac_address,,}" ]]; then return fi ifconfig "$interface" down if [[ "$OSTYPE" == "linux-gnu" ]]; then ifconfig "$interface" hw ether "$mac_address" else ifconfig "$interface" ether "$mac_address" fi ifconfig "$interface" up elif has ip; then ip link set dev "$interface" down ip link set dev "$interface" address "$mac_address" ip link set dev "$interface" up else die "no suitable program found to configure the network interface, need iproute2 or ifconfig" fi } mask2cidr() { local netmask=$1 local nbits=0 IFS=. for dec in "$netmask"; do case $dec in 255) let nbits+=8;; 254) let nbits+=7;; 252) let nbits+=6;; 248) let nbits+=5;; 240) let nbits+=4;; 224) let nbits+=3;; 192) let nbits+=2;; 128) let nbits+=1;; 0);; *) die "Error: $dec is not recognised" esac done echo "$nbits" } set_ip() { local interface=$1 local ip=$2 local netmask=$3 if has ifconfig; then ifconfig "$interface" "$ip" netmask "$netmask" elif has ip; then ip addr add "$ip" dev "$interface" else die "no suitable program found to set ip address, need iproute2 or ifconfig" fi } start_dhclient() { local interface=$1 if [[ "$OSTYPE" == "linux-gnu" ]]; then dhclient -x dhclient -nw "$interface" elif [[ "$OSTYPE" == "freebsd"* ]]; then dhclient -b "$interface" else nohup setsid dhclient "$interface" >/dev/null 2>&1 fi } start_dhcp() { local interface=$1 if has dhcpcd; then dhcpcd -b -n "$interface" elif has dhclient; then start_dhclient "$interface" elif [[ "$OSTYPE" == "darwin"* ]]; then # TODO untested ipconfig set "$interface" DHCP else die "no suitable dhcp program found, need dhcpcd or dhclient" fi } disable_ipv6_privacy() { local interface=$1 if [[ "$OSTYPE" == "linux-gnu" ]]; then sysctl -w "net.ipv6.conf.${interface}.use_tempaddr=0" elif [[ "$OSTYPE" == "openbsd"* ]]; then ifconfig "${interface}" -autoconfprivacy elif has sysctl; then sysctl -w net.inet6.ip6.use_tempaddr=0 fi } [ -z "${INTERFACE:-}" ] && die "no INTERFACE environment variable set" DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) MAC_ADDRESS_FILE="${DIR}/tinc-macaddr" LOCAL_HOOK_FILE="${DIR}/tinc-up.local" TINCRC="${DIR}/tincrc" MAC_ADDRESS="" SUBNET="" DHCP="yes" IPV6_PRIVACY="yes" source "${TINCRC}" || true if [ -z "$MAC_ADDRESS" ]; then echo "${MAC_ADDRESS_FILE} does not exists. Generate it with ./tinc-generate-mac..." "$DIR/tinc-generate-mac" source "$TINCRC" fi set_mac "$INTERFACE" "$MAC_ADDRESS" if [ -n "$SUBNET" ]; then IFS=' ' read ip netmask <<< "$SUBNET" [ -z "$ip" ] && die "no ip set in SUBNET" [ -z "$netmask" ] && die "no netmask set in SUBNET" set_ip "$INTERFACE" "$ip" "$netmask" fi if [ "${DHCP,,}" = "yes" ]; then start_dhcp "$INTERFACE" fi if [[ "${IPV6_PRIVACY,,}" != "yes" ]]; then disable_ipv6_privacy "$INTERFACE" fi [ -x "${DIR}/tinc-up.local" ] && "${DIR}/tinc-up.local" || true