]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - etc/network.subr
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.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 IFCONFIG_CMD="/sbin/ifconfig"
28
29 # Maximum number of addresses expanded from a address range specification.
30 _IPEXPANDMAX=31
31
32 #
33 # Subroutines commonly used from network startup scripts.
34 # Requires that rc.conf be loaded first.
35 #
36
37 # ifn_start ifn
38 #       Bring up and configure an interface.  If some configuration is
39 #       applied, print the interface configuration.
40 #
41 ifn_start()
42 {
43         local ifn cfg
44         ifn="$1"
45         cfg=1
46
47         [ -z "$ifn" ] && err 1 "ifn_start called without an interface"
48
49         ifscript_up ${ifn} && cfg=0
50         ifconfig_up ${ifn} && cfg=0
51         if ! noafif $ifn; then
52                 afexists inet && ipv4_up ${ifn} && cfg=0
53                 afexists inet6 && ipv6_up ${ifn} && cfg=0
54                 afexists ipx && ipx_up ${ifn} && cfg=0
55         fi
56         childif_create ${ifn} && cfg=0
57
58         return $cfg
59 }
60
61 # ifn_stop ifn
62 #       Shutdown and de-configure an interface.  If action is taken,
63 #       print the interface name.
64 #
65 ifn_stop()
66 {
67         local ifn cfg
68         ifn="$1"
69         cfg=1
70
71         [ -z "$ifn" ] && err 1 "ifn_stop called without an interface"
72
73         if ! noafif $ifn; then
74                 afexists ipx && ipx_down ${ifn} && cfg=0
75                 afexists inet6 && ipv6_down ${ifn} && cfg=0
76                 afexists inet && ipv4_down ${ifn} && cfg=0
77         fi
78         ifconfig_down ${ifn} && cfg=0
79         ifscript_down ${ifn} && cfg=0
80         childif_destroy ${ifn} && cfg=0
81
82         return $cfg
83 }
84
85 # ifn_vnetup ifn
86 #       Move ifn to the specified vnet jail.
87 #
88 ifn_vnetup()
89 {
90
91         ifn_vnet0 $1 vnet
92 }
93
94 # ifn_vnetdown ifn
95 #       Reclaim ifn from the specified vnet jail.
96 #
97 ifn_vnetdown()
98 {
99
100         ifn_vnet0 $1 -vnet
101 }
102
103 # ifn_vnet0 ifn action
104 #       Helper function for ifn_vnetup and ifn_vnetdown.
105 #
106 ifn_vnet0()
107 {
108         local _ifn _cfg _action _vnet
109         _ifn="$1"
110         _action="$2"
111         _cfg=1
112
113         if _vnet=$(vnetif $_ifn); then
114                 ${IFCONFIG_CMD} $_ifn $_action $_vnet && _cfg=0
115         fi
116
117         return $_cfg
118 }
119
120 # ifconfig_up if
121 #       Evaluate ifconfig(8) arguments for interface $if and
122 #       run ifconfig(8) with those arguments. It returns 0 if
123 #       arguments were found and executed or 1 if the interface
124 #       had no arguments.  Pseudo arguments DHCP and WPA are handled
125 #       here.
126 #
127 ifconfig_up()
128 {
129         local _cfg _ipv6_opts ifconfig_args
130         _cfg=1
131
132         # Make sure lo0 always comes up.
133         if [ "$1" = "lo0" ]; then
134                 _cfg=0
135         fi
136
137         # ifconfig_IF
138         ifconfig_args=`ifconfig_getargs $1`
139         if [ -n "${ifconfig_args}" ]; then
140                 eval ${IFCONFIG_CMD} $1 ${ifconfig_args}
141                 _cfg=0
142         fi
143
144         # inet6 specific
145         if ! noafif $1 && afexists inet6; then
146                 if checkyesno ipv6_activate_all_interfaces; then
147                         _ipv6_opts="-ifdisabled"
148                 elif [ "$1" != "lo0" ]; then
149                         _ipv6_opts="ifdisabled"
150                 fi
151
152                 # backward compatibility: $ipv6_enable
153                 case $ipv6_enable in
154                 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
155                         case $1 in
156                         bridge[0-9]*)
157                                 # No accept_rtadv by default on if_bridge(4)
158                                 # to avoid a conflict with the member
159                                 # interfaces.
160                         ;;
161                         *)
162                                 if ! checkyesno ipv6_gateway_enable; then
163                                         _ipv6_opts="${_ipv6_opts} accept_rtadv"
164                                 fi
165                         ;;
166                         esac
167                 ;;
168                 esac
169
170                 case $ipv6_cpe_wanif in
171                 $1)
172                         _ipv6_opts="${_ipv6_opts} -no_radr accept_rtadv"
173                 ;;
174                 esac
175
176                 if [ -n "${_ipv6_opts}" ]; then
177                         ${IFCONFIG_CMD} $1 inet6 ${_ipv6_opts}
178                 fi
179
180                 # ifconfig_IF_ipv6
181                 ifconfig_args=`ifconfig_getargs $1 ipv6`
182                 if [ -n "${ifconfig_args}" ]; then
183                         # backward compatibility: inet6 keyword
184                         case "${ifconfig_args}" in
185                         :*|[0-9a-fA-F]*:*)
186                                 warn "\$ifconfig_$1_ipv6 needs " \
187                                     "\"inet6\" keyword for an IPv6 address."
188                                 ifconfig_args="inet6 ${ifconfig_args}"
189                         ;;
190                         esac
191                         ${IFCONFIG_CMD} $1 inet6 -ifdisabled
192                         eval ${IFCONFIG_CMD} $1 ${ifconfig_args}
193                         _cfg=0
194                 fi
195
196                 # $ipv6_prefix_IF will be handled in
197                 # ipv6_prefix_hostid_addr_common().
198                 ifconfig_args=`get_if_var $1 ipv6_prefix_IF`
199                 if [ -n "${ifconfig_args}" ]; then
200                         ${IFCONFIG_CMD} $1 inet6 -ifdisabled
201                         _cfg=0
202                 fi
203
204                 # backward compatibility: $ipv6_ifconfig_IF
205                 ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF`
206                 if [ -n "${ifconfig_args}" ]; then
207                         warn "\$ipv6_ifconfig_$1 is obsolete." \
208                             "  Use ifconfig_$1_ipv6 instead."
209                         ${IFCONFIG_CMD} $1 inet6 -ifdisabled
210                         eval ${IFCONFIG_CMD} $1 inet6 ${ifconfig_args}
211                         _cfg=0
212                 fi
213         fi
214
215         ifalias $1 link alias
216         ifalias $1 ether alias
217
218         if [ ${_cfg} -eq 0 ]; then
219                 ${IFCONFIG_CMD} $1 up
220         fi
221
222         if wpaif $1; then
223                 /etc/rc.d/wpa_supplicant start $1
224                 _cfg=0          # XXX: not sure this should count
225         elif hostapif $1; then
226                 /etc/rc.d/hostapd start $1
227                 _cfg=0
228         fi
229
230         if dhcpif $1; then
231                 if [ $_cfg -ne 0 ] ; then
232                         ${IFCONFIG_CMD} $1 up
233                 fi
234                 if syncdhcpif $1; then
235                         /etc/rc.d/dhclient start $1
236                 fi
237                 _cfg=0
238         fi
239
240         return $_cfg
241 }
242
243 # ifconfig_down if
244 #       returns 1 if wpa_supplicant or dhclient was stopped or
245 #       the interface exists.
246 #
247 ifconfig_down()
248 {
249         local _cfg
250         _cfg=1
251
252         if wpaif $1; then
253                 /etc/rc.d/wpa_supplicant stop $1
254                 _cfg=0
255         elif hostapif $1; then
256                 /etc/rc.d/hostapd stop $1
257                 _cfg=0
258         fi
259
260         if dhcpif $1; then
261                 /etc/rc.d/dhclient stop $1
262                 _cfg=0
263         fi
264
265         if ifexists $1; then
266                 ${IFCONFIG_CMD} $1 down
267                 _cfg=0
268         fi
269
270         return $_cfg
271 }
272
273 # get_if_var if var [default]
274 #       Return the value of the pseudo-hash corresponding to $if where
275 #       $var is a string containg the sub-string "IF" which will be
276 #       replaced with $if after the characters defined in _punct are
277 #       replaced with '_'. If the variable is unset, replace it with
278 #       $default if given.
279 get_if_var()
280 {
281         local _if _punct _punct_c _var _default prefix suffix
282
283         if [ $# -ne 2 -a $# -ne 3 ]; then
284                 err 3 'USAGE: get_if_var name var [default]'
285         fi
286
287         _if=$1
288         _punct=". - / +"
289         for _punct_c in $_punct; do
290                 _if=`ltr ${_if} ${_punct_c} '_'`
291         done
292         _var=$2
293         _default=$3
294
295         prefix=${_var%%IF*}
296         suffix=${_var##*IF}
297         eval echo \${${prefix}${_if}${suffix}-${_default}}
298 }
299
300 # _ifconfig_getargs if [af]
301 #       Prints the arguments for the supplied interface to stdout.
302 #       Returns 1 if empty.  In general, ifconfig_getargs should be used
303 #       outside this file.
304 _ifconfig_getargs()
305 {
306         local _ifn _af
307         _ifn=$1
308         _af=${2+_$2}
309
310         if [ -z "$_ifn" ]; then
311                 return 1
312         fi
313
314         get_if_var $_ifn ifconfig_IF$_af "$ifconfig_DEFAULT"
315 }
316
317 # ifconfig_getargs if [af]
318 #       Takes the result from _ifconfig_getargs and removes pseudo
319 #       args such as DHCP and WPA.
320 ifconfig_getargs()
321 {
322         local _tmpargs _arg _args _vnet
323         _tmpargs=`_ifconfig_getargs $1 $2`
324         if [ $? -eq 1 ]; then
325                 return 1
326         fi
327         _args=
328         _vnet=0
329
330         for _arg in $_tmpargs; do
331                 case $_arg:$_vnet in
332                 [Dd][Hh][Cc][Pp]:0) ;;
333                 [Nn][Oo][Aa][Uu][Tt][Oo]:0) ;;
334                 [Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]:0) ;;
335                 [Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]:0) ;;
336                 [Ww][Pp][Aa]:0) ;;
337                 [Hh][Oo][Ss][Tt][Aa][Pp]:0) ;;
338                 vnet:0) _vnet=1 ;;
339                 *:1)    _vnet=0 ;;
340                 *:0)
341                         _args="$_args $_arg"
342                 ;;
343                 esac
344         done
345
346         echo $_args
347 }
348
349 # autoif
350 #       Returns 0 if the interface should be automatically configured at
351 #       boot time and 1 otherwise.
352 autoif()
353 {
354         local _tmpargs _arg
355         _tmpargs=`_ifconfig_getargs $1`
356
357         for _arg in $_tmpargs; do
358                 case $_arg in
359                 [Nn][Oo][Aa][Uu][Tt][Oo])
360                         return 1
361                         ;;
362                 esac
363         done
364
365         return 0
366 }
367
368 # dhcpif if
369 #       Returns 0 if the interface is a DHCP interface and 1 otherwise.
370 dhcpif()
371 {
372         local _tmpargs _arg
373         _tmpargs=`_ifconfig_getargs $1`
374
375         case $1 in
376         lo[0-9]*|\
377         stf[0-9]*|\
378         faith[0-9]*|\
379         lp[0-9]*|\
380         sl[0-9]*)
381                 return 1
382                 ;;
383         esac
384         if noafif $1; then
385                 return 1
386         fi
387
388         for _arg in $_tmpargs; do
389                 case $_arg in
390                 [Dd][Hh][Cc][Pp])
391                         return 0
392                         ;;
393                 [Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
394                         return 0
395                         ;;
396                 [Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
397                         return 0
398                         ;;
399                 esac
400         done
401
402         return 1
403 }
404
405 # syncdhcpif
406 #       Returns 0 if the interface should be configured synchronously and
407 #       1 otherwise.
408 syncdhcpif()
409 {
410         local _tmpargs _arg
411         _tmpargs=`_ifconfig_getargs $1`
412
413         if noafif $1; then
414                 return 1
415         fi
416
417         for _arg in $_tmpargs; do
418                 case $_arg in
419                 [Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
420                         return 1
421                         ;;
422                 [Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
423                         return 0
424                         ;;
425                 esac
426         done
427
428         checkyesno synchronous_dhclient
429 }
430
431 # wpaif if
432 #       Returns 0 if the interface is a WPA interface and 1 otherwise.
433 wpaif()
434 {
435         local _tmpargs _arg
436         _tmpargs=`_ifconfig_getargs $1`
437
438         for _arg in $_tmpargs; do
439                 case $_arg in
440                 [Ww][Pp][Aa])
441                         return 0
442                         ;;
443                 esac
444         done
445
446         return 1
447 }
448
449 # hostapif if
450 #       Returns 0 if the interface is a HOSTAP interface and 1 otherwise.
451 hostapif()
452 {
453         local _tmpargs _arg
454         _tmpargs=`_ifconfig_getargs $1`
455
456         for _arg in $_tmpargs; do
457                 case $_arg in
458                 [Hh][Oo][Ss][Tt][Aa][Pp])
459                         return 0
460                         ;;
461                 esac
462         done
463
464         return 1
465 }
466
467 # vnetif if
468 #       Returns 0 and echo jail if "vnet" keyword is specified on the
469 #       interface, and 1 otherwise.
470 vnetif()
471 {
472         local _tmpargs _arg _vnet
473         _tmpargs=`_ifconfig_getargs $1`
474
475         _vnet=0
476         for _arg in $_tmpargs; do
477                 case $_arg:$_vnet in
478                 vnet:0) _vnet=1 ;;
479                 *:1)    echo $_arg; return 0 ;;
480                 esac
481         done
482
483         return 1
484 }
485
486 # afexists af
487 #       Returns 0 if the address family is enabled in the kernel
488 #       1 otherwise.
489 afexists()
490 {
491         local _af
492         _af=$1
493
494         case ${_af} in
495         inet|inet6)
496                 check_kern_features ${_af}
497                 ;;
498         ipx)
499                 ${SYSCTL_N} net.ipx > /dev/null 2>&1
500                 ;;
501         atm)
502                 if [ -x /sbin/atmconfig ]; then
503                         /sbin/atmconfig diag list > /dev/null 2>&1
504                 else
505                         return 1
506                 fi
507                 ;;
508         link|ether)
509                 return 0
510                 ;;
511         *)
512                 err 1 "afexists(): Unsupported address family: $_af"
513                 ;;
514         esac
515 }
516
517 # noafif if
518 #       Returns 0 if the interface has no af configuration and 1 otherwise.
519 noafif()
520 {
521         local _if
522         _if=$1
523
524         case $_if in
525         pflog[0-9]*|\
526         pfsync[0-9]*|\
527         usbus[0-9]*|\
528         an[0-9]*|\
529         ath[0-9]*|\
530         ipw[0-9]*|\
531         ipfw[0-9]*|\
532         iwi[0-9]*|\
533         iwn[0-9]*|\
534         ral[0-9]*|\
535         wi[0-9]*|\
536         wl[0-9]*|\
537         wpi[0-9]*)
538                 return 0
539                 ;;
540         esac
541
542         return 1
543 }
544
545 # ipv6if if
546 #       Returns 0 if the interface should be configured for IPv6 and
547 #       1 otherwise.
548 ipv6if()
549 {
550         local _if _tmpargs i
551         _if=$1
552
553         if ! afexists inet6; then
554                 return 1
555         fi
556
557         # lo0 is always IPv6-enabled
558         case $_if in
559         lo0)
560                 return 0
561                 ;;
562         esac
563
564         case "${ipv6_network_interfaces}" in
565         $_if|"$_if "*|*" $_if"|*" $_if "*|[Aa][Uu][Tt][Oo])
566                 # True if $ifconfig_IF_ipv6 is defined.
567                 _tmpargs=`_ifconfig_getargs $_if ipv6`
568                 if [ -n "${_tmpargs}" ]; then
569                         return 0
570                 fi
571
572                 # True if $ipv6_prefix_IF is defined.
573                 _tmpargs=`get_if_var $_if ipv6_prefix_IF`
574                 if [ -n "${_tmpargs}" ]; then
575                         return 0
576                 fi
577
578                 # backward compatibility: True if $ipv6_ifconfig_IF is defined.
579                 _tmpargs=`get_if_var $_if ipv6_ifconfig_IF`
580                 if [ -n "${_tmpargs}" ]; then
581                         return 0
582                 fi
583                 ;;
584         esac
585
586         return 1
587 }
588
589 # ipv6_autoconfif if
590 #       Returns 0 if the interface should be configured for IPv6 with
591 #       Stateless Address Configuration; 1 otherwise.
592 ipv6_autoconfif()
593 {
594         local _if _tmpargs _arg
595         _if=$1
596
597         case $_if in
598         lo[0-9]*|\
599         stf[0-9]*|\
600         faith[0-9]*|\
601         lp[0-9]*|\
602         sl[0-9]*)
603                 return 1
604                 ;;
605         esac
606         if noafif $_if; then
607                 return 1
608         fi
609         if ! ipv6if $_if; then
610                 return 1
611         fi
612         if checkyesno ipv6_gateway_enable; then
613                 return 1
614         fi
615         _tmpargs=`get_if_var $_if ipv6_prefix_IF`
616         if [ -n "${_tmpargs}" ]; then
617                 return 1
618         fi
619         # backward compatibility: $ipv6_enable
620         case $ipv6_enable in
621         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
622                 if checkyesno ipv6_gateway_enable; then
623                         return 1
624                 fi
625                 case $1 in
626                 bridge[0-9]*)
627                         # No accept_rtadv by default on if_bridge(4)
628                         # to avoid a conflict with the member
629                         # interfaces.
630                         return 1
631                 ;;
632                 *)
633                         return 0
634                 ;;
635                 esac
636         ;;
637         esac
638
639         _tmpargs=`_ifconfig_getargs $_if ipv6`
640         for _arg in $_tmpargs; do
641                 case $_arg in
642                 accept_rtadv)
643                         return 0
644                         ;;
645                 esac
646         done
647
648         # backward compatibility: $ipv6_ifconfig_IF
649         _tmpargs=`get_if_var $_if ipv6_ifconfig_IF`
650         for _arg in $_tmpargs; do
651                 case $_arg in
652                 accept_rtadv)
653                         return 0
654                         ;;
655                 esac
656         done
657
658         return 1
659 }
660
661 # ifexists if
662 #       Returns 0 if the interface exists and 1 otherwise.
663 ifexists()
664 {
665         [ -z "$1" ] && return 1
666         ${IFCONFIG_CMD} -n $1 > /dev/null 2>&1
667 }
668
669 # ipv4_up if
670 #       add IPv4 addresses to the interface $if
671 ipv4_up()
672 {
673         local _if _ret
674         _if=$1
675         _ret=1
676
677         # Add 127.0.0.1/8 to lo0 unless otherwise specified.
678         if [ "${_if}" = "lo0" ]; then
679                 ifconfig_args=`get_if_var ${_if} ifconfig_IF`
680                 if [ -z "${ifconfig_args}" ]; then
681                         ${IFCONFIG_CMD} ${_if} inet 127.0.0.1/8 alias
682                 fi
683         fi
684         ifalias ${_if} inet alias && _ret=0
685
686         return $_ret
687 }
688
689 # ipv6_up if
690 #       add IPv6 addresses to the interface $if
691 ipv6_up()
692 {
693         local _if _ret
694         _if=$1
695         _ret=1
696
697         if ! ipv6if $_if; then
698                 return 0
699         fi
700
701         ifalias ${_if} inet6 alias && _ret=0
702         ipv6_prefix_hostid_addr_common ${_if} alias && _ret=0
703         ipv6_accept_rtadv_up ${_if} && _ret=0
704
705         return $_ret
706 }
707
708 # ipv4_down if
709 #       remove IPv4 addresses from the interface $if
710 ipv4_down()
711 {
712         local _if _ifs _ret inetList oldifs _inet
713         _if=$1
714         _ifs="^"
715         _ret=1
716
717         ifalias ${_if} inet -alias && _ret=0
718
719         inetList="`${IFCONFIG_CMD} ${_if} | grep 'inet ' | tr "\n\t" "$_ifs"`"
720
721         oldifs="$IFS"
722         IFS="$_ifs"
723         for _inet in $inetList ; do
724                 # get rid of extraneous line
725                 case $_inet in
726                 inet\ *)        ;;
727                 *)              continue ;;
728                 esac
729
730                 _inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
731
732                 IFS="$oldifs"
733                 ${IFCONFIG_CMD} ${_if} ${_inet} delete
734                 IFS="$_ifs"
735                 _ret=0
736         done
737         IFS="$oldifs"
738
739         return $_ret
740 }
741
742 # ipv6_down if
743 #       remove IPv6 addresses from the interface $if
744 ipv6_down()
745 {
746         local _if _ifs _ret inetList oldifs _inet6
747         _if=$1
748         _ifs="^"
749         _ret=1
750
751         if ! ipv6if $_if; then
752                 return 0
753         fi
754
755         ipv6_accept_rtadv_down ${_if} && _ret=0
756         ipv6_prefix_hostid_addr_common ${_if} -alias && _ret=0
757         ifalias ${_if} inet6 -alias && _ret=0
758
759         inetList="`${IFCONFIG_CMD} ${_if} | grep 'inet6 ' | tr "\n\t" "$_ifs"`"
760
761         oldifs="$IFS"
762         IFS="$_ifs"
763         for _inet6 in $inetList ; do
764                 # get rid of extraneous line
765                 case $_inet in
766                 inet6\ *)       ;;
767                 *)              continue ;;
768                 esac
769
770                 _inet6=`expr "$_inet6" : '.*\(inet6 \([0-9a-f:]*\)\).*'`
771
772                 IFS="$oldifs"
773                 ${IFCONFIG_CMD} ${_if} ${_inet6} -alias
774                 IFS="$_ifs"
775                 _ret=0
776         done
777         IFS="$oldifs"
778
779         return $_ret
780 }
781
782 # ifalias if af action
783 #       Configure or remove aliases for network interface $if.
784 #       It returns 0 if at least one alias was configured or
785 #       removed, or 1 if there were none.
786 #
787 ifalias()
788 {
789         local _ret
790         _ret=1
791
792         afexists $2 || return $_ret
793
794         case "$2" in
795         inet|inet6|link|ether)
796                 ifalias_af_common $1 $2 $3 && _ret=0
797                 ;;
798         esac
799
800         return $_ret
801 }
802
803 # ifalias_expand_addr af action addr
804 #       Expand address range ("N-M") specification in addr.
805 #       "addr" must not include an address-family keyword.
806 #       The results will include an address-family keyword.
807 #
808 ifalias_expand_addr()
809 {
810         local _af _action
811
812         _af=$1
813         _action=$2
814         shift 2
815
816         afexists $_af || return
817         ifalias_expand_addr_$_af $_action $*
818 }
819
820 # ifalias_expand_addr_inet action addr
821 #       Helper function for ifalias_expand_addr().  Handles IPv4.
822 #
823 ifalias_expand_addr_inet()
824 {
825         local _action _arg _cidr _cidr_addr _exargs
826         local _ipaddr _plen _range _iphead _iptail _iplow _iphigh _ipcount
827         local _retstr _c
828         _action=$1
829         _arg=$2
830         shift 2
831         _exargs=$*
832         _retstr=
833
834         case $_action:$_arg:$_exargs in
835         *:*--*)         return ;;       # invalid
836         tmp:*[0-9]-[0-9]*:*)            # to be expanded
837                 _action="alias"
838         ;;
839         *:*[0-9]-[0-9]*:*)              # to be expanded
840         ;;
841         tmp:*:*netmask*)                # already expanded w/ netmask option
842                 echo ${_arg%/[0-9]*} $_exargs && return
843         ;;
844         tmp:*:*)                        # already expanded w/o netmask option
845                 echo $_arg $_exargs && return
846         ;;
847         *:*:*netmask*)                  # already expanded w/ netmask option
848                 echo inet ${_arg%/[0-9]*} $_exargs && return
849         ;;
850         *:*:*)                          # already expanded w/o netmask option
851                 echo inet $_arg $_exargs && return
852         ;;
853         esac
854
855         for _cidr in $_arg; do
856                 _ipaddr=${_cidr%%/*}
857                 _plen=${_cidr##*/}
858                 # When subnet prefix length is not specified, use /32.
859                 case $_plen in
860                 $_ipaddr)       _plen=32 ;;     # "/" character not found
861                 esac
862
863                 OIFS=$IFS
864                 IFS=. set -- $_ipaddr
865                 _range=
866                 _iphead=
867                 _iptail=
868                 for _c in $@; do
869                         case $_range:$_c in
870                         :[0-9]*-[0-9]*)
871                                 _range=$_c
872                         ;;
873                         :*)
874                                 _iphead="${_iphead}${_iphead:+.}${_c}"
875                         ;;
876                         *:*)
877                                 _iptail="${_iptail}${_iptail:+.}${_c}"
878                         ;;
879                         esac
880                 done
881                 IFS=$OIFS
882                 _iplow=${_range%-*}
883                 _iphigh=${_range#*-}
884
885                 # clear netmask when removing aliases
886                 if [ "$_action" = "-alias" ]; then
887                         _plen=""
888                 fi
889
890                 _ipcount=$_iplow
891                 while [ "$_ipcount" -le "$_iphigh" ]; do
892                         _retstr="${_retstr} ${_iphead}${_iphead:+.}${_ipcount}${_iptail:+.}${_iptail}${_plen:+/}${_plen}"
893                         if [ $_ipcount -gt $(($_iplow + $_IPEXPANDMAX)) ]; then
894                                 warn "Range specification is too large (${_iphead}${_iphead:+.}${_iplow}${_iptail:+.}${_iptail}-${_iphead}${_iphead:+.}${_iphigh}${_iptail:+.}${_iptail}).  ${_iphead}${_iphead:+.}${_iplow}${_iptail:+.}${_iptail}-${_iphead}${_iphead:+.}${_ipcount}${_iptail:+.}${_iptail} was processed."
895                                 break
896                         else
897                                 _ipcount=$(($_ipcount + 1))
898                         fi
899                         # Forcibly set /32 for remaining aliases.
900                         _plen=32
901                 done
902         done
903
904         for _c in $_retstr; do
905                 ifalias_expand_addr_inet $_action $_c $_exargs
906         done
907 }
908
909 # ifalias_expand_addr_inet6 action addr
910 #       Helper function for ifalias_expand_addr().  Handles IPv6.
911 #
912 ifalias_expand_addr_inet6()
913 {
914         local _action _arg _cidr _cidr_addr _exargs
915         local _ipaddr _plen _ipleft _ipright _iplow _iphigh _ipcount
916         local _ipv4part
917         local _retstr _c
918         _action=$1
919         _arg=$2
920         shift 2
921         _exargs=$*
922         _retstr=
923
924         case $_action:$_arg:$_exargs in
925         *:*--*:*)       return ;;       # invalid
926         tmp:*[0-9a-zA-Z]-[0-9a-zA-Z]*:*)# to be expanded
927                 _action="alias"
928         ;;
929         *:*[0-9a-zA-Z]-[0-9a-zA-Z]*:*)  # to be expanded
930         ;;
931         tmp:*:*prefixlen*)      # already expanded w/ prefixlen option
932                 echo ${_arg%/[0-9]*} $_exargs && return
933         ;;
934         tmp:*:*)                # already expanded w/o prefixlen option
935                 echo $_arg $_exargs && return
936         ;;
937         *:*:*prefixlen*)        # already expanded w/ prefixlen option
938                 echo inet6 ${_arg%/[0-9]*} $_exargs && return
939         ;;
940         *:*:*)                  # already expanded w/o prefixlen option
941                 echo inet6 $_arg $_exargs && return
942         ;;
943         esac
944
945         for _cidr in $_arg; do
946                 _ipaddr="${_cidr%%/*}"
947                 _plen="${_cidr##*/}"
948
949                 case $_action:$_ipaddr:$_cidr in
950                 -alias:*:*)             unset _plen ;;
951                 *:$_cidr:$_ipaddr)      unset _plen ;;
952                 esac
953
954                 if [ "${_ipaddr%:*.*.*.*}" = "$_ipaddr" ]; then
955                         # Handle !v4mapped && !v4compat addresses.
956
957                         # The default prefix length is 64.
958                         case $_ipaddr:$_cidr in
959                         $_cidr:$_ipaddr)        _plen="64" ;;
960                         esac
961                         _ipleft=${_ipaddr%-*}
962                         _ipright=${_ipaddr#*-}
963                         _iplow=${_ipleft##*:}
964                         _iphigh=${_ipright%%:*}
965                         _ipleft=${_ipleft%:*}
966                         _ipright=${_ipright#*:}
967
968                         if [ "$_iphigh" = "$_ipright" ]; then
969                                 unset _ipright
970                         else
971                                 _ipright=:$_ipright
972                         fi
973
974                         if [ -n "$_iplow" -a -n "$_iphigh" ]; then
975                                 _iplow=$((0x$_iplow))
976                                 _iphigh=$((0x$_iphigh))
977                                 _ipcount=$_iplow
978                                 while [ $_ipcount -le $_iphigh ]; do
979                                         _r=`printf "%s:%04x%s%s" \
980                                             $_ipleft $_ipcount $_ipright \
981                                             ${_plen:+/}$_plen`
982                                         _retstr="$_retstr $_r"
983                                         if [ $_ipcount -gt $(($_iplow + $_IPEXPANDMAX)) ]
984                                         then
985                                                 warn "Range specification is too large $(printf '(%s:%04x%s-%s:%04x%s)' $_ipleft $_iplow $_ipright $_ipleft $_iphigh $_ipright). $(printf '%s:%04x%s-%s:%04x%s' $_ipleft $_iplow $_ipright $_ipleft $_ipcount $_ipright) was processed."
986                                                 break
987                                         else
988                                                 _ipcount=$(($_ipcount + 1))
989                                         fi
990                                 done
991                         else
992                                 _retstr="${_ipaddr}${_plen:+/}${_plen}"
993                         fi
994
995                         for _c in $_retstr; do
996                                 ifalias_expand_addr_inet6 $_action $_c $_exargs
997                         done
998                 else
999                         # v4mapped/v4compat should handle as an IPv4 alias
1000                         _ipv4part=${_ipaddr##*:}
1001
1002                         # Adjust prefix length if any.  If not, set the
1003                         # default prefix length as 32.
1004                         case $_ipaddr:$_cidr in
1005                         $_cidr:$_ipaddr)        _plen=32 ;;
1006                         *)                      _plen=$(($_plen - 96)) ;;
1007                         esac
1008
1009                         _retstr=`ifalias_expand_addr_inet \
1010                             tmp ${_ipv4part}${_plen:+/}${_plen}`
1011                         for _c in $_retstr; do
1012                                 ifalias_expand_addr_inet $_action $_c $_exargs
1013                         done
1014                 fi
1015         done
1016 }
1017
1018 # ifalias_af_common_handler if af action args
1019 #       Helper function for ifalias_af_common().
1020 #
1021 ifalias_af_common_handler()
1022 {
1023         local _ret _if _af _action _args _c _tmpargs
1024
1025         _ret=1
1026         _if=$1
1027         _af=$2
1028         _action=$3
1029         shift 3
1030         _args=$*
1031
1032         case $_args in
1033         ${_af}\ *)      ;;
1034         *)      return  ;;
1035         esac
1036
1037         # link(ether) does not support address removal.
1038         case $_af:$_action in
1039         link:-alias|ether:-alias)       return ;;
1040         esac
1041
1042         _tmpargs=
1043         for _c in $_args; do
1044                 case $_c in
1045                 ${_af})
1046                         case $_tmpargs in
1047                         ${_af}\ *-*)
1048                                 ifalias_af_common_handler $_if $_af $_action \
1049                                 `ifalias_expand_addr $_af $_action ${_tmpargs#${_af}\ }`
1050                         ;;
1051                         ${_af}\ *)
1052                                 ${IFCONFIG_CMD} $_if $_tmpargs $_action && _ret=0
1053                         ;;
1054                         esac
1055                         _tmpargs=$_af
1056                 ;;
1057                 *)
1058                         _tmpargs="$_tmpargs $_c"
1059                 ;;
1060                 esac
1061         done
1062         # Process the last component if any.
1063         if [ -n "$_tmpargs}" ]; then
1064                 case $_tmpargs in
1065                 ${_af}\ *-*)
1066                         ifalias_af_common_handler $_if $_af $_action \
1067                         `ifalias_expand_addr $_af $_action ${_tmpargs#${_af}\ }`
1068                 ;;
1069                 ${_af}\ *)
1070                         ${IFCONFIG_CMD} $_if $_tmpargs $_action && _ret=0
1071                 ;;
1072                 esac
1073         fi
1074
1075         return $_ret
1076 }
1077
1078 # ifalias_af_common if af action
1079 #       Helper function for ifalias().
1080 #
1081 ifalias_af_common()
1082 {
1083         local _ret _if _af _action alias ifconfig_args _aliasn _c _tmpargs _iaf
1084
1085         _ret=1
1086         _aliasn=
1087         _if=$1
1088         _af=$2
1089         _action=$3
1090
1091         # ifconfig_IF_aliasN which starts with $_af
1092         alias=0
1093         while : ; do
1094                 ifconfig_args=`get_if_var $_if ifconfig_IF_alias${alias}`
1095                 _iaf=
1096                 case $ifconfig_args in
1097                 inet\ *)        _iaf=inet ;;
1098                 inet6\ *)       _iaf=inet6 ;;
1099                 ipx\ *)         _iaf=ipx ;;
1100                 link\ *)        _iaf=link ;;
1101                 ether\ *)       _iaf=ether ;;
1102                 esac
1103
1104                 case ${_af}:${_action}:${_iaf}:"${ifconfig_args}" in
1105                 ${_af}:*:${_af}:*)
1106                         _aliasn="$_aliasn $ifconfig_args"
1107                         ;;
1108                 ${_af}:*:"":"")
1109                         break
1110                         ;;
1111                 inet:alias:"":*)
1112                         _aliasn="$_aliasn inet $ifconfig_args"
1113                         warn "\$ifconfig_${_if}_alias${alias} needs " \
1114                             "\"inet\" keyword for an IPv4 address."
1115                 esac
1116                 alias=$(($alias + 1))
1117         done
1118
1119         # backward compatibility: ipv6_ifconfig_IF_aliasN.
1120         case $_af in
1121         inet6)
1122                 alias=0
1123                 while : ; do
1124                         ifconfig_args=`get_if_var $_if ipv6_ifconfig_IF_alias${alias}`
1125                         case ${_action}:"${ifconfig_args}" in
1126                         *:"")
1127                                 break
1128                         ;;
1129                         alias:*)
1130                                 _aliasn="${_aliasn} inet6 ${ifconfig_args}"
1131                                 warn "\$ipv6_ifconfig_${_if}_alias${alias} " \
1132                                     "is obsolete.  Use ifconfig_$1_aliasN " \
1133                                     "instead."
1134                         ;;
1135                         esac
1136                         alias=$(($alias + 1))
1137                 done
1138         esac
1139
1140         # backward compatibility: ipv4_addrs_IF.
1141         for _tmpargs in `get_if_var $_if ipv4_addrs_IF`; do
1142                 _aliasn="$_aliasn inet $_tmpargs"
1143         done
1144
1145         # Handle ifconfig_IF_aliases, ifconfig_IF_aliasN, and the others.
1146         _tmpargs=
1147         for _c in `get_if_var $_if ifconfig_IF_aliases` $_aliasn; do
1148                 case $_c in
1149                 inet|inet6|ipx|link|ether)
1150                         case $_tmpargs in
1151                         ${_af}\ *)
1152                                 eval ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1153                         ;;
1154                         esac
1155                         _tmpargs=$_c
1156                 ;;
1157                 *)
1158                         _tmpargs="$_tmpargs $_c"
1159                 esac
1160         done
1161         # Process the last component
1162         case $_tmpargs in
1163         ${_af}\ *)
1164                 ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1165         ;;
1166         esac
1167
1168         return $_ret
1169 }
1170
1171 # ipv6_prefix_hostid_addr_common if action
1172 #       Add or remove IPv6 prefix + hostid addr on the interface $if
1173 #
1174 ipv6_prefix_hostid_addr_common()
1175 {
1176         local _if _action prefix j
1177         _if=$1
1178         _action=$2
1179         prefix=`get_if_var ${_if} ipv6_prefix_IF`
1180
1181         if [ -n "${prefix}" ]; then
1182                 for j in ${prefix}; do
1183                         # The default prefixlen is 64.
1184                         plen=${j#*/}
1185                         case $j:$plen in
1186                         $plen:$j)       plen=64 ;;
1187                         *)              j=${j%/*} ;;
1188                         esac
1189
1190                         # Normalize the last part by removing ":"
1191                         j=${j%::*}
1192                         j=${j%:}
1193                         ${IFCONFIG_CMD} ${_if} inet6 $j:: \
1194                                 prefixlen $plen eui64 ${_action}
1195
1196                         # if I am a router, add subnet router
1197                         # anycast address (RFC 2373).
1198                         if checkyesno ipv6_gateway_enable; then
1199                                 ${IFCONFIG_CMD} ${_if} inet6 $j:: \
1200                                         prefixlen $plen ${_action} anycast
1201                         fi
1202                 done
1203         fi
1204 }
1205
1206 # ipv6_accept_rtadv_up if
1207 #       Enable accepting Router Advertisement and send Router
1208 #       Solicitation message
1209 ipv6_accept_rtadv_up()
1210 {
1211         if ipv6_autoconfif $1; then
1212                 ${IFCONFIG_CMD} $1 inet6 accept_rtadv up
1213                 if ! checkyesno rtsold_enable; then
1214                         rtsol ${rtsol_flags} $1
1215                 fi
1216         fi
1217 }
1218
1219 # ipv6_accept_rtadv_down if
1220 #       Disable accepting Router Advertisement
1221 ipv6_accept_rtadv_down()
1222 {
1223         if ipv6_autoconfif $1; then
1224                 ${IFCONFIG_CMD} $1 inet6 -accept_rtadv
1225         fi
1226 }
1227
1228 # ifscript_up if
1229 #       Evaluate a startup script for the $if interface.
1230 #       It returns 0 if a script was found and processed or
1231 #       1 if no script was found.
1232 #
1233 ifscript_up()
1234 {
1235         if [ -r /etc/start_if.$1 ]; then
1236                 . /etc/start_if.$1
1237                 return 0
1238         else
1239                 return 1
1240         fi
1241 }
1242
1243 # ifscript_down if
1244 #       Evaluate a shutdown script for the $if interface.
1245 #       It returns 0 if a script was found and processed or
1246 #       1 if no script was found.
1247 #
1248 ifscript_down()
1249 {
1250         if [ -r /etc/stop_if.$1 ]; then
1251                 . /etc/stop_if.$1
1252                 return 0
1253         else
1254                 return 1
1255         fi
1256 }
1257
1258 # clone_up
1259 #       Create cloneable interfaces.
1260 #
1261 clone_up()
1262 {
1263         local _list ifn ifopt _iflist _n tmpargs
1264         _list=
1265         _iflist=$*
1266
1267         # create_args_IF
1268         for ifn in ${cloned_interfaces}; do
1269                 # Parse ifn:ifopt.
1270                 OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1271                 case $_iflist in
1272                 ""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)     ;;
1273                 *)      continue ;;
1274                 esac
1275                 case $ifn in
1276                 epair[0-9]*)
1277                         # epair(4) uses epair[0-9] for creation and
1278                         # epair[0-9][ab] for configuration.
1279                         #
1280                         # Skip if ${ifn}a or ${ifn}b already exist.
1281                         if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1282                                 continue
1283                         elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1284                                 continue
1285                         fi
1286                         ${IFCONFIG_CMD} ${ifn} create \
1287                             `get_if_var ${ifn} create_args_IF`
1288                         if [ $? -eq 0 ]; then
1289                                 _list="$_list ${ifn}a ${ifn}b"
1290                         fi
1291                 ;;
1292                 *)
1293                         # Skip if ${ifn} already exists.
1294                         if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1295                                 continue
1296                         fi
1297                         ${IFCONFIG_CMD} ${ifn} create \
1298                             `get_if_var ${ifn} create_args_IF`
1299                         if [ $? -eq 0 ]; then
1300                                 _list="$_list $ifn"
1301                         fi
1302                 esac
1303         done
1304         if [ -n "$gif_interfaces" ]; then
1305                 warn "\$gif_interfaces is obsolete.  Use \$cloned_interfaces instead."
1306         fi
1307         for ifn in ${gif_interfaces}; do
1308                 # Parse ifn:ifopt.
1309                 OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1310                 case $_iflist in
1311                 ""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)     ;;
1312                 *)      continue ;;
1313                 esac
1314                 # Skip if ifn already exists.
1315                 if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1316                         continue
1317                 fi
1318                 case $ifn in
1319                 gif[0-9]*)
1320                         ${IFCONFIG_CMD} $ifn create
1321                 ;;
1322                 *)
1323                         _n=$(${IFCONFIG_CMD} gif create)
1324                         ${IFCONFIG_CMD} $_n name $ifn
1325                 ;;
1326                 esac
1327                 if [ $? -eq 0 ]; then
1328                         _list="$_list $ifn"
1329                 fi
1330                 tmpargs=$(get_if_var $ifn gifconfig_IF)
1331                 eval ifconfig_${ifn}=\"tunnel \$tmpargs\"
1332         done
1333         if [ -n "${_list# }" ]; then
1334                 echo "Created clone interfaces: ${_list# }."
1335         fi
1336         debug "Cloned: ${_list# }"
1337 }
1338
1339 # clone_down
1340 #       Destroy cloned interfaces. Destroyed interfaces are echoed to
1341 #       standard output.
1342 #
1343 clone_down()
1344 {
1345         local _list ifn _difn ifopt _iflist _sticky
1346         _list=
1347         _iflist=$*
1348
1349         : ${cloned_interfaces_sticky:=NO}
1350         if checkyesno cloned_interfaces_sticky; then
1351                 _sticky=1
1352         else
1353                 _sticky=0
1354         fi
1355         for ifn in ${cloned_interfaces} ${gif_interfaces}; do
1356                 # Parse ifn:ifopt.
1357                 OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1358                 case $ifopt:$_sticky in
1359                 sticky:*)       continue ;;     # :sticky => not destroy
1360                 nosticky:*)     ;;              # :nosticky => destroy
1361                 *:1)            continue ;;     # global sticky knob == 1
1362                 esac
1363                 case $_iflist in
1364                 ""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)     ;;
1365                 *)      continue ;;
1366                 esac
1367                 case $ifn in
1368                 epair[0-9]*)
1369                         # Note: epair(4) uses epair[0-9] for removal and
1370                         # epair[0-9][ab] for configuration.
1371                         #
1372                         # Skip if both of ${ifn}a and ${ifn}b do not exist.
1373                         if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1374                                 _difn=${ifn}a
1375                         elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1376                                 _difn=${ifn}b
1377                         else
1378                                 continue
1379                         fi
1380                         ${IFCONFIG_CMD} -n $_difn destroy
1381                         if [ $? -eq 0 ]; then
1382                                 _list="$_list ${ifn}a ${ifn}b"
1383                         fi
1384                 ;;
1385                 *)
1386                         # Skip if ifn does not exist.
1387                         if ! ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1388                                 continue
1389                         fi
1390                         ${IFCONFIG_CMD} -n ${ifn} destroy
1391                         if [ $? -eq 0 ]; then
1392                                 _list="$_list $ifn"
1393                         fi
1394                 ;;
1395                 esac
1396         done
1397         if [ -n "${_list# }" ]; then
1398                 echo "Destroyed clone interfaces: ${_list# }."
1399         fi
1400         debug "Destroyed clones: ${_list# }"
1401 }
1402
1403 # childif_create
1404 #       Create and configure child interfaces.  Return 0 if child
1405 #       interfaces are created.
1406 #
1407 childif_create()
1408 {
1409         local cfg child child_vlans child_wlans create_args debug_flags ifn i
1410         cfg=1
1411         ifn=$1
1412
1413         # Create wireless interfaces
1414         child_wlans=`get_if_var $ifn wlans_IF`
1415
1416         for child in ${child_wlans}; do
1417                 create_args="wlandev $ifn `get_if_var $child create_args_IF`"
1418                 debug_flags="`get_if_var $child wlandebug_IF`"
1419
1420                 if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
1421                         ${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1422                         if [ -n "${debug_flags}" ]; then
1423                                 wlandebug -i $child ${debug_flags}
1424                         fi
1425                 else
1426                         i=`${IFCONFIG_CMD} wlan create ${create_args}`
1427                         if [ -n "${debug_flags}" ]; then
1428                                 wlandebug -i $i ${debug_flags}
1429                         fi
1430                         ${IFCONFIG_CMD} $i name $child && cfg=0
1431                 fi
1432                 if autoif $child; then
1433                         ifn_start $child
1434                 fi
1435         done
1436
1437         # Create vlan interfaces
1438         child_vlans=`get_if_var $ifn vlans_IF`
1439
1440         if [ -n "${child_vlans}" ]; then
1441                 load_kld if_vlan
1442         fi
1443
1444         for child in ${child_vlans}; do
1445                 if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1446                         child="${ifn}.${child}"
1447                         create_args=`get_if_var $child create_args_IF`
1448                         ${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1449                 else
1450                         create_args="vlandev $ifn `get_if_var $child create_args_IF`"
1451                         if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
1452                                 ${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1453                         else
1454                                 i=`${IFCONFIG_CMD} vlan create ${create_args}`
1455                                 ${IFCONFIG_CMD} $i name $child && cfg=0
1456                         fi
1457                 fi
1458                 if autoif $child; then
1459                         ifn_start $child
1460                 fi
1461         done
1462
1463         return ${cfg}
1464 }
1465
1466 # childif_destroy
1467 #       Destroy child interfaces.
1468 #
1469 childif_destroy()
1470 {
1471         local cfg child child_vlans child_wlans ifn
1472         cfg=1
1473
1474         child_wlans=`get_if_var $ifn wlans_IF`
1475         for child in ${child_wlans}; do
1476                 if ! ifexists $child; then
1477                         continue
1478                 fi
1479                 ${IFCONFIG_CMD} -n $child destroy && cfg=0
1480         done
1481
1482         child_vlans=`get_if_var $ifn vlans_IF`
1483         for child in ${child_vlans}; do
1484                 if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1485                         child="${ifn}.${child}"
1486                 fi
1487                 if ! ifexists $child; then
1488                         continue
1489                 fi
1490                 ${IFCONFIG_CMD} -n $child destroy && cfg=0
1491         done
1492
1493         return ${cfg}
1494 }
1495
1496 # ng_mkpeer
1497 #       Create netgraph nodes.
1498 #
1499 ng_mkpeer()
1500 {
1501         ngctl -f - 2> /dev/null <<EOF
1502 mkpeer $*
1503 msg dummy nodeinfo
1504 EOF
1505 }
1506
1507 # ng_create_one
1508 #       Create netgraph nodes.
1509 #
1510 ng_create_one()
1511 {
1512         local t
1513
1514         ng_mkpeer $* | while read line; do
1515                 t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
1516                 if [ -n "${t}" ]; then
1517                         echo ${t}
1518                         return
1519                 fi
1520         done
1521 }
1522
1523 # ng_fec_create ifn
1524 #       Configure Fast EtherChannel for interface $ifn. Returns 0 if
1525 #       FEC arguments were found and configured; returns !0 otherwise.
1526 ng_fec_create()
1527 {
1528          local req_iface iface bogus
1529          req_iface="$1"
1530
1531          ngctl shutdown ${req_iface}: > /dev/null 2>&1
1532
1533          bogus=""
1534          while true; do
1535                  iface=`ng_create_one fec dummy fec`
1536                  if [ -z "${iface}" ]; then
1537                          exit 2
1538                  fi
1539                  if [ "${iface}" = "${req_iface}" ]; then
1540                          break
1541                  fi
1542                  bogus="${bogus} ${iface}"
1543          done
1544
1545          for iface in ${bogus}; do
1546                  ngctl shutdown ${iface}:
1547          done
1548 }
1549
1550 # fec_up
1551 #       Create Fast EtherChannel interfaces.
1552 fec_up()
1553 {
1554         local i j
1555
1556         for i in ${fec_interfaces}; do
1557                 ng_fec_create $i
1558                 for j in `get_if_var $i fecconfig_IF`; do
1559                         case ${j} in
1560                         '')
1561                                 continue
1562                                 ;;
1563                         *)
1564                                 ngctl msg ${i}: add_iface "\"${j}\""
1565                                 ;;
1566                         esac
1567                 done
1568         done
1569 }
1570
1571 # ipx_up ifn
1572 #       Configure any IPX addresses for interface $ifn. Returns 0 if
1573 #       IPX arguments were found and configured; returns 1 otherwise.
1574 #
1575 ipx_up()
1576 {
1577         local ifn
1578         ifn="$1"
1579
1580         # ifconfig_IF_ipx
1581         ifconfig_args=`_ifconfig_getargs $ifn ipx`
1582         if [ -n "${ifconfig_args}" ]; then
1583                 ${IFCONFIG_CMD} ${ifn} ${ifconfig_args}
1584                 return 0
1585         fi
1586
1587         return 1
1588 }
1589
1590 # ipx_down ifn
1591 #       Remove IPX addresses for interface $ifn. Returns 0 if IPX
1592 #       addresses were found and unconfigured. It returns 1, otherwise.
1593 #
1594 ipx_down()
1595 {
1596         local _if _ifs _ret ipxList oldifs _ipx
1597         _if=$1
1598         _ifs="^"
1599         _ret=1
1600         ipxList="`${IFCONFIG_CMD} ${_if} | grep 'ipx ' | tr "\n" "$_ifs"`"
1601         oldifs="$IFS"
1602
1603         IFS="$_ifs"
1604         for _ipx in $ipxList ; do
1605                 # get rid of extraneous line
1606                 [ -z "$_ipx" ] && break
1607
1608                 _ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
1609
1610                 IFS="$oldifs"
1611                 ${IFCONFIG_CMD} ${_if} ${_ipx} delete
1612                 IFS="$_ifs"
1613                 _ret=0
1614         done
1615         IFS="$oldifs"
1616
1617         return $_ret
1618 }
1619
1620 # ifnet_rename [ifname]
1621 #       Rename interfaces if ifconfig_IF_name is defined.
1622 #
1623 ifnet_rename()
1624 {
1625         local _if _ifname
1626
1627         # ifconfig_IF_name
1628         for _if in ${*:-$(${IFCONFIG_CMD} -l)}; do
1629                 _ifname=`get_if_var $_if ifconfig_IF_name`
1630                 if [ ! -z "$_ifname" ]; then
1631                         ${IFCONFIG_CMD} $_if name $_ifname
1632                 fi
1633         done
1634
1635         return 0
1636 }
1637
1638 # list_net_interfaces type
1639 #       List all network interfaces. The type of interface returned
1640 #       can be controlled by the type argument. The type
1641 #       argument can be any of the following:
1642 #               nodhcp  - all interfaces, excluding DHCP configured interfaces
1643 #               dhcp    - list only DHCP configured interfaces
1644 #               noautoconf      - all interfaces, excluding IPv6 Stateless
1645 #                                 Address Autoconf configured interfaces
1646 #               autoconf        - list only IPv6 Stateless Address Autoconf
1647 #                                 configured interfaces
1648 #       If no argument is specified all network interfaces are output.
1649 #       Note that the list will include cloned interfaces if applicable.
1650 #       Cloned interfaces must already exist to have a chance to appear
1651 #       in the list if ${network_interfaces} is set to `auto'.
1652 #
1653 list_net_interfaces()
1654 {
1655         local type _tmplist _list _autolist _lo _if
1656         type=$1
1657
1658         # Get a list of ALL the interfaces and make lo0 first if it's there.
1659         #
1660         _tmplist=
1661         case ${network_interfaces} in
1662         [Aa][Uu][Tt][Oo])
1663                 _autolist="`${IFCONFIG_CMD} -l`"
1664                 _lo=
1665                 for _if in ${_autolist} ; do
1666                         if autoif $_if; then
1667                                 if [ "$_if" = "lo0" ]; then
1668                                         _lo="lo0 "
1669                                 else
1670                                         _tmplist="${_tmplist} ${_if}"
1671                                 fi
1672                         fi
1673                 done
1674                 _tmplist="${_lo}${_tmplist# }"
1675         ;;
1676         *)
1677                 for _if in ${network_interfaces} ${cloned_interfaces}; do
1678                         # epair(4) uses epair[0-9] for creation and
1679                         # epair[0-9][ab] for configuration.
1680                         case $_if in
1681                         epair[0-9]*)
1682                                 _tmplist="$_tmplist ${_if}a ${_if}b"
1683                         ;;
1684                         *)
1685                                 _tmplist="$_tmplist $_if"
1686                         ;;
1687                         esac
1688                 done
1689                 #
1690                 # lo0 is effectively mandatory, so help prevent foot-shooting
1691                 #
1692                 case "$_tmplist" in
1693                 lo0|'lo0 '*|*' lo0'|*' lo0 '*)
1694                         # This is fine, do nothing
1695                         _tmplist="${_tmplist# }"
1696                 ;;
1697                 *)
1698                         _tmplist="lo0 ${_tmplist# }"
1699                 ;;
1700                 esac
1701         ;;
1702         esac
1703
1704         _list=
1705         case "$type" in
1706         nodhcp)
1707                 for _if in ${_tmplist} ; do
1708                         if ! dhcpif $_if && \
1709                            [ -n "`_ifconfig_getargs $_if`" ]; then
1710                                 _list="${_list# } ${_if}"
1711                         fi
1712                 done
1713         ;;
1714         dhcp)
1715                 for _if in ${_tmplist} ; do
1716                         if dhcpif $_if; then
1717                                 _list="${_list# } ${_if}"
1718                         fi
1719                 done
1720         ;;
1721         noautoconf)
1722                 for _if in ${_tmplist} ; do
1723                         if ! ipv6_autoconfif $_if && \
1724                            [ -n "`_ifconfig_getargs $_if ipv6`" ]; then
1725                                 _list="${_list# } ${_if}"
1726                         fi
1727                 done
1728         ;;
1729         autoconf)
1730                 for _if in ${_tmplist} ; do
1731                         if ipv6_autoconfif $_if; then
1732                                 _list="${_list# } ${_if}"
1733                         fi
1734                 done
1735         ;;
1736         *)
1737                 _list=${_tmplist}
1738         ;;
1739         esac
1740
1741         echo $_list
1742
1743         return 0
1744 }
1745
1746 # get_default_if -address_family
1747 #       Get the interface of the default route for the given address family.
1748 #       The -address_family argument must be suitable passing to route(8).
1749 #
1750 get_default_if()
1751 {
1752         local routeget oldifs defif line
1753         defif=
1754         oldifs="$IFS"
1755         IFS="
1756 "
1757         for line in `route -n get $1 default 2>/dev/null`; do
1758                 case $line in
1759                 *interface:*)
1760                         defif=${line##*: }
1761                         ;;
1762                 esac
1763         done
1764         IFS=${oldifs}
1765
1766         echo $defif
1767 }
1768
1769 # hexdigit arg
1770 #       Echo decimal number $arg (single digit) in hexadecimal format.
1771 hexdigit()
1772 {
1773         printf '%x\n' "$1"
1774 }
1775
1776 # hexprint arg
1777 #       Echo decimal number $arg (multiple digits) in hexadecimal format.
1778 hexprint()
1779 {
1780         printf '%x\n' "$1"
1781 }
1782
1783 is_wired_interface()
1784 {
1785         local media
1786
1787         case `${IFCONFIG_CMD} $1 2>/dev/null` in
1788         *media:?Ethernet*) media=Ethernet ;;
1789         esac
1790
1791         test "$media" = "Ethernet"
1792 }
1793
1794 # network6_getladdr if [flag]
1795 #       Echo link-local address from $if if any.
1796 #       If flag is defined, tentative ones will be excluded.
1797 network6_getladdr()
1798 {
1799         local _if _flag proto addr rest
1800         _if=$1
1801         _flag=$2
1802
1803         ${IFCONFIG_CMD} $_if 2>/dev/null | while read proto addr rest; do
1804                 case "${proto}/${addr}/${_flag}/${rest}" in
1805                 inet6/fe80::*//*)
1806                         echo ${addr}
1807                 ;;
1808                 inet6/fe80:://*tentative*)      # w/o flag
1809                         sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
1810                         network6_getladdr $_if $_flags
1811                 ;;
1812                 inet6/fe80::/*/*tentative*)     # w/ flag
1813                         echo ${addr}
1814                 ;;
1815                 *)
1816                         continue
1817                 ;;
1818                 esac
1819
1820                 return
1821         done
1822 }