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