1df930be7Sderaadt#!/bin/sh - 2df930be7Sderaadt# 3*4f9a4669Sderaadt# $OpenBSD: netstart,v 1.208 2020/11/29 20:14:06 deraadt Exp $ 45116749bSrpe 55116749bSrpe# Turn off Strict Bourne shell mode. 65116749bSrpeset +o sh 78fc5e153Smillert 82511c2f6Srpe# Show usage of the netstart script and exit. 92511c2f6Srpeusage() { 102511c2f6Srpe print -u2 "usage: ${0##*/} [[-n] interface ...]" 112511c2f6Srpe exit 1 122511c2f6Srpe} 132511c2f6Srpe 149ed80bb0Skn# Echo file $1 to stdout. Skip comment lines. Strip leading and trailing 15952fbff6Srpe# whitespace if IFS is set. 16e57a083bSrpe# Usage: stripcom /path/to/file 178fc5e153Smillertstripcom() { 18e57a083bSrpe local _file=$1 _line 19e57a083bSrpe 20e57a083bSrpe [[ -f $_file ]] || return 21e57a083bSrpe 22e57a083bSrpe while read _line; do 23e57a083bSrpe [[ -n ${_line%%#*} ]] && print -r -- "$_line" 24e57a083bSrpe done <$_file 258fc5e153Smillert} 2604e0ac27Smillert 278222f376Srpe# Parse and "unpack" a hostname.if(5) line given as positional parameters. 288222f376Srpe# Fill the _cmds array with the resulting interface configuration commands. 298222f376Srpeparse_hn_line() { 308222f376Srpe local _af=0 _name=1 _mask=2 _bc=3 _prefix=2 _c _cmd _prev _daddr 318222f376Srpe set -A _c -- "$@" 328222f376Srpe set -o noglob 338222f376Srpe 348222f376Srpe case ${_c[_af]} in 358222f376Srpe ''|*([[:blank:]])'#'*) 368222f376Srpe return 378222f376Srpe ;; 388222f376Srpe inet) ((${#_c[*]} > 1)) || return 398222f376Srpe [[ ${_c[_name]} == alias ]] && _mask=3 _bc=4 408222f376Srpe [[ -n ${_c[_mask]} ]] && _c[_mask]="netmask ${_c[_mask]}" 418222f376Srpe if [[ -n ${_c[_bc]} ]]; then 428222f376Srpe _c[_bc]="broadcast ${_c[_bc]}" 438222f376Srpe [[ ${_c[_bc]} == *NONE ]] && _c[_bc]= 448222f376Srpe fi 458222f376Srpe _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}" 468222f376Srpe ;; 478222f376Srpe inet6) ((${#_c[*]} > 1)) || return 488222f376Srpe if [[ ${_c[_name]} == autoconf ]]; then 498222f376Srpe _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}" 500113d951Srpe V6_AUTOCONF=true 518222f376Srpe return 528222f376Srpe fi 538222f376Srpe [[ ${_c[_name]} == alias ]] && _prefix=3 548222f376Srpe [[ -n ${_c[_prefix]} ]] && _c[_prefix]="prefixlen ${_c[_prefix]}" 558222f376Srpe _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}" 568222f376Srpe ;; 578222f376Srpe dest) ((${#_c[*]} == 2)) && _daddr=${_c[1]} || return 588222f376Srpe _prev=$((${#_cmds[*]} - 1)) 598222f376Srpe ((_prev >= 0)) || return 608222f376Srpe set -A _c -- ${_cmds[_prev]} 618222f376Srpe _name=3 628222f376Srpe [[ ${_c[_name]} == alias ]] && _name=4 638222f376Srpe _c[_name]="${_c[_name]} $_daddr" 648222f376Srpe _cmds[$_prev]="${_c[@]}" 658222f376Srpe ;; 668222f376Srpe dhcp) _c[0]= 678c1551d3Skrw _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]} up;dhclient $_if" 680113d951Srpe V4_DHCPCONF=true 698222f376Srpe ;; 708222f376Srpe '!'*) _cmd=$(print -- "${_c[@]}" | sed 's/\$if/'$_if'/g') 718222f376Srpe _cmds[${#_cmds[*]}]="${_cmd#!}" 728222f376Srpe ;; 738222f376Srpe *) _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}" 748222f376Srpe ;; 758222f376Srpe esac 768222f376Srpe unset _c 7779699d09Srpe set +o noglob 788222f376Srpe} 798222f376Srpe 80d7d55851Srpe# Create interface $1 if it does not yet exist. 8180771ddaSrpe# Usage: ifcreate if1 82b6107460Sdlgifcreate() { 83b6107460Sdlg local _if=$1 84b6107460Sdlg 85d7d55851Srpe { ifconfig $_if || ifconfig $_if create; } >/dev/null 2>&1 86b6107460Sdlg} 87b6107460Sdlg 88d7d55851Srpe# Create interfaces for network pseudo-devices referred to by hostname.if files. 8980771ddaSrpe# Usage: vifscreate 90b6107460Sdlgvifscreate() { 91d7d55851Srpe local _vif _hn _if 92b6107460Sdlg 93d7d55851Srpe for _vif in $(ifconfig -C); do 94375c217eSrpe for _hn in /etc/hostname.${_vif}+([[:digit:]]); do 95b6107460Sdlg [[ -f $_hn ]] || continue 96b6107460Sdlg _if=${_hn#/etc/hostname.} 97b6107460Sdlg 98375c217eSrpe if ! ifcreate $_if; then 997f358361Srpe print -u2 "${0##*/}: create for '$_if' failed." 100375c217eSrpe fi 101b6107460Sdlg done 102b6107460Sdlg done 103b6107460Sdlg} 104b6107460Sdlg 105e57a083bSrpe# Start a single interface. 106e57a083bSrpe# Usage: ifstart if1 107dfc209d0Smiodifstart() { 10878b420f3Stb local _if=$1 _hn=/etc/hostname.$1 _cmds _i=0 _line _stat 1098222f376Srpe set -A _cmds 11024811c97Srpe 111dfc209d0Smiod # Interface names must be alphanumeric only. We check to avoid 112dfc209d0Smiod # configuring backup or temp files, and to catch the "*" case. 1138222f376Srpe [[ $_if != +([[:alpha:]])+([[:digit:]]) ]] && return 114dfc209d0Smiod 115b7a96a2bSrpe if [[ ! -f $_hn ]]; then 1167f358361Srpe print -u2 "${0##*/}: $_hn: No such file or directory." 11749352c7bStodd return 11849352c7bStodd fi 1198222f376Srpe 120300d0407Srpe # Not using stat(1), we can't rely on having /usr yet. 121b7a96a2bSrpe set -A _stat -- $(ls -nL $_hn) 1221a0aef30Srpe if [[ "${_stat[0]}${_stat[2]}${_stat[3]}" != *---00 ]]; then 1237f358361Srpe print -u2 "WARNING: $_hn is insecure, fixing permissions." 124b7a96a2bSrpe chmod -LR o-rwx $_hn 125b7a96a2bSrpe chown -LR root:wheel $_hn 126bc53e65aSderaadt fi 127dfc209d0Smiod 1288222f376Srpe # Check for ifconfig'able interface, except if -n option is specified. 1298222f376Srpe if ! $PRINT_ONLY; then 130b6107460Sdlg ifcreate $_if || return 1312817040cStodd fi 1328222f376Srpe 1338222f376Srpe # Parse the hostname.if(5) file and fill _cmds array with interface 1348222f376Srpe # configuration commands. 1358222f376Srpe set -o noglob 13688c728ccSkn while IFS= read -- _line; do 1378222f376Srpe parse_hn_line $_line 138b7a96a2bSrpe done <$_hn 1398222f376Srpe 1408222f376Srpe # Apply the interface configuration commands stored in _cmds array. 1418222f376Srpe while ((_i < ${#_cmds[*]})); do 1428222f376Srpe if $PRINT_ONLY; then 1438222f376Srpe print -r -- "${_cmds[_i]}" 1448222f376Srpe else 1458222f376Srpe eval "${_cmds[_i]}" 1468222f376Srpe fi 1478222f376Srpe ((_i++)) 1488222f376Srpe done 1498222f376Srpe unset _cmds 15079699d09Srpe set +o noglob 151dfc209d0Smiod} 152dfc209d0Smiod 153dde523b1Srpe# Start multiple interfaces by driver name. 154dde523b1Srpe# Usage: ifmstart "em iwm" "trunk vlan" 155300d0407Srpe# Start "$1" interfaces in order or all interfaces if empty. 156dde523b1Srpe# Don't start "$2" interfaces. "$2" is optional. 1579ac6b043Stoddifmstart() { 158dde523b1Srpe local _sifs=$1 _xifs=$2 _hn _if _sif _xif 159dde523b1Srpe 160dde523b1Srpe for _sif in ${_sifs:-ALL}; do 161375c217eSrpe for _hn in /etc/hostname.+([[:alpha:]])+([[:digit:]]); do 162375c217eSrpe [[ -f $_hn ]] || continue 163dde523b1Srpe _if=${_hn#/etc/hostname.} 1649ac6b043Stodd 165300d0407Srpe # Skip unwanted ifs. 166dde523b1Srpe for _xif in $_xifs; do 167dde523b1Srpe [[ $_xif == ${_if%%[0-9]*} ]] && continue 2 1689ac6b043Stodd done 1699ac6b043Stodd 170300d0407Srpe # Start wanted ifs. 171dde523b1Srpe [[ $_sif == @(ALL|${_if%%[0-9]*}) ]] && ifstart $_if 1729ac6b043Stodd done 1739ac6b043Stodd done 1749ac6b043Stodd} 1759ac6b043Stodd 17680771ddaSrpe# Parse /etc/mygate and add default routes for IPv4 and IPv6. 17705102370Smpi# Usage: defaultroute 17805102370Smpidefaultroute() { 179e9c30f15Stb local _cmd; 180*4f9a4669Sderaadt set -o noglob 181e9c30f15Stb 182*4f9a4669Sderaadt stripcom /etc/mygate | 1830113d951Srpe while read gw; do 184*4f9a4669Sderaadt case $gw in 185*4f9a4669Sderaadt '!'*) 186*4f9a4669Sderaadt _cmd=$(print -- "$gw" | sed 's/\$if/'$_if'/g') 187*4f9a4669Sderaadt _cmd="${_cmd#!}" 188*4f9a4669Sderaadt ;; 189*4f9a4669Sderaadt *) 190*4f9a4669Sderaadt if [[ $gw != @(*:*) ]]; then 191*4f9a4669Sderaadt $V4_DHCPCONF && continue 192e9c30f15Stb _cmd="route -qn add -host default $gw" 193*4f9a4669Sderaadt elif [[ $gw == @(*:*) ]]; then 194*4f9a4669Sderaadt $V6_AUTOCONF && continue 195e9c30f15Stb _cmd="route -qn add -host -inet6 default $gw" 196*4f9a4669Sderaadt fi 197*4f9a4669Sderaadt ;; 198*4f9a4669Sderaadt esac 199e9c30f15Stb if $PRINT_ONLY; then 200*4f9a4669Sderaadt print -r -- "$_cmd" 201e9c30f15Stb else 202*4f9a4669Sderaadt $_cmd 203e9c30f15Stb fi 20405102370Smpi done 205*4f9a4669Sderaadt set +o noglob 20605102370Smpi} 20705102370Smpi 20889f9479fStb# Make sure the invoking user has the right privileges. Check for presence of 20989f9479fStb# id(1) to avoid problems with diskless setups. 21089f9479fStbif [[ -x /usr/bin/id ]] && (($(id -u) != 0)); then 21189f9479fStb echo "${0##*/}: need root privileges" 21289f9479fStb exit 1 21389f9479fStbfi 21489f9479fStb 215a035c1adSrpe# Get network related vars from rc.conf using the parsing routine from rc.subr. 216a035c1adSrpeFUNCS_ONLY=1 . /etc/rc.d/rc.subr 2178799e9c8Srobert_rc_parse_conf 2180dc37902Sangelos 2198222f376SrpePRINT_ONLY=false 2200113d951SrpeV4_DHCPCONF=false 2210113d951SrpeV6_AUTOCONF=false 2220113d951Srpe 2238222f376Srpewhile getopts ":n" opt; do 2248222f376Srpe case $opt in 2258222f376Srpe n) PRINT_ONLY=true;; 2262511c2f6Srpe *) usage;; 2278222f376Srpe esac 2288222f376Srpedone 2298222f376Srpeshift $((OPTIND-1)) 2308222f376Srpe 2318222f376Srpe# Option -n is only supported if interface names are specified as parameters. 2322511c2f6Srpe$PRINT_ONLY && (($# == 0)) && usage 2338222f376Srpe 23480771ddaSrpe# Load key material for the generation of IPv6 Semantically Opaque Interface 23580771ddaSrpe# Identifiers (SOII) used for link local and SLAAC addresses. 23681acd49bSflorian$PRINT_ONLY || [[ ! -f /etc/soii.key ]] || 23781acd49bSflorian sysctl -q "net.inet6.ip6.soiikey=$(</etc/soii.key)" 23881acd49bSflorian 239dfc209d0Smiod# If we were invoked with a list of interface names, just reconfigure these 24005102370Smpi# interfaces (or bridges), add default routes and return. 2410a295e45Srpeif (($# > 0)); then 2420a295e45Srpe for _if; do ifstart $_if; done 24305102370Smpi defaultroute 244dfc209d0Smiod return 245dfc209d0Smiodfi 246dfc209d0Smiod 247dfc209d0Smiod# Otherwise, process with the complete network initialization. 248dfc209d0Smiod 2494fbd02fcSsobrado# Set the address for the loopback interface. Bringing the interface up, 2504fbd02fcSsobrado# automatically invokes the IPv6 address ::1. 251d216f73bShenningifconfig lo0 inet 127.0.0.1/8 25298c28033Skstailey 25380771ddaSrpe# IPv6 configuration. 2543d8fed7cSitojunif ifconfig lo0 inet6 >/dev/null 2>&1; then 2553d8fed7cSitojun ip6kernel=YES 2563d8fed7cSitojun 257dfc209d0Smiod # Disallow link-local unicast dest without outgoing scope identifiers. 258c3b5ca42Skn route -qn add -inet6 fe80:: -prefixlen 10 ::1 -reject 25992aceabbSitojun 260dfc209d0Smiod # Disallow site-local unicast dest without outgoing scope identifiers. 26192aceabbSitojun # If you configure site-locals without scope id (it is permissible 26292aceabbSitojun # config for routers that are not on scope boundary), you may want 26392aceabbSitojun # to comment the line out. 264c3b5ca42Skn route -qn add -inet6 fec0:: -prefixlen 10 ::1 -reject 26592aceabbSitojun 266dfc209d0Smiod # Disallow "internal" addresses to appear on the wire. 267c3b5ca42Skn route -qn add -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject 26892aceabbSitojun 269dfc209d0Smiod # Disallow packets to malicious 6to4 prefix. 270c3b5ca42Skn route -qn add -inet6 2002:e000:: -prefixlen 20 ::1 -reject 271c3b5ca42Skn route -qn add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject 272c3b5ca42Skn route -qn add -inet6 2002:0000:: -prefixlen 24 ::1 -reject 273c3b5ca42Skn route -qn add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject 27492aceabbSitojun 275a4ee3723Sitojun # Disallow packets without scope identifier. 276c3b5ca42Skn route -qn add -inet6 ff01:: -prefixlen 16 ::1 -reject 277c3b5ca42Skn route -qn add -inet6 ff02:: -prefixlen 16 ::1 -reject 278a4ee3723Sitojun 27992aceabbSitojun # Completely disallow packets to IPv4 compatible prefix. 280300d0407Srpe # 28192aceabbSitojun # This may conflict with RFC1933 under following circumstances: 28292aceabbSitojun # (1) An IPv6-only KAME node tries to originate packets to IPv4 2835e268fadSderaadt # compatible destination. The KAME node has no IPv4 compatible 28492aceabbSitojun # support. Under RFC1933, it should transmit native IPv6 28592aceabbSitojun # packets toward IPv4 compatible destination, hoping it would 28692aceabbSitojun # reach a router that forwards the packet toward auto-tunnel 28792aceabbSitojun # interface. 2885e268fadSderaadt # (2) An IPv6-only node originates a packet to an IPv4 compatible 28992aceabbSitojun # destination. A KAME node is acting as an IPv6 router, and 29092aceabbSitojun # asked to forward it. 291300d0407Srpe # 2925e268fadSderaadt # Due to rare use of IPv4 compatible addresses, and security issues 29392aceabbSitojun # with it, we disable it by default. 294c3b5ca42Skn route -qn add -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject 2953d8fed7cSitojunelse 2963d8fed7cSitojun ip6kernel=NO 2973d8fed7cSitojunfi 2983d8fed7cSitojun 29980771ddaSrpe# Create all the pseudo interfaces up front. 300b6107460Sdlgvifscreate 301df930be7Sderaadt 3029ac6b043Stodd# Configure all the non-loopback interfaces which we know about, but 3034eb97611Sderaadt# do not start interfaces which must be delayed. Refer to hostname.if(5) 304f7df26a3Sjmcifmstart "" "aggr trunk svlan vlan carp pppoe tun tap gif etherip gre egre pflow wg" 30582c17b75Sitojun 306774508f4Sdlg# The aggr and trunk interfaces need to come up first in this list. 307f45bd3bdSmpf# The (s)vlan interfaces need to come up after trunk. 3084bdcd471Sbrad# Configure all the carp interfaces which we know about before default route. 309774508f4Sdlgifmstart "aggr trunk svlan vlan carp pppoe" 3104bdcd471Sbrad 31180771ddaSrpe# Set default routes for IPv4 and IPv6. 31205102370Smpidefaultroute 313cf3860a5Sderaadt 314745634aaSniklas# Multicast routing. 3156e0f151eSsthenif [[ $multicast != YES ]]; then 316705fcffdSreyk route -qn delete 224.0.0.0/4 >/dev/null 2>&1 317f4b4b73bSderaadt route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject >/dev/null 3186e0f151eSsthenfi 319dfc209d0Smiod 320300d0407Srpe# Reject 127/8 other than 127.0.0.1. 3218f8fdbefSderaadtroute -qn add -net 127 127.0.0.1 -reject >/dev/null 3228f8fdbefSderaadt 323b6107460Sdlg# Configure interfaces that rely on routing 324f7df26a3Sjmcifmstart "tun tap gif etherip gre egre pflow wg" 325b6107460Sdlg 3260a295e45Srpeif [[ $ip6kernel == YES ]]; then 32780771ddaSrpe # Ensure IPv6 Duplicate Address Detection (DAD) is completed. 328c653ce7bSmarkus count=0 3290a295e45Srpe while ((count++ < 10 && $(sysctl -n net.inet6.ip6.dad_pending) != 0)); do 330c653ce7bSmarkus sleep 1 331c653ce7bSmarkus done 332089287c3Sdavidfi 333