diff --git a/pf-framework.subr b/pf-framework.subr new file mode 100644 index 0000000..deb1a9d --- /dev/null +++ b/pf-framework.subr @@ -0,0 +1,69 @@ +_genfile="${route_policy_file}" +if [ -z "${_genfile}" ] +then + _genfile="/dev/fd/1" +fi + +__install_route_policy() +{ + iface=$1;shift 1 + network=$1;shift 1 + table=$1;shift 1 + + echo "match out on ${iface} from !fd00::/8 to ${network} rtable ${table}" >> $1 + echo "match in on ${iface} from ${network} to !fd00::/8 rtable ${table}" >> $1 +} + +__install_route_policy_v4() +{ + iface=$1;shift 1 + network=$1;shift 1 + table=$1;shift 1 + + echo "match out on ${iface} to ${network} rtable ${table}" >> $1 + echo "match in on ${iface} from ${network} rtable ${table}" >> $1 +} + +_install_route_policy() +{ + iface=$1;shift 1 + split=`echo $1 | sed -e 's/->/ /g'`;shift 1 + + __install_route_policy $iface ${split} $* +} + +_install_route_policy_v4() +{ + iface=$1;shift 1 + split=`echo $1 | sed -e 's/->/ /g'`;shift 1 + + __install_route_policy_v4 $iface ${split} $* +} + +install_route_policy() +{ + _install_route_policy internal $* ${_genfile} +} + +install_route_policy_v4() +{ + _install_route_policy_v4 internal $* ${_genfile} +} + + +add_route_policy() +{ + route_policies="${route_policies} $1->$2" +} + +add_route_policy_v4() +{ + route_policies_v4="${route_policies_v4} $1->$2" +} + +clear_all_policies() +{ + echo -n > $_genfile +} + +# vim: ft=sh diff --git a/rc.d/allow_hosts b/rc.d/allow_hosts new file mode 100755 index 0000000..2752871 --- /dev/null +++ b/rc.d/allow_hosts @@ -0,0 +1,49 @@ +#!/bin/sh +# +# $FreeBSD$ +# +# PROVIDE: allow_hosts +# REQUIRE: named +# KEYWORD: shutdown +# + +. /etc/rc.subr + +name="allow_hosts" +desc="Allow hosts by DNS (from local DNS)" + +start_cmd='allow_hosts_start' +stop_cmd='allow_hosts_stop' +rcvar='allow_hosts_enable' + +load_rc_config 'allow_hosts' + +[ -z "$allow_hosts_enable" ] && allow_hosts_enable='NO' +if [ -z "${allow_hosts_rules}" ] +then + echo "Must have a route policy target file" + exit 1 +fi + +. /etc/router-conf/pf-framework.subr + + + +allow_hosts_start() +{ + echo "Running allow hosts" + echo "include \"${allow_hosts_rules}\"" > /etc/router-conf/gen/pf.rules.conf + pfctl -a allow-hosts -f ${allow_hosts_rules} +} + +allow_hosts_stop() +{ +} + + + +################ Epilogue + +run_rc_command "$1" + +# vim: ft=bash diff --git a/rc.d/clear_route_policy b/rc.d/clear_route_policy new file mode 100755 index 0000000..0c52e4c --- /dev/null +++ b/rc.d/clear_route_policy @@ -0,0 +1,54 @@ +#!/bin/sh +# +# $FreeBSD$ +# +# PROVIDE: clear_route_policy +# BEFORE: pf +# KEYWORD: shutdown +# + +. /etc/rc.subr + +name="clear_route_policy" +desc="Policy Based Routing Reset" + +start_cmd='clear_route_policy_start' +stop_cmd='clear_route_policy_stop' +rcvar='route_policy_enable' + +load_rc_config 'route_policy' + +[ -z "$route_policy_enable" ] && route_policy_enable='NO' +if [ -z "${route_policy_file}" ] +then + echo "Must have a route policy target file" + exit 1 +fi + +. /etc/router-conf/pf-framework.subr + + + +clear_route_policy_start() +{ + echo "" >/etc/router-conf/gen/pf.rules.conf + pfctl -a allow-hosts -f /dev/null + clear_all_policies + #pfctl -a route-policies -f ${route_policy_file} +} + +clear_route_policy_stop() +{ + echo "" >/etc/router-conf/gen/pf.rules.conf + pfctl -a allow-hosts -f /dev/null + clear_all_policies + #pfctl -a route-policies -f ${route_policy_file} +} + + + +################ Epilogue + +run_rc_command "$1" + +# vim: ft=bash diff --git a/rc.d/dhcp6c b/rc.d/dhcp6c new file mode 100755 index 0000000..258d4b4 --- /dev/null +++ b/rc.d/dhcp6c @@ -0,0 +1,56 @@ +#!/bin/sh + +# PROVIDE: dhcp6c +# REQUIRE: netif +# BEFORE: NETWORKING +# KEYWORD: shutdown + +# Add the following lines to +# /etc/rc.conf.d/dhcp6c /etc/rc.conf.local or /etc/rc.conf +# to enable this service: +# +# dhcp6c_enable (bool): Set to NO by default. +# Set it to YES to enable dhcp6c. +# dhcp6c_config (path): Set to /usr/local/etc/dhcp6c.conf +# by default. +# dhcp6c_dhcp6cctlkey (path): Set to /usr/local/etc/dhcp6cctlkey +# by default. +# dhcp6c_pidfile (path): Set to /var/run/dhcp6c.pid +# by default. +# dhcp6c_interfaces (NIC list): Not defined by default. +# Set it to the network interface(s) where dhcp6c should work on. +# dhcp6c_flags (additional arguments): Not defined by default. +# + +. /etc/rc.subr + +name="dhcp6c" +rcvar=dhcp6c_enable + +command="/usr/local/sbin/${name}" +start_precmd="${name}_precmd" + +load_rc_config $name + +: ${dhcp6c_enable="NO"} +: ${dhcp6c_config="/usr/local/etc/${name}.conf"} +: ${dhcp6c_dhcp6cctlkey="/usr/local/etc/dhcp6cctlkey"} +: ${dhcp6c_pidfile="/var/run/${name}.pid"} + +required_files="${dhcp6c_config}" +pidfile="${dhcp6c_pidfile}" +command_args="${dhcp6c_args} -c ${dhcp6c_config} -p ${dhcp6c_pidfile} ${dhcp6c_interfaces}" + +dhcp6c_precmd() +{ + if [ -z ${dhcp6c_interfaces} ]; then + warn "dhcp6c_interfaces is not set." + return 1 + fi + if [ ! -s ${dhcp6c_dhcp6cctlkey} ]; then + echo "Creating ${dhcp6c_dhcp6cctlkey}" + (umask 077 ; openssl rand -base64 48 > ${dhcp6c_dhcp6cctlkey}) + fi +} + +run_rc_command "$1" diff --git a/rc.d/fib_setup b/rc.d/fib_setup new file mode 100755 index 0000000..a6a1ec0 --- /dev/null +++ b/rc.d/fib_setup @@ -0,0 +1,45 @@ +#!/bin/sh +# +# $FreeBSD$ +# +# PROVIDE: fib_setup +# BEFORE: sysctl +# + +. /etc/rc.subr + +name="fib_setup" +desc="Calculate the fib count" + +start_cmd='fib_setup_start' +stop_cmd='fib_setup_stop' +rcvar='fib_setup_enable' + +load_rc_config 'fib_setup' + +[ -z "$fib_setup_enable" ] && fib_setup_enable='NO' + +. /etc/router-conf/pf-framework.subr + + +fib_setup_start() +{ + echo "Running fib_setup" + fib_count=$(( ${max_fib} + 1 )) + + cp ${router_conf_dir}/sysctl.conf ${router_conf_dir}/gen/ + echo "net.fibs=${fib_count}" >> ${router_conf_dir}/gen/sysctl.conf +} + +fib_setup_stop() +{ +} + + + +################ Epilogue + +run_rc_command "$1" + +# vim: ft=bash + diff --git a/rc.d/generate_isp_dhcp b/rc.d/generate_isp_dhcp new file mode 100755 index 0000000..ceef9ef --- /dev/null +++ b/rc.d/generate_isp_dhcp @@ -0,0 +1,37 @@ +#!/bin/sh +# +# $FreeBSD$ +# +# PROVIDE: generate_isp_dhcp +# REQUIRE: netif +# BEFORE: dhcp6c +# KEYWORD: shutdown +# + +. /etc/rc.subr + +name='generate_isp_dhcp' + +start_cmd='generate_isp_dhcp_start' +stop_cmd='generate_isp_dhcp_stop' +rcvar='generate_isp_dhcp_enable' + +load_rc_config 'generate_isp_dhcp' + +[ -z "$generate_isp_dhcp_enable" ] && generate_isp_dhcp_enable='YES' + +generate_isp_dhcp_start() +{ + _emit_dhcpv6 + cat ${router_conf_dir}/gen/dhcp6c.*.conf > ${router_conf_dir}/gen/dhcp6c.conf +} + +generate_isp_dhcp_stop() +{ +} + +################ Epilogue + +run_rc_command "$1" + +# vim: ft=bash diff --git a/rc.d/localnet b/rc.d/localnet new file mode 100755 index 0000000..e99c1f8 --- /dev/null +++ b/rc.d/localnet @@ -0,0 +1,142 @@ +#!/bin/sh +# +# $FreeBSD$ +# +# PROVIDE: localnet +# REQUIRE: dhcp6c +# BEFORE: rtadvd named +# KEYWORD: shutdown +# + +# This is a bit hacky, but I think I can live with it for now. +# +# The purpose of this script is to generate various ISP prefix dependent files. +# +# Specifically, the DNS (BIND) acls file for handling various views, a local ISP +# range address for the router itself (on a dedicated loopback device), and attach +# the IMP_NET address for this machine to another loopback device. + +. /etc/rc.subr + +name='localnet' + +extra_commands="rebuild_rtadvd_conf rebuild_zoneinfo" +start_cmd='localnet_start' +stop_cmd='localnet_stop' +rebuild_rtadvd_conf_cmd="localnet_build_rtadv" +rebuild_zoneinfo_cmd="localnet_build_zoneinfo" +rcvar='localnet_enable' + +load_rc_config 'localnet' + +localnet_first_nic="re0.301" + +[ -z "$localnet_enable" ] && localnet_enable='NO' +[ -z "$localnet_zoneinfo_enable" ] && localnet_zoneinfo_enable='NO' + +localnet_build_zoneinfo() +{ + compute_addrs + localnet_build_zoneinfo_impl +} + + +localnet_build_zoneinfo_impl() +{ + if [ $(option_selected localnet_zoneinfo_enable) = "YES" ] + then + build_zoneinfo ${isp_prefix} ${localnet_zoneinfo_subnet} ${router_conf_dir}/namedb/local-machines.defs > ${router_conf_dir}/gen/${localnet_zone_file} + fi +} + +localnet_build_acls() +{ + gen_acls_dir=${router_conf_dir}/gen/namedb + mkdir -p ${gen_acls_dir} + cat ${router_conf_dir}/namedb/acls.template.conf \ + | sed \ + -e "s/@ISP_PREFIX@/${isp_prefix}/g" \ + -e "s/@ULA_PREFIX@/${secret_ip6_net}/g" \ + > ${gen_acls_dir}/acls.conf +} + +localnet_build_rtadv() +{ + gen_rtadv_dir=${router_conf_dir}/gen + rtadvd_conf=${gen_rtadv_dir}/rtadvd.conf + mkdir -p ${gen_rtadv_dir} + _search_list=$( echo ${rtadvd_dns_search_list} | sed -e 's/ */,/g' -e 's/^,//' -e 's/,$//' ) + cat ${router_conf_dir}/rtadvd.template.conf \ + | sed \ + -e "s/@PREF64_PREFIX@/${rtadvd_pref64_prefix}/" \ + -e "s/@DNS_SERVER@/${rtadvd_dns_server}/" \ + -e "s/@DNSSL@/${_search_list}/" \ + > ${rtadvd_conf} + + echo "" >> ${rtadvd_conf} + echo "" >> ${rtadvd_conf} + + for interface in ${rtadvd_interfaces} + do + echo "${interface}:tc=settings" >> ${rtadvd_conf} + done +} + +compute_addrs() { + # todo: Adjust our ipv6 hint... get from a var? + v6addr=$(ifconfig ${localnet_first_nic} | grep "inet6 [23]...:" | head -1 | awk '{print $2}') + echo "V6 addr is: ${v6addr}" + + loop=0 + while [ -z "${v6addr}" -a ${loop} -lt 4 ] + do + sleep 5 + v6addr=$(ifconfig re0.301 | grep "2600:4040:" | head -1 | awk '{print $2}') + echo "V6 addr is: ${v6addr}" + loop=$(( ${loop} + 1 )) + done + + echo "V6 addr is: ${v6addr}" + three_quads=$(echo ${v6addr} | awk -F ':' '{print $1":"$2":"$3}') + echo "First three quads are: ${three_quads}" + last_quad=$(echo ${v6addr} | awk -F ':' '{print $4}') + echo "Last quad is: ${last_quad}" + last_prefix=$(echo ${last_quad} | rev | awk '{print $1"0000"}' | cut -c 3,4 | rev | sed -e 's/^0//') + echo "Last prefix is: ${last_prefix}" + + isp_prefix="${three_quads}:${last_prefix}" + base_addr=" inet6 ${isp_prefix}ff::1" +} + + +localnet_start() { + cp ${router_conf_dir}/resolv.conf.master ${router_conf_dir}/resolv.conf + compute_addrs + ifconfig lo1 create ${base_addr} prefer_source + ifconfig lo3 create inet 198.18.0.1/32 + + # DO NOT USE prefer_source for this address... + # It will cause confusion for the wireguard tunnels underneath... + # It also could cause DNS recursion to fail -- routing as the nested + # connections... + ifconfig lo2 create inet6 2602:f6a8:1::/64 anycast # DO NOT USE prefer_source + ifconfig lo4 create inet 155.103.215.15/32 anycast + + localnet_build_rtadv + localnet_build_acls + localnet_build_zoneinfo_impl +} + +localnet_stop() { + compute_addrs + ifconfig lo0 ${base_addr} delete + + ifconfig lo1 destroy + ifconfig lo2 destroy + ifconfig lo3 destroy + ifconfig lo4 destroy +} + +run_rc_command "$1" + +# vim: ft=bash diff --git a/rc.d/route_policy b/rc.d/route_policy new file mode 100755 index 0000000..57997fe --- /dev/null +++ b/rc.d/route_policy @@ -0,0 +1,92 @@ +#!/bin/sh +# +# $FreeBSD$ +# +# PROVIDE: route_policy +# REQUIRE: wireguard +# KEYWORD: shutdown +# + +# This is a bit hacky, but I think I can live with it for now. + +#hack + +. /etc/rc.subr + +name="route_policy" +desc="Policy Based Routing Installer" + +start_cmd='route_policy_start' +stop_cmd='route_policy_stop' +rcvar='route_policy_enable' + +load_rc_config 'route_policy' + +[ -z "$route_policy_enable" ] && route_policy_enable='NO' +if [ -z "${route_policy_file}" ] +then + echo "Must have a route policy target file" + exit 1 +fi + +. /etc/router-conf/pf-framework.subr + + + + +do_all_routes() +{ + while [ -n "$1" ] + do + install_route_policy $1 + shift 1 + done +} + +do_all_routes_v4() +{ + while [ -n "$1" ] + do + install_route_policy_v4 $1 + shift 1 + done +} + +route_policy_start() +{ + clear_all_policies + echo "# This file is generated." >> ${route_policy_file} + echo "# Do not edit." >> ${route_policy_file} + echo "" >> ${route_policy_file} + + # TODO: Record the policies one-per-line via a helper loop subroutine? + echo "# (Generated with \`${route_policies}\`, at `date`.)" >> ${route_policy_file} + echo "# (Generated with \`${route_policies_v4}\`, at `date`.)" >> ${route_policy_file} + echo "" >> ${route_policy_file} + echo "" >> ${route_policy_file} + + do_all_routes ${route_policies} + do_all_routes_v4 ${route_policies_v4} + + echo "" >> ${route_policy_file} + echo -n "# v" >> ${route_policy_file} + echo "im: ft=pf" >> ${route_policy_file} + + #pfctl -a "route-policies" -f ${route_policy_file} + #pfctl -f ${pf_rules} # <--- Hack? + /etc/rc.d/pf reload # <---- UGLY hack!!? +} + +route_policy_stop() +{ + clear_all_policies +} + + + + +################ Epilogue + +run_rc_command "$1" + +# vim: ft=bash diff --git a/rc.d/tayga b/rc.d/tayga new file mode 100755 index 0000000..69bf9d7 --- /dev/null +++ b/rc.d/tayga @@ -0,0 +1,77 @@ +#!/bin/sh +# +# $FreeBSD$ +# +# PROVIDE: tayga +# REQUIRE: SERVERS +# KEYWORD: shutdown +# + +. /etc/rc.subr + +name='tayga' + +start_cmd='tayga_start' +stop_cmd='tayga_stop' +rcvar='tayga_enable' + +load_rc_config 'tayga' +pidfile="/var/run/${name}.pid" +command="/usr/local/sbin/${name}" + +# Confirm necessary variables are set +check_vars() { + [ -z "$tayga_ipv4_addr" ] && err 3 "Must set tayga_ipv4_addr to the address that the tayga server lives on" + [ -z "$tayga_ipv4_endpoint" ] && err 3 "Must set tayga_ipv4_endpoint to the address that the tunnel lives on" + [ -z "$tayga_ipv4_net" ] && err 3 "Must set tayga_ipv4_net to the network that the tunnel lives on" + [ -z "$tayga_ipv6_endpoint" ] && err 3 "Must set tayga_ipv6_endpoint to the address that the tunnel lives on" + [ -z "$tayga_ipv6_net" ] && err 3 "Must set tayga_ipv6_net to the network that the tunnel provides" +} + +[ -z "$tayga_config" ] && tayga_config="/usr/local/etc/tayga.conf" + +command_args="-p ${pidfile} -c ${tayga_config}" + +[ -z "$tayga_enable" ] && tayga_enable='YES' + +tayga_start() { + check_vars + "$command" $command_args + while ! ifconfig 'nat64'; do sleep 1; done + ifconfig 'nat64' inet "${tayga_ipv4_endpoint}/32" "${tayga_ipv4_addr}" + if [ ! -z "${tayga_group}" ] ; then ifconfig 'nat64' group ${tayga_group} ; fi + ifconfig 'nat64' inet6 "${tayga_ipv6_endpoint}/128" + #echo Add route 4 + route -4 add "${tayga_ipv4_net}" -interface 'nat64' + #echo Add route 6 for endpoint from net + #route -6 add "${tayga_ipv6_endpoint}" -iface 'nat64' #-fib 0-7 + route -6 add "${tayga_ipv6_net}" "${tayga_ipv6_endpoint}" #-fib 0-7 + #echo Add route 6 for endpoint subnet + route -6 add "${tayga_ipv6_endpoint}/64" "${tayga_ipv6_endpoint}" #-fib 0-7 + + for prefix in ${tayga_v4_prefixes} + do + route add ${prefix} ${tayga_ipv4_addr} -fib 0-${max_fib} + done +} + +tayga_stop() { + if [ -n "$rc_pid" ]; then + check_vars + + for prefix in tayga_v4_prefixes + do + route del ${prefix} ${tayga_ipv4_addr} -fib 0-${max_fib} + done + + echo 'stopping tayga' + kill -2 "${rc_pid}" + route -6 del "${tayga_ipv6_net}" -interface 'nat64' + route -4 del "${tayga_ipv4_net}" -interface 'nat64' + ifconfig 'nat64' destroy + else + echo "${name} is not running." + fi +} + +run_rc_command "$1" diff --git a/rc.subr b/rc.subr new file mode 100644 index 0000000..d2fdcb1 --- /dev/null +++ b/rc.subr @@ -0,0 +1,516 @@ +########################################################################## +## +## The rc.router Project +## Copyright (C) 2026 ADAM David Alan Martin +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU Affero General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Affero General Public License for more details. +## +## You should have received a copy of the +## GNU Affero General Public License along with this program. If not, +## see . +## +########################################################################## + + +########################################################### +# Print debugging info, if `debug_conf` is set. +_echo() +{ + if [ "${debug_conf}" = "YES" ] + then + echo 1>&2 $* + fi +} + +########################################################### +# Log warning info. +_warn() +{ + if [ -x /usr/bin/logger ]; then + logger "$0: WARNING: $*" + fi + echo 1>&2 "$0: WARNING: $*" +} + +########################################################### +# Repeat a command for multiple arguments +# +# - First param is the name of the function or binary to repeat. +# - Remaining arguments are each passed to the function. +# +# Example: __repeat touch Hello World +__repeat() +{ + __func=$1;shift 1 + + while [ "$1" != "" ] + do + ${__func} $1 + shift 1 + done +} + +########################################################### +# Create the specified single interface +# +# This adds the interface to the `cloned_interfaces` +# rc.conf variable +__clone_interface() +{ + _echo Adding $1 to cloned interfaces + cloned_interfaces="${cloned_interfaces} $1" + _echo "Cloned interfaces are now \"${cloned_interfaces}\"" +} + +########################################################### +# Create the specified list of interfaces. +clone_interfaces() +{ + __repeat __clone_interface $* +} + +########################################################### +# Create the specified interface +# (optionally create more interfaces) +clone_interface() +{ + clone_interfaces $* +} + +__add_wireguard_interface() +{ + _echo "Adding $1 to ${wireguard_interfaces}" + wireguard_enable="YES" + wireguard_interfaces="${wireguard_interfaces} $1" +} + +add_wireguard_interfaces() +{ + __repeat __add_wireguard_interface $* +} + +add_wireguard_interface() +{ + add_wireguard_interfaces $* +} + +add_wireguard_route() +{ + add_route_policy $1 $2 + add_wireguard_interface wg$2 +} + +add_wireguard_route_v4() +{ + add_route_policy_v4 $1 $2 + # Assuming v6 did this, for now... + #add_wireguard_interface wg$2 +} + +compute_56_net() +{ + _echo Running 56 > /dev/fd/2 + _echo 'Computing for `'$1'`' > /dev/fd/2 + echo $1 | sha1 | cut -c 1-12 | sed -e 's/\([0-9a-f][0-9a-f]\)/\1:/g' | awk -F: '{print "fd"$1":"$2$3":"$4$5":"$6}' +} + +compute_48_net() +{ + _echo Running 48 > /dev/fd/2 + _echo 'Computing for `'$1'`' > /dev/fd/2 + echo $1 | sha1 | cut -c 1-10 | sed -e 's/\([0-9a-f][0-9a-f]\)/\1:/g' | awk -F: '{print "fd"$1":"$2$3":"$4$5":}' +} + +########################################################### +# Compute the ULA prefix for the specified subnet size +# using the second argument (string) as a seed. +# +# Note: Only `/56` and `/48` ULA prefixes are supported at +# this time. +compute_net() { + _echo 'Computing for `'$2'`' > /dev/fd/2 + case $1 in + 56) + compute_56_net "$2" + ;; + + 48) + compute_48_net "$2" + ;; + esac +} + +compute_v4_net() +{ + _prefix_name=v4_net_${1} + _prefix=\${${_prefix_name}} + _subnet=$2 + echo "${_prefix}.${_subnet}.1/24" +} + +compute_v6_net() +{ + _subnet=$2 + _prefix=$1 + echo "${_prefix}${_subnet}::1" +} + +_compute_nets() +{ + _card=$1 + shift 1 + _vlan=$1 + shift 1 + + _base=$((${_vlan}%10)) + _net=$((${_vlan}/100)) + _subnet=${_net}${_base} + _extra_address="" + + if [ -z "${1}" ] + then + #echo "Error in configuration: No network class given" + #exit 1 + fi + + _class=$1 + shift 1 + + _priv="YES" + while true + do + case ${1} in + "no_ula") + _priv="NO" + ;; + + "no_isp") + _isp="" + ;; + + isp=*) + _isp=`echo ${1} | sed -e 's/isp=//'` + ;; + + *) + break + ;; + esac + + shift 1 + done + + while [ -n "${1}" ] + do + _extra_address="${_extra_address} $1" + shift 1 + done +} + +_add_vlan() +{ + _card=$1 + _vlan=$2 + _vlans_var=vlans_${_card} + eval _vlans="\${${_vlans_var}}" + + _echo "XXX ${_vlans} XXX" + _echo "QQQ ${_vlans} QQQ" | grep ${_vlan} + _qres=$? + _echo $_qres + echo "${_vlans}" | grep ${_vlan} > /dev/null + _res=$? + _echo $_res + + if [ 0 -ne $_res ] + then + _echo vlans_${_card}="\${vlans_${_card}} ${_vlan}" + eval vlans_${_card}=\"\${vlans_${_card}} ${_vlan}\" + else + _echo "Not adding vlan ${_vlan} to card ${_card}" + fi +} + +_add_rtadv() +{ + _card=$1 + _vlan=$2 + + _subcard="${_card}.${_vlan}" + + _echo "XXX ${rtadvd_interfaces} XXX" + _echo "QQQ ${rtadvd_interfaces} QQQ" | grep ${_subcard} + _qres=$? + _echo $_qres + echo "${rtadvd_interfaces}" | grep ${_subcard} > /dev/null + _res=$? + _echo $_res + + if [ 0 -ne $_res ] + then + _echo rtadvd_interfaces="${rtadvd_interfaces} ${_subcard}" + rtadvd_interfaces="${rtadvd_interfaces} ${_subcard}" + else + _echo "Not adding subcard ${_subcard} to ipv6 rtadvd list: ${rtadvd_interfaces}" + fi +} + +_add_dhcpv6() +{ + _iface=${1} + _isp=${2} + if [ -z "${_isp}" ] + then + _isp=${default_isp} + fi + + eval dhcpv6_${_isp}_list=\"\${dhcpv6_${_isp}_list} ${_iface}\" +} + +add_dhcpv6() +{ + _iface=${1} + _sla=${2} + _isp=${3} + if [ -z "${_isp}" ] + then + _isp=${default_isp} + fi + + eval dhcpv6_${_isp}_supplement_list=\"\${dhcpv6_${_isp}_supplement_list} ${_iface}/${_sla}\" +} + +_emit_dhcpv6_for_iface() +{ + _iface=${1} + _sla=${2} + echo " prefix-interface ${_iface}" >> ${_dhcp_file} + echo " {" >> ${_dhcp_file} + echo " sla-id ${_sla};" >> ${_dhcp_file} + echo " sla-len $((64 - ${_prefix_len}));" >> ${_dhcp_file} + echo " };" >> ${_dhcp_file} + echo "" >> ${_dhcp_file} +} + +_emit_dhcpv6_for_isp() +{ + _isp=${1} + eval _interface=\"\${dhcp_interface_${_isp}}\" + _n=${2} + eval _prefix_len=\"\${dhcp_prefix_${_isp}}\" + mkdir -p ${router_conf_dir}/gen + _dhcp_file=${router_conf_dir}/gen/dhcp6c.${_isp}.conf + eval _isp_list=\${dhcpv6_${_isp}_list} + eval _isp_supplement_list=\${dhcpv6_${_isp}_supplement_list} + + _echo "Building DHCP info for ${_isp} (interfaces: ${_isp_list})" + + echo "" > ${_dhcp_file} + echo "id-assoc pd $_n" >> ${_dhcp_file} + echo "{" >> ${_dhcp_file} + echo " prefix ::/${_prefix_len} infinity;" >> ${_dhcp_file} + + + for _iface_desc in ${_isp_supplement_list} + do + _iface=`echo ${_iface_desc} | sed -e 's;/.*$;;'` + _sla=`echo ${_iface_desc} | sed -e 's;^.*/;;'` + _emit_dhcpv6_for_iface ${_iface} ${_sla} + done + for _iface in ${_isp_list} + do + _vlan=`echo ${_iface} | sed -e 's/^.*\.//'` + _num=`echo ${_vlan} | sed -e 's/\([0-9]\)0\([0-9]\)/\1\2/'` + _vlan_sla=`printf "%d" 0x${_num}` + _emit_dhcpv6_for_iface ${_iface} ${_vlan_sla} + done + echo "};" >> ${_dhcp_file} + + echo "" >> ${_dhcp_file} + echo "interface ${_interface} {" >> ${_dhcp_file} + echo " send ia-pd ${_n};" >> ${_dhcp_file} + echo "};" >> ${_dhcp_file} +} + +_emit_dhcpv6() +{ + _n=0 + for _isp in ${dhcp_isps} + do + _emit_dhcpv6_for_isp $_isp ${_n} + _n=$((${_n}+1)) + done + +} + +add_v4_net() +{ + _compute_nets $* + _add_vlan $_card $_vlan + + _class_group="" + if [ ! -z "${_class}" ] + then + _class_group="group ${_class}" + fi + eval ifconfig_${_card}_${_vlan}=\"$(compute_v4_net $_card $_subnet) group internal ${_class_group}\" + eval dhcpd_ifaces=\"${dhcpd_ifaces} ${_card}.${_vlan}\" +} + +_add_v6_prefixes() +{ + _next_alias=$1 + shift 1 + + while [ -n "${1}" ] + do + eval ifconfig_${_card}_${_vlan}_alias${_next_alias}=\"inet6 $1/64\" + shift 1 + _next_alias=`expr $_next_alias + 1` + done +} + +########################################################### +# Create a VLAN on the specified network interface with +# the specififed VLAN-ID, interface group, and optional +# address parameters. +# +# @1 - The underlying network interface to use. +# @2 - The VLAN-ID of the VLAN to create. +# @3 - The network interface group to put this new +# VLAN into. (Uses: `ifconfig @dev group @3`) +# @* - Additional networks to join (or adjustments +# to make). +# - `no_ula` Make this VLAN not use a ULA. +# - `no_isp` Make this VLAN not use any ISP prefixes +# (from DHCPv6) +# - `isp:${isp}` Put this VLAN under the specified ISP +# - `2001:db8:42::` Make this VLAN have `2001:db8:42::/64` +# as a prefix. +# +add_v6_net() +{ + _isp=${default_isp} + _compute_nets $* + _add_vlan $_card $_vlan + _add_rtadv $_card $_vlan + + _class_group="" + if [ ! -z "${_class}" ] + then + _class_group="group ${_class}" + fi + + eval ifconfig_${_card}_${_vlan}_ipv6=\"inet6 fe80::1/64 group internal ${_class_group}\" + + _next_alias=0 + + if [ "${_priv}" = "YES" ] + then + eval ifconfig_${_card}_${_vlan}_alias${_next_alias}=\"inet6 $(compute_v6_net ${secret_ip6_net} ${_subnet})/64\" + _next_alias=1 # UGLY HACK!!! Does BASH increment work in BSD's sh? + fi + + if [ -n "${_isp}" ] + then + _add_dhcpv6 $_card.$_vlan ${_isp} + fi + + _add_v6_prefixes ${_next_alias} ${_extra_address} +} + +add_net() +{ + add_v4_net $* + add_v6_net $* +} + +option_selected() +{ + eval _value=\$${1} + _echo "option_selected: $1 is set to $_value." + case $_value in + + # "yes", "true", "on", or "1" + [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) + echo "YES" + ;; + + # "no", "false", "off", or "0" + [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) + echo "NO" + ;; + *) + _warn "\$${1} is not set properly - see rc.conf(5)." + echo "FAILED" + ;; + esac +} + +build_zoneinfo_for_host() +{ + _ISP_PREFIX=${1};shift 1 + _MAIN_SUBNET=${1};shift 1 + _host=$( echo ${1} | sed -e 's/=.*$//' ) + # Not really the MAC, but maybe that's the right way? + # For now it's host=SUFFIX + _MAC=$( echo ${1} | sed -e 's/^.*=//' ) + #echo "Host: ${_host} --- MAC: ${_MAC}" + echo "${_host}" IN AAAA ${_ISP_PREFIX}${_MAIN_SUBNET}:${_MAC} +} + +build_zoneinfo() +{ + _prefix=${1} ; shift 1 + _subnet=${1} ; shift 1 + echo '$TTL 1h30m' + + echo '@ IN SOA '"${localnet_zoneinfo_master_nameserver}"'. '"${localnet_zoneinfo_email}"'. (' + date +'%s' + + echo 7200 + echo 1200 + echo 7200 + echo 5400 + + echo ')' + + echo '$ORIGIN '"${localnet_zoneinfo_domain}"'.' + + for nameserver in ${localnet_zoneinfo_nameservers} + do + echo '@ IN NS '"${nameserver}"'.' + done + + for _hostline in $(cat ${1}) + do + #echo ${_prefix} ${_subnet} ${_hostline} + case "${_hostline}" in + "#"*) + continue + ;; + esac + + build_zoneinfo_for_host ${_prefix} ${_subnet} ${_hostline} + done +} + + +# Now we compute a prefix from the hash of the network name. +# This lets us be deterministic, yet still know what our +# net name is. +# +#compute_net 56 "${ip6_net_name}" +secret_ip6_net=$(compute_net ${ip6_net_size} "${ip6_net_name}") + +. ${router_conf_dir}/pf-framework.subr + +# vim: ft=bash