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