profiles/ds-lite: Connect to Netcologne with PPP DS-Lite
This commit is contained in:
12
pkgs/ds-lite-dhcpcd-hook/default.nix
Normal file
12
pkgs/ds-lite-dhcpcd-hook/default.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
pkgs.writeShellApplication {
|
||||
name = "ds-lite-dhcpcd-hook";
|
||||
text = builtins.readFile ./ds-lite-dhcpcd-hook.sh;
|
||||
runtimeInputs = with pkgs; [
|
||||
iproute2
|
||||
jq
|
||||
dig
|
||||
gawk
|
||||
];
|
||||
}
|
||||
102
pkgs/ds-lite-dhcpcd-hook/ds-lite-dhcpcd-hook.sh
Normal file
102
pkgs/ds-lite-dhcpcd-hook/ds-lite-dhcpcd-hook.sh
Normal file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Setting up required environment variables
|
||||
# shellcheck disable=SC2154
|
||||
WAN_INTERFACE_NAME="${DS_LITE_WAN_INTERFACE_NAME}"
|
||||
# shellcheck disable=SC2154
|
||||
TUNNEL_INTERFACE_NAME="${DS_LITE_TUNNEL_INTERFACE_NAME}"
|
||||
|
||||
log_dhcp () {
|
||||
echo "<ds-lite-dhcpcd-hook> ${WAN_INTERFACE_NAME}: $1"
|
||||
}
|
||||
|
||||
log_tunnel () {
|
||||
echo "<ds-lite-dhcpcd-hook> ${WAN_INTERFACE_NAME} (${TUNNEL_INTERFACE_NAME}): $1"
|
||||
}
|
||||
|
||||
# Check if the event calling this hook is for the wan interface
|
||||
# exit immediately if not
|
||||
# shellcheck disable=SC2154
|
||||
if [[ "$interface" != "$WAN_INTERFACE_NAME" ]]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Make sure the event calling this hook carries the environment variable
|
||||
# in question. The environment variable is not provided with every call
|
||||
# and we just want to exit if it is not provided
|
||||
# shellcheck disable=SC2154
|
||||
if [[ ! -v new_dhcp6_aftr_name ]]; then
|
||||
# Variable is not set
|
||||
exit
|
||||
fi
|
||||
# shellcheck disable=SC2154
|
||||
if [[ -z "${new_dhcp6_aftr_name}" ]]; then
|
||||
# Variable is empty, can't do anything
|
||||
exit
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
AFTR_NAME="$new_dhcp6_aftr_name"
|
||||
|
||||
log_dhcp "Received new AFTR_NAME ${AFTR_NAME}"
|
||||
|
||||
# Make sure we have a nameserver to resolve aftr name against
|
||||
# shellcheck disable=SC2154
|
||||
if [[ ! -v new_dhcp6_name_servers ]]; then
|
||||
# Variable is not set
|
||||
exit
|
||||
fi
|
||||
# shellcheck disable=SC2154
|
||||
if [[ -z "${new_dhcp6_name_servers}" ]]; then
|
||||
# Variable is empty, can't do anything
|
||||
exit
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
NAME_SERVERS="$new_dhcp6_name_servers"
|
||||
|
||||
log_dhcp "Received new NAME_SERVERS ${NAME_SERVERS}"
|
||||
|
||||
# Select first nameserver
|
||||
NAME_SERVER="$(echo "${NAME_SERVERS}" | awk '{print $1;}')"
|
||||
|
||||
log_dhcp "Selected NAME_SERVER ${NAME_SERVER}"
|
||||
|
||||
# Figure out a usable IPv6 address on the wan interface, to origin our DNS requests and tunnel
|
||||
WAN_INTERFACE_ADDRESS="$(ip --json address show "${WAN_INTERFACE_NAME}" | jq -r '.[0].addr_info[] | select(.family == "inet6" and .scope == "global" and .mngtmpaddr == true) | .local')"
|
||||
|
||||
log_dhcp "Using WAN_INTERFACE_ADDRESS ${WAN_INTERFACE_ADDRESS}"
|
||||
|
||||
AFTR_ADDRESS="$(dig "@${NAME_SERVER}" -b "${WAN_INTERFACE_ADDRESS}" AAAA "${AFTR_NAME}" +short | head -1)"
|
||||
|
||||
log_dhcp "Resolved AFTR_NAME ${AFTR_NAME} to ${AFTR_ADDRESS}"
|
||||
|
||||
# Check if there is already a tunnel interface
|
||||
if TUNNEL_INTERFACE_CONFIG="$(ip --json link show "${TUNNEL_INTERFACE_NAME}")"; then
|
||||
TUNNEL_INTERFACE_OPERSTATE="$(echo "${TUNNEL_INTERFACE_CONFIG}" | jq -r '.[0].operstate')"
|
||||
TUNNEL_INTERFACE_ORIGIN_ADDRESS="$(echo "${TUNNEL_INTERFACE_CONFIG}" | jq -r '.[0].address')"
|
||||
TUNNEL_INTERFACE_REMOTE_ADDRESS="$(echo "${TUNNEL_INTERFACE_CONFIG}" | jq -r '.[0].broadcast')"
|
||||
|
||||
# Reconfigure tunnel interface, if not already in state we want
|
||||
if [[ "${TUNNEL_INTERFACE_ORIGIN_ADDRESS}" != "${WAN_INTERFACE_ADDRESS}" || "${TUNNEL_INTERFACE_REMOTE_ADDRESS}" != "${AFTR_ADDRESS}" || "${TUNNEL_INTERFACE_OPERSTATE}" != "UNKNOWN" ]]; then
|
||||
log_tunnel "Bad configuration, fixing tunnel parameter"
|
||||
|
||||
ip tunnel change "${TUNNEL_INTERFACE_NAME}" mode ipip6 local "${WAN_INTERFACE_ADDRESS}" remote "${AFTR_ADDRESS}"
|
||||
ip link set "$TUNNEL_INTERFACE_NAME" up
|
||||
else
|
||||
log_tunnel "Tunnel already configured"
|
||||
fi
|
||||
else
|
||||
log_tunnel "Setting up DS-Lite tunnel"
|
||||
|
||||
ip tunnel add "${TUNNEL_INTERFACE_NAME}" mode ipip6 local "${WAN_INTERFACE_ADDRESS}" remote "${AFTR_ADDRESS}"
|
||||
ip link set "$TUNNEL_INTERFACE_NAME" up
|
||||
fi
|
||||
|
||||
log_tunnel "Setting default route"
|
||||
|
||||
ip route replace default dev "${TUNNEL_INTERFACE_NAME}"
|
||||
|
||||
log_tunnel "Tunnel setup finished"
|
||||
Reference in New Issue
Block a user