]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - etc/network.subr
Fix a race condition exists in the OpenSSL TLS server extension code and
[FreeBSD/releng/8.0.git] / etc / network.subr
1 #
2 # Copyright (c) 2003 The FreeBSD Project. All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
6 # are met:
7 # 1. Redistributions of source code must retain the above copyright
8 #    notice, this list of conditions and the following disclaimer.
9 # 2. Redistributions in binary form must reproduce the above copyright
10 #    notice, this list of conditions and the following disclaimer in the
11 #    documentation and/or other materials provided with the distribution.
12 #
13 # THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
14 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 # ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
17 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 # SUCH DAMAGE.
24 #
25 # $FreeBSD$
26 #
27
28 #
29 # Subroutines commonly used from network startup scripts.
30 # Requires that rc.conf be loaded first.
31 #
32
33 # ifn_start ifn
34 # Bring up and configure an interface.  If some configuration is applied
35 # print the interface configuration.
36 #
37 ifn_start()
38 {
39         local ifn cfg
40         ifn="$1"
41         cfg=1
42
43         [ -z "$ifn" ] && err 1 "ifn_start called without an interface"
44
45         ifscript_up ${ifn} && cfg=0
46         ifconfig_up ${ifn} && cfg=0
47         ipv4_up ${ifn} && cfg=0
48         ipx_up ${ifn} && cfg=0
49         childif_create ${ifn}
50
51         return $cfg
52 }
53
54 # ifn_start ifn
55 # Shutdown and de-configure an interface.  If action is taken print the
56 # interface name.
57 #
58 ifn_stop()
59 {
60         local ifn cfg
61         ifn="$1"
62         cfg=1
63
64         [ -z "$ifn" ] && return 1
65
66         ipx_down ${ifn} && cfg=0
67         ipv4_down ${ifn} && cfg=0
68         ifconfig_down ${ifn} && cfg=0
69         ifscript_down ${ifn} && cfg=0
70         childif_destroy ${ifn}
71
72         return $cfg
73 }
74
75 # ifconfig_up if
76 #       Evaluate ifconfig(8) arguments for interface $if and
77 #       run ifconfig(8) with those arguments. It returns 0 if
78 #       arguments were found and executed or 1 if the interface
79 #       had no arguments.  Pseudo arguments DHCP and WPA are handled
80 #       here.
81 #
82 ifconfig_up()
83 {
84         _cfg=1
85
86         ifconfig_args=`ifconfig_getargs $1`
87         if [ -n "${ifconfig_args}" ]; then
88                 ifconfig $1 ${ifconfig_args}
89                 ifconfig $1 up
90                 _cfg=0
91         fi
92
93         if wpaif $1; then
94                 /etc/rc.d/wpa_supplicant start $1
95                 _cfg=0          # XXX: not sure this should count
96         fi
97
98         if dhcpif $1; then
99                 if [ $_cfg -ne 0 ] ; then
100                         ifconfig $1 up
101                 fi
102                 if syncdhcpif $1; then
103                         /etc/rc.d/dhclient start $1
104                 fi
105                 _cfg=0
106         fi
107
108         return $_cfg
109 }
110
111 # ifconfig_down if
112 #       returns 1 if wpa_supplicant or dhclient was stopped or
113 #       the interface exists.
114 #
115 ifconfig_down()
116 {
117         [ -z "$1" ] && return 1
118         _cfg=1
119
120         if wpaif $1; then
121                 /etc/rc.d/wpa_supplicant stop $1
122                 _cfg=0
123         fi
124
125         if dhcpif $1; then
126                 /etc/rc.d/dhclient stop $1
127                 _cfg=0
128         fi
129
130         if ifexists $1; then
131                 ifconfig $1 down
132                 _cfg=0
133         fi
134
135         return $_cfg
136 }
137
138 # get_if_var if var [default]
139 #       Return the value of the pseudo-hash corresponding to $if where
140 #       $var is a string containg the sub-string "IF" which will be
141 #       replaced with $if after the characters defined in _punct are
142 #       replaced with '_'. If the variable is unset, replace it with
143 #       $default if given.
144 get_if_var()
145 {
146         if [ $# -ne 2 -a $# -ne 3 ]; then
147                 err 3 'USAGE: get_if_var name var [default]'
148         fi
149
150         _if=$1
151         _punct=". - / +"
152         for _punct_c in $_punct; do
153                 _if=`ltr ${_if} ${_punct_c} '_'`
154         done
155         _var=$2
156         _default=$3
157
158         prefix=${_var%%IF*}
159         suffix=${_var##*IF}
160         eval echo \${${prefix}${_if}${suffix}-${_default}}
161 }
162
163 # _ifconfig_getargs if
164 #       Echos the arguments for the supplied interface to stdout.
165 #       returns 1 if empty.  In general, ifconfig_getargs should be used
166 #       outside this file.
167 _ifconfig_getargs()
168 {
169         _ifn=$1
170         if [ -z "$_ifn" ]; then
171                 return 1
172         fi
173
174         get_if_var $_ifn ifconfig_IF "$ifconfig_DEFAULT"
175 }
176
177 # ifconfig_getargs if
178 #       Takes the result from _ifconfig_getargs and removes pseudo
179 #       args such as DHCP and WPA.
180 ifconfig_getargs()
181 {
182         _tmpargs=`_ifconfig_getargs $1`
183         if [ $? -eq 1 ]; then
184                 return 1
185         fi
186         _args=
187
188         for _arg in $_tmpargs; do
189                 case $_arg in
190                 [Dd][Hh][Cc][Pp]) ;;
191                 [Nn][Oo][Aa][Uu][Tt][Oo]) ;;
192                 [Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
193                 [Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
194                 [Ww][Pp][Aa]) ;;
195                 *)
196                         _args="$_args $_arg"
197                         ;;
198                 esac
199         done
200
201         echo $_args
202 }
203
204 # autoif
205 #       Returns 0 if the interface should be automaticly configured at
206 #       boot time and 1 otherwise.
207 autoif()
208 {
209         _tmpargs=`_ifconfig_getargs $1`
210         for _arg in $_tmpargs; do
211                 case $_arg in
212                 [Nn][Oo][Aa][Uu][Tt][Oo])
213                         return 1
214                         ;;
215                 esac
216         done
217         return 0
218 }
219
220 # dhcpif if
221 #       Returns 0 if the interface is a DHCP interface and 1 otherwise.
222 dhcpif()
223 {
224         _tmpargs=`_ifconfig_getargs $1`
225         for _arg in $_tmpargs; do
226                 case $_arg in
227                 [Dd][Hh][Cc][Pp])
228                         return 0
229                         ;;
230                 [Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
231                         return 0
232                         ;;
233                 [Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
234                         return 0
235                         ;;
236                 esac
237         done
238         return 1
239 }
240
241 # syncdhcpif
242 #       Returns 0 if the interface should be configured synchronously and
243 #       1 otherwise.
244 syncdhcpif()
245 {
246         _tmpargs=`_ifconfig_getargs $1`
247         for _arg in $_tmpargs; do
248                 case $_arg in
249                 [Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
250                         return 1
251                         ;;
252                 [Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
253                         return 0
254                         ;;
255                 esac
256         done
257         if checkyesno synchronous_dhclient; then
258                 return 0
259         else
260                 return 1
261         fi
262 }
263
264 # wpaif if
265 #       Returns 0 if the interface is a WPA interface and 1 otherwise.
266 wpaif()
267 {
268         _tmpargs=`_ifconfig_getargs $1`
269         for _arg in $_tmpargs; do
270                 case $_arg in
271                 [Ww][Pp][Aa])
272                         return 0
273                         ;;
274                 esac
275         done
276         return 1
277 }
278
279 # ipv6if if
280 #       Returns 0 if the interface should be configured for IPv6 and
281 #       1 otherwise.
282 ipv6if()
283 {
284         if ! checkyesno ipv6_enable; then
285                 return 1
286         fi
287         case "${ipv6_network_interfaces}" in
288         [Aa][Uu][Tt][Oo])
289                 return 0
290                 ;;
291         ''|[Nn][Oo][Nn][Ee])
292                 return 1
293                 ;;
294         esac
295         for v6if in ${ipv6_network_interfaces}; do
296                 if [ "${v6if}" = "${1}" ]; then
297                         return 0
298                 fi
299         done
300         return 1
301 }
302
303 # ifexists if
304 #       Returns 0 if the interface exists and 1 otherwise.
305 ifexists()
306 {
307         ifconfig -n $1 > /dev/null 2>&1
308 }
309
310 # ipv4_up if
311 #  add IPv4 addresses to the interface $if 
312 ipv4_up()
313 {
314         _if=$1
315         ifalias_up ${_if}
316         ipv4_addrs_common ${_if} alias
317 }
318
319 # ipv4_down if
320 #  remove IPv4 addresses from the interface $if
321 ipv4_down()
322 {
323         _if=$1
324         _ifs="^"
325         _ret=1
326
327         ifexists ${_if} || return 1
328
329         inetList="`ifconfig ${_if} | grep 'inet ' | tr "\n" "$_ifs"`"
330
331         oldifs="$IFS"
332         IFS="$_ifs"
333         for _inet in $inetList ; do
334                 # get rid of extraneous line
335                 [ -z "$_inet" ] && break
336
337                 _inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
338
339                 IFS="$oldifs"
340                 ifconfig ${_if} ${_inet} delete
341                 IFS="$_ifs"
342                 _ret=0
343         done
344         IFS="$oldifs"
345
346         ifalias_down ${_if} && _ret=0
347         ipv4_addrs_common ${_if} -alias && _ret=0
348
349         return $_ret
350 }
351
352 # ipv4_addrs_common if action
353 #   Evaluate the ifconfig_if_ipv4 arguments for interface $if
354 #   and use $action to add or remove IPv4 addresses from $if.
355 ipv4_addrs_common()
356 {  
357         _ret=1
358         _if=$1
359         _action=$2
360     
361         # get ipv4-addresses
362         cidr_addr=`get_if_var $_if ipv4_addrs_IF`
363     
364         for _cidr in ${cidr_addr}; do
365                 _ipaddr=${_cidr%%/*}
366                 _netmask="/"${_cidr##*/}
367                 _range=${_ipaddr##*.}
368                 _ipnet=${_ipaddr%.*}
369                 _iplow=${_range%-*}
370                 _iphigh=${_range#*-}
371
372                 # clear netmask when removing aliases
373                 if [ "${_action}" = "-alias" ]; then
374                         _netmask=""
375                 fi
376         
377                 _ipcount=${_iplow}
378                 while [ "${_ipcount}" -le "${_iphigh}" ]; do
379                         eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
380                         _ipcount=$((${_ipcount}+1))
381                         _ret=0
382
383                         # only the first ipaddr in a subnet need the real netmask
384                         if [ "${_action}" != "-alias" ]; then
385                                 _netmask="/32"
386                         fi
387                 done
388         done
389         return $_ret
390 }
391
392 # ifalias_up if
393 #       Configure aliases for network interface $if.
394 #       It returns 0 if at least one alias was configured or
395 #       1 if there were none.
396 #
397 ifalias_up()
398 {
399         _ret=1
400         alias=0
401         while : ; do
402                 ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
403                 if [ -n "${ifconfig_args}" ]; then
404                         ifconfig $1 ${ifconfig_args} alias
405                         alias=$((${alias} + 1))
406                         _ret=0
407                 else
408                         break
409                 fi
410         done
411         return $_ret
412 }
413
414 #ifalias_down if
415 #       Remove aliases for network interface $if.
416 #       It returns 0 if at least one alias was removed or
417 #       1 if there were none.
418 #
419 ifalias_down()
420 {
421         _ret=1
422         alias=0
423         while : ; do
424                 ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
425                 if [ -n "${ifconfig_args}" ]; then
426                         ifconfig $1 ${ifconfig_args} -alias
427                         alias=$((${alias} + 1))
428                         _ret=0
429                 else
430                         break
431                 fi
432         done
433         return $_ret
434 }
435
436 # ifscript_up if
437 #       Evaluate a startup script for the $if interface.
438 #       It returns 0 if a script was found and processed or
439 #       1 if no script was found.
440 #
441 ifscript_up()
442 {
443         if [ -r /etc/start_if.$1 ]; then
444                 . /etc/start_if.$1
445                 return 0
446         fi
447         return 1
448 }
449
450 # ifscript_down if
451 #       Evaluate a shutdown script for the $if interface.
452 #       It returns 0 if a script was found and processed or
453 #       1 if no script was found.
454 #
455 ifscript_down()
456 {
457         if [ -r /etc/stop_if.$1 ]; then
458                 . /etc/stop_if.$1
459                 return 0
460         fi
461         return 1
462 }
463
464 # Create cloneable interfaces.
465 #
466 clone_up()
467 {
468         _prefix=
469         _list=
470         for ifn in ${cloned_interfaces}; do
471                 ifconfig ${ifn} create `get_if_var ${ifn} create_args_IF`
472                 if [ $? -eq 0 ]; then
473                         _list="${_list}${_prefix}${ifn}"
474                         [ -z "$_prefix" ] && _prefix=' '
475                 fi
476         done
477         debug "Cloned: ${_list}"
478 }
479
480 # Destroy cloned interfaces. Destroyed interfaces are echoed
481 # to standard output.
482 #
483 clone_down()
484 {
485         _prefix=
486         _list=
487         for ifn in ${cloned_interfaces}; do
488                 ifconfig ${ifn} destroy
489                 if [ $? -eq 0 ]; then
490                         _list="${_list}${_prefix}${ifn}"
491                         [ -z "$_prefix" ] && _prefix=' '
492                 fi
493         done
494         debug "Destroyed clones: ${_list}"
495 }
496
497 # Create and configure child interfaces.
498 # Return 0 if child interfaces are created.
499 #
500 childif_create()
501 {
502         local cfg child child_wlans create_args debug_flags ifn i
503         cfg=1
504
505         ifn=$1
506
507         # Create wireless interfaces
508         child_wlans=`get_if_var $ifn wlans_IF`
509
510         for child in ${child_wlans}; do
511                 create_args="wlandev $ifn `get_if_var $child create_args_IF`"
512                 debug_flags="`get_if_var $child wlandebug_IF`"
513
514                 if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
515                         ifconfig $child create ${create_args} && cfg=0
516                         if [ -n "${debug_flags}" ]; then
517                                 wlandebug -i $child ${debug_flags}
518                         fi
519                 else
520                         i=`ifconfig wlan create ${create_args}`
521                         if [ -n "${debug_flags}" ]; then
522                                 wlandebug -i $i ${debug_flags}
523                         fi
524                         ifconfig $i name $child && cfg=0
525                 fi
526                 if autoif $child; then
527                         ifn_start $child
528                 fi
529         done
530
531         return ${cfg}
532 }
533
534 # Destroy child interfaces.
535 #
536 childif_destroy()
537 {
538         local cfg child child_wlans ifn
539
540         child_wlans="`get_if_var $ifn wlans_IF` `get_if_var $ifn vaps_IF`"
541         for child in ${child_wlans}; do
542                 ifconfig $child destroy && cfg=0
543         done
544 }
545
546 # Create netgraph nodes.
547 #
548 ng_mkpeer() {
549         ngctl -f - 2> /dev/null <<EOF
550 mkpeer $*
551 msg dummy nodeinfo
552 EOF
553 }
554
555 ng_create_one() {
556         ng_mkpeer $* | while read line; do
557                 t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
558                 if [ -n "${t}" ]; then
559                         echo ${t}
560                         return
561                 fi
562         done
563 }
564
565 gif_up() {
566         for i in ${gif_interfaces}; do
567                 peers=`get_if_var $i gifconfig_IF`
568                 case ${peers} in
569                 '')
570                         continue
571                         ;;
572                 *)
573                         if expr $i : 'gif[0-9][0-9]*$' >/dev/null 2>&1; then
574                                 ifconfig $i create >/dev/null 2>&1
575                         else
576                                 gif=`ifconfig gif create`
577                                 ifconfig $gif name $i
578                         fi
579                         ifconfig $i tunnel ${peers}
580                         ifconfig $i up
581                         ;;
582                 esac
583         done
584 }
585
586 # ng_fec_create ifn
587 # Configure Fast EtherChannel for interface $ifn. Returns 0 if FEC
588 # arguments were found and configured; returns !0 otherwise.
589 ng_fec_create() {
590          local req_iface iface bogus
591          req_iface="$1"
592
593          ngctl shutdown ${req_iface}: > /dev/null 2>&1
594
595          bogus=""
596          while true; do
597                  iface=`ng_create_one fec dummy fec`
598                  if [ -z "${iface}" ]; then
599                          exit 2
600                  fi
601                  if [ "${iface}" = "${req_iface}" ]; then
602                          break
603                  fi
604                  bogus="${bogus} ${iface}"
605          done
606
607          for iface in ${bogus}; do
608                  ngctl shutdown ${iface}:
609          done
610 }
611
612 fec_up() {
613         for i in ${fec_interfaces}; do
614                 ng_fec_create $i
615                 for j in `get_if_var $i fecconfig_IF`; do
616                         case ${j} in
617                         '')
618                                 continue
619                                 ;;
620                         *)
621                                 ngctl msg ${i}: add_iface "\"${j}\""
622                                 ;;
623                         esac
624                 done
625         done
626 }
627
628 #
629 # ipx_up ifn
630 # Configure any IPX addresses for interface $ifn. Returns 0 if IPX
631 # arguments were found and configured; returns 1 otherwise.
632 #
633 ipx_up()
634 {
635         ifn="$1"
636         ifconfig_args=`get_if_var $ifn ifconfig_IF_ipx`
637         if [ -n "${ifconfig_args}" ]; then
638                 ifconfig ${ifn} ${ifconfig_args}
639                 return 0
640         fi
641         return 1
642 }
643
644 # ipx_down ifn
645 #       Remove IPX addresses for interface $ifn. Returns 0 if IPX
646 #       addresses were found and unconfigured. It returns 1, otherwise.
647 #
648 ipx_down()
649 {
650         [ -z "$1" ] && return 1
651         _ifs="^"
652         _ret=1
653
654         ifexists $1 || return 1
655
656         ipxList="`ifconfig $1 | grep 'ipx ' | tr "\n" "$_ifs"`"
657
658         oldifs="$IFS"
659         IFS="$_ifs"
660         for _ipx in $ipxList ; do
661                 # get rid of extraneous line
662                 [ -z "$_ipx" ] && break
663
664                 _ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
665
666                 IFS="$oldifs"
667                 ifconfig $1 ${_ipx} delete
668                 IFS="$_ifs"
669                 _ret=0
670         done
671         IFS="$oldifs"
672
673         return $_ret
674 }
675
676 # ifnet_rename
677 #       Rename all requested interfaces.
678 #
679 ifnet_rename()
680 {
681
682         _ifn_list="`ifconfig -l`"
683         [ -z "$_ifn_list" ] && return 0
684         for _if in ${_ifn_list} ; do
685                 _ifname=`get_if_var $_if ifconfig_IF_name`
686                 if [ ! -z "$_ifname" ]; then
687                         ifconfig $_if name $_ifname
688                 fi
689         done
690         return 0
691 }
692
693 #
694 # list_net_interfaces type
695 #       List all network interfaces. The type of interface returned
696 #       can be controlled by the type argument. The type
697 #       argument can be any of the following:
698 #               nodhcp - all interfaces, excluding DHCP configured interfaces
699 #               dhcp   - list only DHCP configured interfaces
700 #       If no argument is specified all network interfaces are output.
701 #       Note that the list will include cloned interfaces if applicable.
702 #       Cloned interfaces must already exist to have a chance to appear
703 #       in the list if ${network_interfaces} is set to `auto'.
704 #
705 list_net_interfaces()
706 {
707         type=$1
708
709         # Get a list of ALL the interfaces and make lo0 first if it's there.
710         #
711         case ${network_interfaces} in
712         [Aa][Uu][Tt][Oo])
713                 _prefix=''
714                 _autolist="`ifconfig -l`"
715                 _lo=
716                 for _if in ${_autolist} ; do
717                         if autoif $_if; then
718                                 if [ "$_if" = "lo0" ]; then
719                                         _lo="lo0 "
720                                 else
721                                         _tmplist="${_tmplist}${_prefix}${_if}"
722                                         [ -z "$_prefix" ] && _prefix=' '
723                                 fi
724                         fi
725                 done
726                 _tmplist="${_lo}${_tmplist}"
727                 ;;
728         *)
729                 _tmplist="${network_interfaces} ${cloned_interfaces}"
730
731                 # lo0 is effectively mandatory, so help prevent foot-shooting
732                 #
733                 case "$_tmplist" in
734                 lo0|'lo0 '*|*' lo0'|*' lo0 '*) ;; # This is fine, do nothing
735                 *)      _tmplist="lo0 ${_tmplist}" ;;
736                 esac
737                 ;;
738         esac
739
740         if [ -z "$type" ]; then
741                 echo $_tmplist
742                 return 0
743         fi
744
745         # Separate out dhcp and non-dhcp interfaces
746         #
747         _aprefix=
748         _bprefix=
749         for _if in ${_tmplist} ; do
750                 if dhcpif $_if; then
751                         _dhcplist="${_dhcplist}${_aprefix}${_if}"
752                         [ -z "$_aprefix" ] && _aprefix=' '
753                 elif [ -n "`_ifconfig_getargs $_if`" ]; then
754                         _nodhcplist="${_nodhcplist}${_bprefix}${_if}"
755                         [ -z "$_bprefix" ] && _bprefix=' '
756                 fi
757         done
758
759         case "$type" in
760         nodhcp)
761                 echo $_nodhcplist
762                 ;;
763         dhcp)
764                 echo $_dhcplist
765                 ;;
766         esac
767         return 0
768 }
769
770 # get_default_if -address_family
771 #       Get the interface of the default route for the given address family.
772 #       The -address_family argument must be suitable passing to route(8).
773 #
774 get_default_if()
775 {
776         routeget="`route -n get $1 default 2>/dev/null`"
777         oldifs="$IFS"
778         IFS="
779 "
780         defif=
781         for line in $routeget ; do
782                 case $line in
783                 *interface:*)
784                         defif=${line##*: }
785                         ;;
786                 esac
787         done
788         IFS=${oldifs}
789
790         echo $defif
791 }
792
793 hexdigit()
794 {
795         if [ $1 -lt 10 ]; then
796                 echo $1
797         else
798                 case $1 in
799                 10)     echo a ;;
800                 11)     echo b ;;
801                 12)     echo c ;;
802                 13)     echo d ;;
803                 14)     echo e ;;
804                 15)     echo f ;;
805                 esac
806         fi
807 }
808
809 hexprint()
810 {
811         val=$1
812         str=''
813
814         dig=`hexdigit $((${val} & 15))`
815         str=${dig}${str}
816         val=$((${val} >> 4))
817         while [ ${val} -gt 0 ]; do
818                 dig=`hexdigit $((${val} & 15))`
819                 str=${dig}${str}
820                 val=$((${val} >> 4))
821         done
822
823         echo ${str}
824 }
825
826 is_wired_interface()
827 {
828         local media
829
830         case `ifconfig $1 2>/dev/null` in
831         *media:?Ethernet*) media=Ethernet ;;
832         esac
833
834         test "$media" = "Ethernet"
835 }
836
837 # Setup the interfaces for IPv6
838 network6_interface_setup()
839 {
840         interfaces=$*
841         rtsol_interfaces=''
842         case ${ipv6_gateway_enable} in
843         [Yy][Ee][Ss])
844                 rtsol_available=no
845                 ;;
846         *)
847                 rtsol_available=yes
848                 ;;
849         esac
850         for i in $interfaces; do
851                 rtsol_interface=yes
852                 prefix=`get_if_var $i ipv6_prefix_IF`
853                 if [ -n "${prefix}" ]; then
854                         rtsol_available=no
855                         rtsol_interface=no
856                         laddr=`network6_getladdr $i`
857                         hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
858                         for j in ${prefix}; do
859                                 address=$j\:${hostid}
860                                 ifconfig $i inet6 ${address} prefixlen 64 alias
861
862                                 case ${ipv6_gateway_enable} in
863                                 [Yy][Ee][Ss])
864                                         # subnet-router anycast address
865                                         # (rfc2373)
866                                         ifconfig $i inet6 $j:: prefixlen 64 \
867                                                 alias anycast
868                                         ;;
869                                 esac
870                         done
871                 fi
872                 ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF`
873                 if [ -n "${ipv6_ifconfig}" ]; then
874                         rtsol_available=no
875                         rtsol_interface=no
876                         ifconfig $i inet6 ${ipv6_ifconfig} alias
877                 fi
878
879                 # Wireless NIC cards are virtualized through the wlan interface
880                 if ! is_wired_interface ${i}; then
881                         case "${i}" in
882                         wlan*)  rtsol_interface=yes ;;
883                         *)      rtsol_interface=no ;;
884                         esac
885                 fi
886
887                 if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ]
888                 then
889                         case ${i} in
890                         lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*|pflog[0-9]*|pfsync[0-9]*)
891                                 ;;
892                         *)
893                                 rtsol_interfaces="${rtsol_interfaces} ${i}"
894                                 ;;
895                         esac
896                 else
897                         ifconfig $i inet6
898                 fi
899         done
900
901         if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then
902                 # Act as endhost - automatically configured.
903                 # You can configure only single interface, as
904                 # specification assumes that autoconfigured host has
905                 # single interface only.
906                 sysctl net.inet6.ip6.accept_rtadv=1
907                 set ${rtsol_interfaces}
908                 ifconfig $1 up
909                 rtsol ${rtsol_flags} $1
910         fi
911
912         for i in $interfaces; do
913                 alias=0
914                 while : ; do
915                         ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF_alias${alias}`
916                         if [ -z "${ipv6_ifconfig}" ]; then
917                                 break;
918                         fi
919                         ifconfig $i inet6 ${ipv6_ifconfig} alias
920                         alias=$((${alias} + 1))
921                 done
922         done
923 }
924
925 # Setup IPv6 to IPv4 mapping
926 network6_stf_setup()
927 {
928         case ${stf_interface_ipv4addr} in
929         [Nn][Oo] | '')
930                 ;;
931         *)
932                 # assign IPv6 addr and interface route for 6to4 interface
933                 stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
934                 OIFS="$IFS"
935                 IFS=".$IFS"
936                 set ${stf_interface_ipv4addr}
937                 IFS="$OIFS"
938                 hexfrag1=`hexprint $(($1*256 + $2))`
939                 hexfrag2=`hexprint $(($3*256 + $4))`
940                 ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
941                 case ${stf_interface_ipv6_ifid} in
942                 [Aa][Uu][Tt][Oo] | '')
943                         for i in ${ipv6_network_interfaces}; do
944                                 laddr=`network6_getladdr ${i}`
945                                 case ${laddr} in
946                                 '')
947                                         ;;
948                                 *)
949                                         break
950                                         ;;
951                                 esac
952                         done
953                         stf_interface_ipv6_ifid=`expr "${laddr}" : \
954                                                       'fe80::\(.*\)%\(.*\)'`
955                         case ${stf_interface_ipv6_ifid} in
956                         '')
957                                 stf_interface_ipv6_ifid=0:0:0:1
958                                 ;;
959                         esac
960                         ;;
961                 esac
962                 ifconfig stf0 create >/dev/null 2>&1
963                 ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
964                         prefixlen ${stf_prefixlen}
965                 # disallow packets to malicious 6to4 prefix
966                 route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
967                 route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
968                 route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
969                 route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
970                 ;;
971         esac
972 }
973
974 # Setup static routes
975 network6_static_routes_setup()
976 {
977         # Set up any static routes.
978         case ${ipv6_defaultrouter} in
979         [Nn][Oo] | '')
980                 ;;
981         *)
982                 ipv6_static_routes="default ${ipv6_static_routes}"
983                 ipv6_route_default="default ${ipv6_defaultrouter}"
984                 ;;
985         esac
986         case ${ipv6_static_routes} in
987         [Nn][Oo] | '')
988                 ;;
989         *)
990                 for i in ${ipv6_static_routes}; do
991                         ipv6_route_args=`get_if_var $i ipv6_route_IF`
992                         route add -inet6 ${ipv6_route_args}
993                 done
994                 ;;
995         esac
996 }
997
998 # Setup faith
999 network6_faith_setup()
1000 {
1001         case ${ipv6_faith_prefix} in
1002         [Nn][Oo] | '')
1003                 ;;
1004         *)
1005                 sysctl net.inet6.ip6.keepfaith=1
1006                 ifconfig faith0 create >/dev/null 2>&1
1007                 ifconfig faith0 up
1008                 for prefix in ${ipv6_faith_prefix}; do
1009                         prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
1010                         case ${prefixlen} in
1011                         '')
1012                                 prefixlen=96
1013                                 ;;
1014                         *)
1015                                 prefix=`expr "${prefix}" : \
1016                                              "\(.*\)/${prefixlen}"`
1017                                 ;;
1018                         esac
1019                         route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
1020                         route change -inet6 ${prefix} -prefixlen ${prefixlen} \
1021                                 -ifp faith0
1022                 done
1023                 ;;
1024         esac
1025 }
1026
1027 # Install the "default interface" to kernel, which will be used
1028 # as the default route when there's no router.
1029 network6_default_interface_setup()
1030 {
1031         # Choose IPv6 default interface if it is not clearly specified.
1032         case ${ipv6_default_interface} in
1033         '')
1034                 for i in ${ipv6_network_interfaces}; do
1035                         case $i in
1036                         lo0|faith[0-9]*)
1037                                 continue
1038                                 ;;
1039                         esac
1040                         laddr=`network6_getladdr $i exclude_tentative`
1041                         case ${laddr} in
1042                         '')
1043                                 ;;
1044                         *)
1045                                 ipv6_default_interface=$i
1046                                 break
1047                                 ;;
1048                         esac
1049                 done
1050                 ;;
1051         esac
1052
1053         # Disallow unicast packets without outgoing scope identifiers,
1054         # or route such packets to a "default" interface, if it is specified.
1055         route add -inet6 fe80:: -prefixlen 10 ::1 -reject
1056         case ${ipv6_default_interface} in
1057         [Nn][Oo] | '')
1058                 route add -inet6 ff02:: -prefixlen 16 ::1 -reject
1059                 ;;
1060         *)
1061                 laddr=`network6_getladdr ${ipv6_default_interface}`
1062                 route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
1063                         -cloning
1064
1065                 # Disable installing the default interface with the
1066                 # case net.inet6.ip6.forwarding=0 and
1067                 # net.inet6.ip6.accept_rtadv=0, due to avoid conflict
1068                 # between the default router list and the manual
1069                 # configured default route.
1070                 case ${ipv6_gateway_enable} in
1071                 [Yy][Ee][Ss])
1072                         ;;
1073                 *)
1074                         if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ]
1075                         then
1076                                 ndp -I ${ipv6_default_interface}
1077                         fi
1078                         ;;
1079                 esac
1080                 ;;
1081         esac
1082 }
1083
1084 network6_getladdr()
1085 {
1086         ifconfig $1 2>/dev/null | while read proto addr rest; do
1087                 case ${proto} in
1088                 inet6)
1089                         case ${addr} in
1090                         fe80::*)
1091                                 if [ -z "$2" ]; then
1092                                         echo ${addr}
1093                                         return
1094                                 fi
1095                                 case ${rest} in
1096                                 *tentative*)
1097                                         continue
1098                                         ;;
1099                                 *)
1100                                         echo ${addr}
1101                                         return
1102                                 esac
1103                         esac
1104                 esac
1105         done
1106 }