1#!/bin/sh - 2# 3# $OpenBSD: netstart,v 1.170 2016/09/09 19:48:16 jasper 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# Make sure the invoking user has the right privileges. 171if (($(id -u) != 0)); then 172 echo "${0##*/}: need root privileges" 173 exit 1 174fi 175 176# Get network related vars from rc.conf using the parsing routine from rc.subr. 177FUNCS_ONLY=1 . /etc/rc.d/rc.subr 178_rc_parse_conf 179 180# If we were invoked with a list of interface names, just reconfigure these 181# interfaces (or bridges) and return. 182if (($# > 0)); then 183 for _if; do ifstart $_if; done 184 ifv6autoconf 185 return 186fi 187 188# Otherwise, process with the complete network initialization. 189 190# /etc/myname contains my symbolic name. 191[[ -f /etc/myname ]] && hostname "$(stripcom /etc/myname)" 192 193# Set the address for the loopback interface. Bringing the interface up, 194# automatically invokes the IPv6 address ::1. 195ifconfig lo0 inet 127.0.0.1/8 196 197if ifconfig lo0 inet6 >/dev/null 2>&1; then 198 # IPv6 configurations. 199 ip6kernel=YES 200 201 # Disallow link-local unicast dest without outgoing scope identifiers. 202 route -qn add -inet6 fe80:: -prefixlen 10 ::1 -reject >/dev/null 203 204 # Disallow site-local unicast dest without outgoing scope identifiers. 205 # If you configure site-locals without scope id (it is permissible 206 # config for routers that are not on scope boundary), you may want 207 # to comment the line out. 208 route -qn add -inet6 fec0:: -prefixlen 10 ::1 -reject >/dev/null 209 210 # Disallow "internal" addresses to appear on the wire. 211 route -qn add -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject >/dev/null 212 213 # Disallow packets to malicious IPv4 compatible prefix. 214 route -qn add -inet6 ::224.0.0.0 -prefixlen 100 ::1 -reject >/dev/null 215 route -qn add -inet6 ::127.0.0.0 -prefixlen 104 ::1 -reject >/dev/null 216 route -qn add -inet6 ::0.0.0.0 -prefixlen 104 ::1 -reject >/dev/null 217 route -qn add -inet6 ::255.0.0.0 -prefixlen 104 ::1 -reject >/dev/null 218 219 # Disallow packets to malicious 6to4 prefix. 220 route -qn add -inet6 2002:e000:: -prefixlen 20 ::1 -reject >/dev/null 221 route -qn add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject >/dev/null 222 route -qn add -inet6 2002:0000:: -prefixlen 24 ::1 -reject >/dev/null 223 route -qn add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject >/dev/null 224 225 # Disallow packets without scope identifier. 226 route -qn add -inet6 ff01:: -prefixlen 16 ::1 -reject >/dev/null 227 route -qn add -inet6 ff02:: -prefixlen 16 ::1 -reject >/dev/null 228 229 # Completely disallow packets to IPv4 compatible prefix. 230 # 231 # This may conflict with RFC1933 under following circumstances: 232 # (1) An IPv6-only KAME node tries to originate packets to IPv4 233 # compatible destination. The KAME node has no IPv4 compatible 234 # support. Under RFC1933, it should transmit native IPv6 235 # packets toward IPv4 compatible destination, hoping it would 236 # reach a router that forwards the packet toward auto-tunnel 237 # interface. 238 # (2) An IPv6-only node originates a packet to an IPv4 compatible 239 # destination. A KAME node is acting as an IPv6 router, and 240 # asked to forward it. 241 # 242 # Due to rare use of IPv4 compatible addresses, and security issues 243 # with it, we disable it by default. 244 route -qn add -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject >/dev/null 245 246 rtsolif="" 247else 248 ip6kernel=NO 249fi 250 251 252# Configure all the non-loopback interfaces which we know about, but 253# do not start interfaces which must be delayed. Refer to hostname.if(5) 254ifmstart "" "trunk svlan vlan carp gif gre pfsync pppoe tun bridge pflow" 255 256# The trunk interfaces need to come up first in this list. 257# The (s)vlan interfaces need to come up after trunk. 258# Configure all the carp interfaces which we know about before default route. 259ifmstart "trunk svlan vlan carp" 260 261# Now that $rtsolif has been populated, IPv6 autoconf those interfaces 262ifv6autoconf 263 264# Look for default routes in /etc/mygate. 265[[ -z $dhcpif ]] && stripcom /etc/mygate | while read gw; do 266 [[ $gw == @(*:*) ]] && continue 267 route -qn delete default >/dev/null 2>&1 268 route -qn add -host default $gw && break 269done 270[[ -z $rtsolif ]] && stripcom /etc/mygate | while read gw; do 271 [[ $gw == !(*:*) ]] && continue 272 route -qn delete -inet6 default >/dev/null 2>&1 273 route -qn add -host -inet6 default $gw && break 274done 275 276# Multicast routing. 277if [[ $multicast != YES ]]; then 278 route -qn delete 224.0.0.0/4 >/dev/null 2>&1 279 route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject >/dev/null 280fi 281 282# Configure PPPoE, GIF, GRE, TUN and PFLOW interfaces, delayed because they 283# require routes to be set. TUN might depend on PPPoE, and GIF or GRE may 284# depend on either of them. PFLOW might bind to ip addresses configured 285# on either of them. 286ifmstart "pppoe tun gif gre bridge pflow" 287 288# Reject 127/8 other than 127.0.0.1. 289route -qn add -net 127 127.0.0.1 -reject >/dev/null 290 291if [[ $ip6kernel == YES ]]; then 292 # This is to make sure DAD is completed before going further. 293 count=0 294 while ((count++ < 10 && $(sysctl -n net.inet6.ip6.dad_pending) != 0)); do 295 sleep 1 296 done 297fi 298