netstart revision 1.129
1#!/bin/sh - 2# 3# $OpenBSD: netstart,v 1.129 2010/01/12 07:43:41 henning Exp $ 4 5# Strip comments (and leading/trailing whitespace if IFS is set) 6# from a file and spew to stdout 7stripcom() { 8 local _l 9 [[ -f $1 ]] || return 10 while read _l; do 11 [[ -n ${_l%%#*} ]] && echo $_l 12 done<$1 13} 14 15# Returns true if $1 contains only alphanumerics 16isalphanumeric() { 17 local _n 18 _n=$1 19 while [ ${#_n} != 0 ]; do 20 case $_n in 21 [A-Za-z0-9]*) ;; 22 *) return 1;; 23 esac 24 _n=${_n#?} 25 done 26 return 0 27} 28 29# Start the $1 interface 30ifstart() { 31 if=$1 32 # Interface names must be alphanumeric only. We check to avoid 33 # configuring backup or temp files, and to catch the "*" case. 34 if ! isalphanumeric "$if"; then 35 return 36 fi 37 38 file=/etc/hostname.$if 39 if ! [ -f $file ]; then 40 echo "netstart: $file: No such file or directory" 41 return 42 fi 43 # Not using stat(1), we can't rely on having /usr yet 44 set -A stat -- `ls -nL $file` 45 if [ "${stat[0]#???????} ${stat[2]} ${stat[3]}" != "--- 0 0" ]; then 46 echo "WARNING: $file is insecure, fixing permissions" 47 chmod -LR o-rwx $file 48 chown -LR root.wheel $file 49 fi 50 ifconfig $if > /dev/null 2>&1 51 if [ "$?" != "0" ]; then 52 # Try to create interface if it does not exist 53 ifconfig $if create > /dev/null 2>&1 54 if [ "$?" != "0" ]; then 55 return 56 fi 57 fi 58 59 # Now parse the hostname.* file 60 while :; do 61 if [ "$cmd2" ]; then 62 # We are carrying over from the 'read dt dtaddr' 63 # last time. 64 set -- $cmd2 65 af="$1" name="$2" mask="$3" bcaddr="$4" ext1="$5" cmd2= 66 # Make sure and get any remaining args in ext2, 67 # like the read below 68 i=1 69 while [ $i -lt 6 -a -n "$1" ]; do shift; let i=i+1; done 70 ext2="$@" 71 else 72 # Read the next line or exit the while loop. 73 read af name mask bcaddr ext1 ext2 || break 74 fi 75 # $af can be "dhcp", "up", "rtsol", an address family, 76 # commands, or a comment. 77 case "$af" in 78 "#"*|"") # skip comments and empty lines 79 continue 80 ;; 81 "!"*) # parse commands 82 cmd="${af#*!} ${name} ${mask} ${bcaddr} ${ext1} ${ext2}" 83 ;; 84 "dhcp") 85 [ "$name" = "NONE" ] && name= 86 [ "$mask" = "NONE" ] && mask= 87 [ "$bcaddr" = "NONE" ] && bcaddr= 88 cmd="ifconfig $if $name $mask $bcaddr $ext1 $ext2 down" 89 cmd="$cmd;dhclient $if" 90 dhcpif="$dhcpif $if" 91 ;; 92 "rtsol") 93 rtsolif="$rtsolif $if" 94 cmd="ifconfig $if $name $mask $bcaddr $ext1 $ext2 up" 95 ;; 96 *) 97 read dt dtaddr 98 if [ "$name" = "alias" ]; then 99 # perform a 'shift' of sorts 100 alias=$name 101 name=$mask 102 mask=$bcaddr 103 bcaddr=$ext1 104 ext1=$ext2 105 ext2= 106 else 107 alias= 108 fi 109 cmd="ifconfig $if $af $alias $name" 110 case "$dt" in 111 dest) 112 cmd="$cmd $dtaddr" 113 ;; 114 [a-z!]*) 115 cmd2="$dt $dtaddr" 116 ;; 117 esac 118 case $af in 119 inet) 120 if [ ! -n "$name" ]; then 121 echo "/etc/hostname.$if: inet alone is invalid" 122 return 123 fi 124 [ "$mask" ] && cmd="$cmd netmask $mask" 125 if [ "$bcaddr" -a "X$bcaddr" != "XNONE" ]; then 126 cmd="$cmd broadcast $bcaddr" 127 fi 128 [ "$alias" ] && rtcmd=";route -qn add -host $name 127.0.0.1" 129 ;; 130 inet6) 131 if [ ! -n "$name" ]; then 132 echo "/etc/hostname.$if: inet6 alone is invalid" 133 return 134 fi 135 [ "$mask" ] && cmd="$cmd prefixlen $mask" 136 cmd="$cmd $bcaddr" 137 ;; 138 *) 139 cmd="$cmd $mask $bcaddr" 140 ;; 141 esac 142 cmd="$cmd $ext1 $ext2$rtcmd" rtcmd= 143 ;; 144 esac 145 eval "$cmd" 146 done < /etc/hostname.$if 147} 148 149# Start multiple: 150# start "$1" interfaces in order or all interfaces if empty 151# don't start "$2" interfaces 152ifmstart() { 153 for sif in ${1:-ALL}; do 154 for hn in /etc/hostname.*; do 155 # Strip off /etc/hostname. prefix 156 if=${hn#/etc/hostname.} 157 test "$if" = "*" && continue 158 159 # Skip unwanted ifs 160 s="" 161 for xf in $2; do 162 test "$xf" = "${if%%[0-9]*}" && s="1" && break 163 done 164 test "$s" = "1" && continue 165 166 # Start wanted ifs 167 test "$sif" = "ALL" -o \ 168 "$sif" = "${if%%[0-9]*}" \ 169 && ifstart $if 170 done 171 done 172} 173 174# Re-read /etc/rc.conf 175. /etc/rc.conf 176 177# If we were invoked with a list of interface names, just reconfigure these 178# interfaces (or bridges) and return. 179if [ $1x = autobootx ]; then 180 shift 181fi 182if [ $# -gt 0 ]; then 183 while [ $# -gt 0 ]; do 184 ifstart $1 185 shift 186 done 187 return 188fi 189 190# Otherwise, process with the complete network initialization. 191 192# /etc/myname contains my symbolic name 193if [ -f /etc/myname ]; then 194 hostname=`stripcom /etc/myname` 195 hostname $hostname 196else 197 hostname=`hostname` 198fi 199 200if [ -f /etc/defaultdomain ]; then 201 domainname `stripcom /etc/defaultdomain` 202fi 203 204# Set the address for the loopback interface. Bringing the 205# interface up, automatically invokes the IPv6 address ::1) 206ifconfig lo0 inet 127.0.0.1/8 207 208if ifconfig lo0 inet6 >/dev/null 2>&1; then 209 # IPv6 configurations. 210 ip6kernel=YES 211 212 # Disallow link-local unicast dest without outgoing scope identifiers. 213 route -qn add -inet6 fe80:: -prefixlen 10 ::1 -reject > /dev/null 214 215 # Disallow site-local unicast dest without outgoing scope identifiers. 216 # If you configure site-locals without scope id (it is permissible 217 # config for routers that are not on scope boundary), you may want 218 # to comment the line out. 219 route -qn add -inet6 fec0:: -prefixlen 10 ::1 -reject > /dev/null 220 221 # Disallow "internal" addresses to appear on the wire. 222 route -qn add -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject > /dev/null 223 224 # Disallow packets to malicious IPv4 compatible prefix. 225 route -qn add -inet6 ::224.0.0.0 -prefixlen 100 ::1 -reject > /dev/null 226 route -qn add -inet6 ::127.0.0.0 -prefixlen 104 ::1 -reject > /dev/null 227 route -qn add -inet6 ::0.0.0.0 -prefixlen 104 ::1 -reject > /dev/null 228 route -qn add -inet6 ::255.0.0.0 -prefixlen 104 ::1 -reject > /dev/null 229 230 # Disallow packets to malicious 6to4 prefix. 231 route -qn add -inet6 2002:e000:: -prefixlen 20 ::1 -reject > /dev/null 232 route -qn add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject > /dev/null 233 route -qn add -inet6 2002:0000:: -prefixlen 24 ::1 -reject > /dev/null 234 route -qn add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject > /dev/null 235 236 # Disallow packets without scope identifier. 237 route -qn add -inet6 ff01:: -prefixlen 16 ::1 -reject > /dev/null 238 route -qn add -inet6 ff02:: -prefixlen 16 ::1 -reject > /dev/null 239 240 # Completely disallow packets to IPv4 compatible prefix. 241 # This may conflict with RFC1933 under following circumstances: 242 # (1) An IPv6-only KAME node tries to originate packets to IPv4 243 # compatible destination. The KAME node has no IPv4 compatible 244 # support. Under RFC1933, it should transmit native IPv6 245 # packets toward IPv4 compatible destination, hoping it would 246 # reach a router that forwards the packet toward auto-tunnel 247 # interface. 248 # (2) An IPv6-only node originates a packet to an IPv4 compatible 249 # destination. A KAME node is acting as an IPv6 router, and 250 # asked to forward it. 251 # Due to rare use of IPv4 compatible addresses, and security issues 252 # with it, we disable it by default. 253 route -qn add -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject > /dev/null 254 255 rtsolif="" 256else 257 ip6kernel=NO 258fi 259 260 261# Configure all the non-loopback interfaces which we know about, but 262# do not start interfaces which must be delayed. Refer to hostname.if(5) 263ifmstart "" "trunk vlan carp gif gre pfsync pppoe tun bridge" 264 265# The trunk interfaces need to come up first in this list. 266# The vlan interfaces need to come up after trunk. 267# Configure all the carp interfaces which we know about before default route. 268ifmstart "trunk vlan carp" 269 270if [ "$ip6kernel" = "YES" -a "x$rtsolif" != "x" ]; then 271 fw=`sysctl -n net.inet6.ip6.forwarding` 272 ra=`sysctl -n net.inet6.ip6.accept_rtadv` 273 if [ "x$fw" = "x0" -a "x$ra" = "x1" ]; then 274 echo "IPv6 autoconf:$rtsolif" 275 rtsol $rtsolif 276 else 277 echo "WARNING: inconsistent config - check /etc/sysctl.conf for IPv6 autoconf" 278 fi 279fi 280 281# /etc/mygate, if it exists, contains the name of my gateway host 282# that name must be in /etc/hosts. 283[[ -z $dhcpif ]] && stripcom /etc/mygate | while read gw; do 284 [[ $gw == @(*:*) ]] && continue 285 route -qn delete default > /dev/null 2>&1 286 route -qn add -host default $gw && break 287done 288[[ -z $rtsolif ]] && stripcom /etc/mygate | while read gw; do 289 [[ $gw == !(*:*) ]] && continue 290 route -qn delete -inet6 default > /dev/null 2>&1 291 route -qn add -host -inet6 default $gw && break 292done 293 294# Multicast routing. 295# 296# The routing to the 224.0.0.0/4 net is setup according to these rules: 297# multicast_host multicast_router route comment 298# NO NO -reject no multicast 299# NO YES none installed daemon will run 300# YES/interface NO -interface YES=def. iface 301# Any other combination -reject config error 302route -qn delete 224.0.0.0/4 > /dev/null 2>&1 303case "$multicast_host:$multicast_router" in 304NO:NO) 305 route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject > /dev/null 306 ;; 307NO:YES) 308 ;; 309*:NO) 310 maddr=`if [ "$multicast_host" = "YES" ]; then 311 ed -s '!route -qn show -inet' <<EOF 312/^default/p 313EOF 314 else 315 ed -s "!ifconfig $multicast_host" <<EOF 316/^ inet /p 317EOF 318 fi 2> /dev/null` 319 if [ "X${maddr}" != "X" ]; then 320 set $maddr 321 route -qn add -net 224.0.0.0/4 -interface $2 > /dev/null 322 else 323 route -qn add -net 224.0.0.0/4 -interface \ 324 127.0.0.1 -reject > /dev/null 325 fi 326 ;; 327*:*) 328 echo 'config error, multicasting disabled until rc.conf is fixed' 329 route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject > /dev/null 330 ;; 331esac 332 333 334# Configure PPPoE, GIF, GRE and TUN interfaces, delayed because they require 335# routes to be set. TUN might depend on PPPoE, and GIF or GRE may depend on 336# either of them. 337ifmstart "pppoe tun gif gre bridge" 338 339# reject 127/8 other than 127.0.0.1 340route -qn add -net 127 127.0.0.1 -reject > /dev/null 341 342if [ "$ip6kernel" = "YES" ]; then 343 # this is to make sure DAD is completed before going further. 344 count=0 345 while [ $((count++)) -lt 10 -a "x"`sysctl -n net.inet6.ip6.dad_pending` != "x0" ]; do 346 sleep 1 347 done 348fi 349