netstart revision 1.177
1#!/bin/sh - 2# 3# $OpenBSD: netstart,v 1.177 2017/04/24 20:31:48 rpe Exp $ 4 5# Turn off Strict Bourne shell mode. 6set +o sh 7 8# Echo file $1 to stdout. Skip comment lines and delete everything 9# after the first '#' from other lines. Strip leading and trailing 10# whitespace if IFS is set. 11# Usage: stripcom /path/to/file 12stripcom() { 13 local _file=$1 _line 14 15 [[ -f $_file ]] || return 16 17 while read _line; do 18 [[ -n ${_line%%#*} ]] && print -r -- "$_line" 19 done <$_file 20} 21 22# Parse and "unpack" a hostname.if(5) line given as positional parameters. 23# Fill the _cmds array with the resulting interface configuration commands. 24parse_hn_line() { 25 local _af=0 _name=1 _mask=2 _bc=3 _prefix=2 _c _cmd _prev _daddr 26 set -A _c -- "$@" 27 set -o noglob 28 29 case ${_c[_af]} in 30 ''|*([[:blank:]])'#'*) 31 return 32 ;; 33 inet) ((${#_c[*]} > 1)) || return 34 [[ ${_c[_name]} == alias ]] && _mask=3 _bc=4 35 [[ -n ${_c[_mask]} ]] && _c[_mask]="netmask ${_c[_mask]}" 36 if [[ -n ${_c[_bc]} ]]; then 37 _c[_bc]="broadcast ${_c[_bc]}" 38 [[ ${_c[_bc]} == *NONE ]] && _c[_bc]= 39 fi 40 _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}" 41 ;; 42 inet6) ((${#_c[*]} > 1)) || return 43 if [[ ${_c[_name]} == autoconf ]]; then 44 _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}" 45 rtsolif="$rtsolif $_if" 46 return 47 fi 48 [[ ${_c[_name]} == alias ]] && _prefix=3 49 [[ -n ${_c[_prefix]} ]] && _c[_prefix]="prefixlen ${_c[_prefix]}" 50 _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}" 51 ;; 52 dest) ((${#_c[*]} == 2)) && _daddr=${_c[1]} || return 53 _prev=$((${#_cmds[*]} - 1)) 54 ((_prev >= 0)) || return 55 set -A _c -- ${_cmds[_prev]} 56 _name=3 57 [[ ${_c[_name]} == alias ]] && _name=4 58 _c[_name]="${_c[_name]} $_daddr" 59 _cmds[$_prev]="${_c[@]}" 60 ;; 61 dhcp) _c[0]= 62 _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]} down;dhclient $_if" 63 dhcpif="$dhcpif $_if" 64 ;; 65 rtsol) # XXX Support the rtsol keyword for some time to enable a smooth 66 # XXX transition to autoconf. 67 _c[0]= 68 _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]} up" 69 _cmds[${#_cmds[*]}]="ifconfig $_if inet6 autoconf" 70 rtsolif="$rtsolif $_if" 71 ;; 72 '!'*) _cmd=$(print -- "${_c[@]}" | sed 's/\$if/'$_if'/g') 73 _cmds[${#_cmds[*]}]="${_cmd#!}" 74 ;; 75 *) _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}" 76 ;; 77 esac 78 unset _c 79} 80 81# Start a single interface. 82# Usage: ifstart if1 83ifstart() { 84 local _if=$1 _file=$HN_DIR/hostname.$1 _cmds _i=0 _line _stat 85 set -A _cmds 86 87 # Interface names must be alphanumeric only. We check to avoid 88 # configuring backup or temp files, and to catch the "*" case. 89 [[ $_if != +([[:alpha:]])+([[:digit:]]) ]] && return 90 91 if [[ ! -f $_file ]]; then 92 echo "netstart: $_file: No such file or directory" 93 return 94 fi 95 96 # Not using stat(1), we can't rely on having /usr yet. 97 set -A _stat -- $(ls -nL $_file) 98 if [ "${_stat[0]#???????} ${_stat[2]} ${_stat[3]}" != "--- 0 0" ]; then 99 echo "WARNING: $_file is insecure, fixing permissions" 100 chmod -LR o-rwx $_file 101 chown -LR root.wheel $_file 102 fi 103 104 # Check for ifconfig'able interface, except if -n option is specified. 105 if ! $PRINT_ONLY; then 106 (ifconfig $_if || ifconfig $_if create) >/dev/null 2>&1 || 107 return 108 fi 109 110 # Parse the hostname.if(5) file and fill _cmds array with interface 111 # configuration commands. 112 set -o noglob 113 while IFS= read -- _line; do 114 parse_hn_line $_line 115 done <$_file 116 117 # Apply the interface configuration commands stored in _cmds array. 118 while ((_i < ${#_cmds[*]})); do 119 if $PRINT_ONLY; then 120 print -r -- "${_cmds[_i]}" 121 else 122 eval "${_cmds[_i]}" 123 fi 124 ((_i++)) 125 done 126 unset _cmds 127} 128 129# Start multiple interfaces by driver name. 130# Usage: ifmstart "em iwm" "trunk vlan" 131# Start "$1" interfaces in order or all interfaces if empty. 132# Don't start "$2" interfaces. "$2" is optional. 133ifmstart() { 134 local _sifs=$1 _xifs=$2 _hn _if _sif _xif 135 136 for _sif in ${_sifs:-ALL}; do 137 for _hn in /etc/hostname.*; do 138 _if=${_hn#/etc/hostname.} 139 [[ $_if == '*' ]] && continue 140 141 # Skip unwanted ifs. 142 for _xif in $_xifs; do 143 [[ $_xif == ${_if%%[0-9]*} ]] && continue 2 144 done 145 146 # Start wanted ifs. 147 [[ $_sif == @(ALL|${_if%%[0-9]*}) ]] && ifstart $_if 148 done 149 done 150} 151 152# IPv6 autoconf the interfaces in the $rtsolif list. 153# Usage: ifv6autoconf 154ifv6autoconf() { 155 local _if 156 157 # $ip6kernel will not have been set if we were invoked with a 158 # list of interface names 159 ifconfig lo0 inet6 >/dev/null 2>&1 || return 0 160 161 for _if in $rtsolif; do 162 ifconfig $_if inet6 autoconf 163 done 164} 165 166# Parse /etc/mygate and add default routes for IPv4 and IPv6 167# Usage: defaultroute 168defaultroute() { 169 [[ -z $dhcpif ]] && stripcom /etc/mygate | while read gw; do 170 [[ $gw == @(*:*) ]] && continue 171 route -qn delete default >/dev/null 2>&1 172 route -qn add -host default $gw && break 173 done 174 [[ -z $rtsolif ]] && stripcom /etc/mygate | while read gw; do 175 [[ $gw == !(*:*) ]] && continue 176 route -qn delete -inet6 default >/dev/null 2>&1 177 route -qn add -host -inet6 default $gw && break 178 done 179} 180 181# Make sure the invoking user has the right privileges. 182if (($(id -u) != 0)); then 183 echo "${0##*/}: need root privileges" 184 exit 1 185fi 186 187# Get network related vars from rc.conf using the parsing routine from rc.subr. 188FUNCS_ONLY=1 . /etc/rc.d/rc.subr 189_rc_parse_conf 190 191HN_DIR=${HN_DIR:-/etc} 192PRINT_ONLY=false 193USAGE="USAGE: ${0##*/} [-n] [interface ...]" 194while getopts ":n" opt; do 195 case $opt in 196 n) PRINT_ONLY=true;; 197 *) print -u2 "$USAGE"; exit 1;; 198 esac 199done 200shift $((OPTIND-1)) 201 202# Option -n is only supported if interface names are specified as parameters. 203if $PRINT_ONLY && (($# == 0)); then 204 print -u2 "Missing parameters.\n$USAGE" 205 exit 1 206fi 207 208# If we were invoked with a list of interface names, just reconfigure these 209# interfaces (or bridges), add default routes and return. 210if (($# > 0)); then 211 for _if; do ifstart $_if; done 212 ifv6autoconf 213 defaultroute 214 return 215fi 216 217# Otherwise, process with the complete network initialization. 218 219# /etc/myname contains my symbolic name. 220[[ -f /etc/myname ]] && hostname "$(stripcom /etc/myname)" 221 222# Set the address for the loopback interface. Bringing the interface up, 223# automatically invokes the IPv6 address ::1. 224ifconfig lo0 inet 127.0.0.1/8 225 226if ifconfig lo0 inet6 >/dev/null 2>&1; then 227 # IPv6 configurations. 228 ip6kernel=YES 229 230 # Disallow link-local unicast dest without outgoing scope identifiers. 231 route -qn add -inet6 fe80:: -prefixlen 10 ::1 -reject >/dev/null 232 233 # Disallow site-local unicast dest without outgoing scope identifiers. 234 # If you configure site-locals without scope id (it is permissible 235 # config for routers that are not on scope boundary), you may want 236 # to comment the line out. 237 route -qn add -inet6 fec0:: -prefixlen 10 ::1 -reject >/dev/null 238 239 # Disallow "internal" addresses to appear on the wire. 240 route -qn add -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject >/dev/null 241 242 # Disallow packets to malicious IPv4 compatible prefix. 243 route -qn add -inet6 ::224.0.0.0 -prefixlen 100 ::1 -reject >/dev/null 244 route -qn add -inet6 ::127.0.0.0 -prefixlen 104 ::1 -reject >/dev/null 245 route -qn add -inet6 ::0.0.0.0 -prefixlen 104 ::1 -reject >/dev/null 246 route -qn add -inet6 ::255.0.0.0 -prefixlen 104 ::1 -reject >/dev/null 247 248 # Disallow packets to malicious 6to4 prefix. 249 route -qn add -inet6 2002:e000:: -prefixlen 20 ::1 -reject >/dev/null 250 route -qn add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject >/dev/null 251 route -qn add -inet6 2002:0000:: -prefixlen 24 ::1 -reject >/dev/null 252 route -qn add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject >/dev/null 253 254 # Disallow packets without scope identifier. 255 route -qn add -inet6 ff01:: -prefixlen 16 ::1 -reject >/dev/null 256 route -qn add -inet6 ff02:: -prefixlen 16 ::1 -reject >/dev/null 257 258 # Completely disallow packets to IPv4 compatible prefix. 259 # 260 # This may conflict with RFC1933 under following circumstances: 261 # (1) An IPv6-only KAME node tries to originate packets to IPv4 262 # compatible destination. The KAME node has no IPv4 compatible 263 # support. Under RFC1933, it should transmit native IPv6 264 # packets toward IPv4 compatible destination, hoping it would 265 # reach a router that forwards the packet toward auto-tunnel 266 # interface. 267 # (2) An IPv6-only node originates a packet to an IPv4 compatible 268 # destination. A KAME node is acting as an IPv6 router, and 269 # asked to forward it. 270 # 271 # Due to rare use of IPv4 compatible addresses, and security issues 272 # with it, we disable it by default. 273 route -qn add -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject >/dev/null 274 275 rtsolif="" 276else 277 ip6kernel=NO 278fi 279 280 281# Configure all the non-loopback interfaces which we know about, but 282# do not start interfaces which must be delayed. Refer to hostname.if(5) 283ifmstart "" "trunk svlan vlan carp gif gre pfsync pppoe tun bridge switch pflow" 284 285# The trunk interfaces need to come up first in this list. 286# The (s)vlan interfaces need to come up after trunk. 287# Configure all the carp interfaces which we know about before default route. 288ifmstart "trunk svlan vlan carp" 289 290# Now that $rtsolif has been populated, IPv6 autoconf those interfaces 291ifv6autoconf 292 293# Look for default routes in /etc/mygate. 294defaultroute 295 296# Multicast routing. 297if [[ $multicast != YES ]]; then 298 route -qn delete 224.0.0.0/4 >/dev/null 2>&1 299 route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject >/dev/null 300fi 301 302# Configure PPPoE, GIF, GRE, TUN and PFLOW interfaces, delayed because they 303# require routes to be set. TUN might depend on PPPoE, and GIF or GRE may 304# depend on either of them. PFLOW might bind to ip addresses configured 305# on either of them. 306ifmstart "pppoe tun gif gre bridge switch pflow" 307 308# Reject 127/8 other than 127.0.0.1. 309route -qn add -net 127 127.0.0.1 -reject >/dev/null 310 311if [[ $ip6kernel == YES ]]; then 312 # This is to make sure DAD is completed before going further. 313 count=0 314 while ((count++ < 10 && $(sysctl -n net.inet6.ip6.dad_pending) != 0)); do 315 sleep 1 316 done 317fi 318