]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - etc/network.subr
MFC r325559: ifconfig_<interface>_descr
[FreeBSD/stable/10.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 : ${netif_ipexpand_max:=2048}
29
30 #
31 # Subroutines commonly used from network startup scripts.
32 # Requires that rc.conf be loaded first.
33 #
34
35 # ifn_start ifn
36 #       Bring up and configure an interface.  If some configuration is
37 #       applied, print the interface configuration.
38 #
39 ifn_start()
40 {
41         local ifn cfg
42         ifn="$1"
43         cfg=1
44
45         [ -z "$ifn" ] && err 1 "ifn_start called without an interface"
46
47         ifscript_up ${ifn} && cfg=0
48         ifconfig_up ${ifn} && cfg=0
49         if ! noafif $ifn; then
50                 afexists inet && ipv4_up ${ifn} && cfg=0
51                 afexists inet6 && ipv6_up ${ifn} && cfg=0
52                 afexists ipx && ipx_up ${ifn} && cfg=0
53         fi
54         childif_create ${ifn} && cfg=0
55
56         return $cfg
57 }
58
59 # ifn_stop ifn
60 #       Shutdown and de-configure an interface.  If action is taken,
61 #       print the interface name.
62 #
63 ifn_stop()
64 {
65         local ifn cfg
66         ifn="$1"
67         cfg=1
68
69         [ -z "$ifn" ] && err 1 "ifn_stop called without an interface"
70
71         if ! noafif $ifn; then
72                 afexists ipx && ipx_down ${ifn} && cfg=0
73                 afexists inet6 && ipv6_down ${ifn} && cfg=0
74                 afexists inet && ipv4_down ${ifn} && cfg=0
75         fi
76         ifconfig_down ${ifn} && cfg=0
77         ifscript_down ${ifn} && cfg=0
78         childif_destroy ${ifn} && cfg=0
79
80         return $cfg
81 }
82
83 # ifn_vnetup ifn
84 #       Move ifn to the specified vnet jail.
85 #
86 ifn_vnetup()
87 {
88
89         ifn_vnet0 $1 vnet
90 }
91
92 # ifn_vnetdown ifn
93 #       Reclaim ifn from the specified vnet jail.
94 #
95 ifn_vnetdown()
96 {
97
98         ifn_vnet0 $1 -vnet
99 }
100
101 # ifn_vnet0 ifn action
102 #       Helper function for ifn_vnetup and ifn_vnetdown.
103 #
104 ifn_vnet0()
105 {
106         local _ifn _cfg _action _vnet
107         _ifn="$1"
108         _action="$2"
109         _cfg=1
110
111         if _vnet=$(vnetif $_ifn); then
112                 ${IFCONFIG_CMD} $_ifn $_action $_vnet && _cfg=0
113         fi
114
115         return $_cfg
116 }
117
118 # ifconfig_up if
119 #       Evaluate ifconfig(8) arguments for interface $if and
120 #       run ifconfig(8) with those arguments. It returns 0 if
121 #       arguments were found and executed or 1 if the interface
122 #       had no arguments.  Pseudo arguments DHCP and WPA are handled
123 #       here.
124 #
125 ifconfig_up()
126 {
127         local _cfg _ifconfig_descr _ipv6_opts ifconfig_args 
128         _cfg=1
129
130         # Make sure lo0 always comes up.
131         if [ "$1" = "lo0" ]; then
132                 _cfg=0
133         fi
134
135         # inet6 specific
136         if ! noafif $1 && afexists inet6; then
137                 if checkyesno ipv6_activate_all_interfaces; then
138                         _ipv6_opts="-ifdisabled"
139                 elif [ "$1" != "lo0" ]; then
140                         _ipv6_opts="ifdisabled"
141                 fi
142
143                 # backward compatibility: $ipv6_enable
144                 case $ipv6_enable in
145                 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
146                         case $1 in
147                         bridge[0-9]*)
148                                 # No accept_rtadv by default on if_bridge(4)
149                                 # to avoid a conflict with the member
150                                 # interfaces.
151                         ;;
152                         *)
153                                 if ! checkyesno ipv6_gateway_enable; then
154                                         _ipv6_opts="${_ipv6_opts} accept_rtadv"
155                                 fi
156                         ;;
157                         esac
158                 ;;
159                 esac
160
161                 case $ipv6_cpe_wanif in
162                 $1)
163                         _ipv6_opts="${_ipv6_opts} -no_radr accept_rtadv"
164                 ;;
165                 esac
166
167                 if [ -n "${_ipv6_opts}" ]; then
168                         ${IFCONFIG_CMD} $1 inet6 ${_ipv6_opts}
169                 fi
170         fi
171
172         # ifconfig_IF
173         ifconfig_args=`ifconfig_getargs $1`
174         if [ -n "${ifconfig_args}" ]; then
175                 eval ${IFCONFIG_CMD} $1 ${ifconfig_args}
176                 _cfg=0
177         fi
178
179         # inet6 specific
180         if ! noafif $1 && afexists inet6; then
181                 # ifconfig_IF_ipv6
182                 ifconfig_args=`ifconfig_getargs $1 ipv6`
183                 if [ -n "${ifconfig_args}" ]; then
184                         # backward compatibility: inet6 keyword
185                         case "${ifconfig_args}" in
186                         :*|[0-9a-fA-F]*:*)
187                                 warn "\$ifconfig_$1_ipv6 needs leading" \
188                                     "\"inet6\" keyword for an IPv6 address."
189                                 ifconfig_args="inet6 ${ifconfig_args}"
190                         ;;
191                         esac
192                         ${IFCONFIG_CMD} $1 inet6 -ifdisabled
193                         eval ${IFCONFIG_CMD} $1 ${ifconfig_args}
194                         _cfg=0
195                 fi
196
197                 # $ipv6_prefix_IF will be handled in
198                 # ipv6_prefix_hostid_addr_common().
199                 ifconfig_args=`get_if_var $1 ipv6_prefix_IF`
200                 if [ -n "${ifconfig_args}" ]; then
201                         ${IFCONFIG_CMD} $1 inet6 -ifdisabled
202                         _cfg=0
203                 fi
204
205                 # backward compatibility: $ipv6_ifconfig_IF
206                 ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF`
207                 if [ -n "${ifconfig_args}" ]; then
208                         warn "\$ipv6_ifconfig_$1 is obsolete." \
209                             "  Use ifconfig_$1_ipv6 instead."
210                         ${IFCONFIG_CMD} $1 inet6 -ifdisabled
211                         eval ${IFCONFIG_CMD} $1 inet6 ${ifconfig_args}
212                         _cfg=0
213                 fi
214         fi
215
216         ifalias $1 link alias
217         ifalias $1 ether alias
218
219         _ifconfig_descr=`get_if_var $1 ifconfig_IF_descr`
220         if [ -n "${_ifconfig_descr}" ]; then
221                 ${IFCONFIG_CMD} $1 description "${_ifconfig_descr}"
222         fi
223
224         if wpaif $1; then
225                 /etc/rc.d/wpa_supplicant start $1
226                 _cfg=0          # XXX: not sure this should count
227         elif hostapif $1; then
228                 /etc/rc.d/hostapd start $1
229                 _cfg=0
230         fi
231
232         if dhcpif $1; then
233                 if [ $_cfg -ne 0 ] ; then
234                         ${IFCONFIG_CMD} $1 up
235                 fi
236                 if syncdhcpif $1; then
237                         /etc/rc.d/dhclient start $1
238                 fi
239                 _cfg=0
240         fi
241
242         return $_cfg
243 }
244
245 # ifconfig_down if
246 #       returns 1 if wpa_supplicant or dhclient was stopped or
247 #       the interface exists.
248 #
249 ifconfig_down()
250 {
251         local _cfg
252         _cfg=1
253
254         if wpaif $1; then
255                 /etc/rc.d/wpa_supplicant stop $1
256                 _cfg=0
257         elif hostapif $1; then
258                 /etc/rc.d/hostapd stop $1
259                 _cfg=0
260         fi
261
262         if dhcpif $1; then
263                 /etc/rc.d/dhclient stop $1
264                 _cfg=0
265         fi
266
267         if ifexists $1; then
268                 ${IFCONFIG_CMD} $1 down
269                 _cfg=0
270         fi
271
272         return $_cfg
273 }
274
275 # get_if_var if var [default]
276 #       Return the value of the pseudo-hash corresponding to $if where
277 #       $var is a string containg the sub-string "IF" which will be
278 #       replaced with $if after the characters defined in _punct are
279 #       replaced with '_'. If the variable is unset, replace it with
280 #       $default if given.
281 get_if_var()
282 {
283         local _if _punct _punct_c _var _default prefix suffix
284
285         if [ $# -ne 2 -a $# -ne 3 ]; then
286                 err 3 'USAGE: get_if_var name var [default]'
287         fi
288
289         _if=$1
290         _punct=".-/+"
291         ltr ${_if} "${_punct}" '_' _if
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 $_inet6 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 + $netif_ipexpand_max)) ]; 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.  Increase \$netif_ipexpand_max in rc.conf."
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 + $netif_ipexpand_max)) ]
984                                         then
985                                                 warn "Range specification is too large $(printf '(%s:%x%s-%s:%x%s)' "$_ipleft" "$_iplow" "$_ipright" "$_ipleft" "$_iphigh" "$_ipright"). $(printf '%s:%x%s-%s:%x%s' "$_ipleft" "$_iplow" "$_ipright" "$_ipleft" "$_ipcount" "$_ipright") was processed.  Increase \$netif_ipexpand_max in rc.conf."
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}\ *[0-9a-fA-F]-*)
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}\ *[0-9a-fA-F]-*)
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         local _vif _punct=".-/+"
1085
1086         _ret=1
1087         _aliasn=
1088         _if=$1
1089         _af=$2
1090         _action=$3
1091
1092         # Normalize $_if before using it in a pattern to list_vars()
1093         ltr "$_if" "$_punct" "_" _vif
1094
1095         # ifconfig_IF_aliasN which starts with $_af
1096         for alias in `list_vars ifconfig_${_vif}_alias[0-9]\* |
1097                 sort_lite -nk1.$((9+${#_vif}+7))`
1098         do
1099                 eval ifconfig_args=\"\$$alias\"
1100                 _iaf=
1101                 case $ifconfig_args in
1102                 inet\ *)        _iaf=inet ;;
1103                 inet6\ *)       _iaf=inet6 ;;
1104                 ipx\ *)         _iaf=ipx ;;
1105                 link\ *)        _iaf=link ;;
1106                 ether\ *)       _iaf=ether ;;
1107                 esac
1108
1109                 case ${_af}:${_action}:${_iaf}:"${ifconfig_args}" in
1110                 ${_af}:*:${_af}:*)
1111                         _aliasn="$_aliasn $ifconfig_args"
1112                         ;;
1113                 ${_af}:*:"":"")
1114                         break
1115                         ;;
1116                 inet:alias:"":*)
1117                         _aliasn="$_aliasn inet $ifconfig_args"
1118                         warn "\$${alias} needs leading" \
1119                             "\"inet\" keyword for an IPv4 address."
1120                 esac
1121         done
1122
1123         # backward compatibility: ipv6_ifconfig_IF_aliasN.
1124         case $_af in
1125         inet6)
1126                 for alias in `list_vars ipv6_ifconfig_${_vif}_alias[0-9]\* |
1127                         sort_lite -nk1.$((14+${#_vif}+7))`
1128                 do
1129                         eval ifconfig_args=\"\$$alias\"
1130                         case ${_action}:"${ifconfig_args}" in
1131                         *:"")
1132                                 break
1133                         ;;
1134                         alias:*)
1135                                 _aliasn="${_aliasn} inet6 ${ifconfig_args}"
1136                                 warn "\$${alias} is obsolete. " \
1137                                     "Use ifconfig_${_vif}_aliasN instead."
1138                         ;;
1139                         esac
1140                 done
1141         esac
1142
1143         # backward compatibility: ipv4_addrs_IF.
1144         for _tmpargs in `get_if_var $_if ipv4_addrs_IF`; do
1145                 _aliasn="$_aliasn inet $_tmpargs"
1146         done
1147
1148         # Handle ifconfig_IF_aliases, ifconfig_IF_aliasN, and the others.
1149         _tmpargs=
1150         for _c in `get_if_var $_if ifconfig_IF_aliases` $_aliasn; do
1151                 case $_c in
1152                 inet|inet6|ipx|link|ether)
1153                         case $_tmpargs in
1154                         ${_af}\ *)
1155                                 eval ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1156                         ;;
1157                         esac
1158                         _tmpargs=$_c
1159                 ;;
1160                 *)
1161                         _tmpargs="$_tmpargs $_c"
1162                 esac
1163         done
1164         # Process the last component
1165         case $_tmpargs in
1166         ${_af}\ *)
1167                 ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1168         ;;
1169         esac
1170
1171         return $_ret
1172 }
1173
1174 # ipv6_prefix_hostid_addr_common if action
1175 #       Add or remove IPv6 prefix + hostid addr on the interface $if
1176 #
1177 ipv6_prefix_hostid_addr_common()
1178 {
1179         local _if _action prefix j
1180         _if=$1
1181         _action=$2
1182         prefix=`get_if_var ${_if} ipv6_prefix_IF`
1183
1184         if [ -n "${prefix}" ]; then
1185                 for j in ${prefix}; do
1186                         # The default prefixlen is 64.
1187                         plen=${j#*/}
1188                         case $j:$plen in
1189                         $plen:$j)       plen=64 ;;
1190                         *)              j=${j%/*} ;;
1191                         esac
1192
1193                         # Normalize the last part by removing ":"
1194                         j=${j%::*}
1195                         j=${j%:}
1196                         ${IFCONFIG_CMD} ${_if} inet6 $j:: \
1197                                 prefixlen $plen eui64 ${_action}
1198
1199                         # if I am a router, add subnet router
1200                         # anycast address (RFC 2373).
1201                         if checkyesno ipv6_gateway_enable; then
1202                                 ${IFCONFIG_CMD} ${_if} inet6 $j:: \
1203                                         prefixlen $plen ${_action} anycast
1204                         fi
1205                 done
1206         fi
1207 }
1208
1209 # ipv6_accept_rtadv_up if
1210 #       Enable accepting Router Advertisement and send Router
1211 #       Solicitation message
1212 ipv6_accept_rtadv_up()
1213 {
1214         if ipv6_autoconfif $1; then
1215                 ${IFCONFIG_CMD} $1 inet6 accept_rtadv up
1216                 if ! checkyesno rtsold_enable; then
1217                         rtsol ${rtsol_flags} $1
1218                 fi
1219         fi
1220 }
1221
1222 # ipv6_accept_rtadv_down if
1223 #       Disable accepting Router Advertisement
1224 ipv6_accept_rtadv_down()
1225 {
1226         if ipv6_autoconfif $1; then
1227                 ${IFCONFIG_CMD} $1 inet6 -accept_rtadv
1228         fi
1229 }
1230
1231 # ifscript_up if
1232 #       Evaluate a startup script for the $if interface.
1233 #       It returns 0 if a script was found and processed or
1234 #       1 if no script was found.
1235 #
1236 ifscript_up()
1237 {
1238         if [ -r /etc/start_if.$1 ]; then
1239                 . /etc/start_if.$1
1240                 return 0
1241         else
1242                 return 1
1243         fi
1244 }
1245
1246 # ifscript_down if
1247 #       Evaluate a shutdown script for the $if interface.
1248 #       It returns 0 if a script was found and processed or
1249 #       1 if no script was found.
1250 #
1251 ifscript_down()
1252 {
1253         if [ -r /etc/stop_if.$1 ]; then
1254                 . /etc/stop_if.$1
1255                 return 0
1256         else
1257                 return 1
1258         fi
1259 }
1260
1261 # clone_up
1262 #       Create cloneable interfaces.
1263 #
1264 clone_up()
1265 {
1266         local _list ifn ifopt _iflist _n tmpargs
1267         _list=
1268         _iflist=$*
1269
1270         # create_args_IF
1271         for ifn in ${cloned_interfaces}; do
1272                 # Parse ifn:ifopt.
1273                 OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1274                 case $_iflist in
1275                 ""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)     ;;
1276                 *)      continue ;;
1277                 esac
1278                 case $ifn in
1279                 epair[0-9]*)
1280                         # epair(4) uses epair[0-9] for creation and
1281                         # epair[0-9][ab] for configuration.
1282                         #
1283                         # Skip if ${ifn}a or ${ifn}b already exist.
1284                         if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1285                                 continue
1286                         elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1287                                 continue
1288                         fi
1289                         ${IFCONFIG_CMD} ${ifn} create \
1290                             `get_if_var ${ifn} create_args_IF`
1291                         if [ $? -eq 0 ]; then
1292                                 _list="$_list ${ifn}a ${ifn}b"
1293                         fi
1294                 ;;
1295                 *)
1296                         # Skip if ${ifn} already exists.
1297                         if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1298                                 continue
1299                         fi
1300                         ${IFCONFIG_CMD} ${ifn} create \
1301                             `get_if_var ${ifn} create_args_IF`
1302                         if [ $? -eq 0 ]; then
1303                                 _list="$_list $ifn"
1304                         fi
1305                 esac
1306         done
1307         if [ -n "$gif_interfaces" ]; then
1308                 warn "\$gif_interfaces is obsolete.  Use \$cloned_interfaces instead."
1309         fi
1310         for ifn in ${gif_interfaces}; do
1311                 # Parse ifn:ifopt.
1312                 OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1313                 case $_iflist in
1314                 ""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)     ;;
1315                 *)      continue ;;
1316                 esac
1317                 # Skip if ifn already exists.
1318                 if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1319                         continue
1320                 fi
1321                 case $ifn in
1322                 gif[0-9]*)
1323                         ${IFCONFIG_CMD} $ifn create
1324                 ;;
1325                 *)
1326                         _n=$(${IFCONFIG_CMD} gif create)
1327                         ${IFCONFIG_CMD} $_n name $ifn
1328                 ;;
1329                 esac
1330                 if [ $? -eq 0 ]; then
1331                         _list="$_list $ifn"
1332                 fi
1333                 tmpargs=$(get_if_var $ifn gifconfig_IF)
1334                 eval ifconfig_${ifn}=\"tunnel \$tmpargs\"
1335         done
1336         if [ -n "${_list# }" ]; then
1337                 echo "Created clone interfaces: ${_list# }."
1338         fi
1339         debug "Cloned: ${_list# }"
1340 }
1341
1342 # clone_down
1343 #       Destroy cloned interfaces. Destroyed interfaces are echoed to
1344 #       standard output.
1345 #
1346 clone_down()
1347 {
1348         local _list ifn _difn ifopt _iflist _sticky
1349         _list=
1350         _iflist=$*
1351
1352         : ${cloned_interfaces_sticky:=NO}
1353         if checkyesno cloned_interfaces_sticky; then
1354                 _sticky=1
1355         else
1356                 _sticky=0
1357         fi
1358         for ifn in ${cloned_interfaces} ${gif_interfaces}; do
1359                 # Parse ifn:ifopt.
1360                 OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1361                 case $ifopt:$_sticky in
1362                 sticky:*)       continue ;;     # :sticky => not destroy
1363                 nosticky:*)     ;;              # :nosticky => destroy
1364                 *:1)            continue ;;     # global sticky knob == 1
1365                 esac
1366                 case $_iflist in
1367                 ""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)     ;;
1368                 *)      continue ;;
1369                 esac
1370                 case $ifn in
1371                 epair[0-9]*)
1372                         # Note: epair(4) uses epair[0-9] for removal and
1373                         # epair[0-9][ab] for configuration.
1374                         #
1375                         # Skip if both of ${ifn}a and ${ifn}b do not exist.
1376                         if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1377                                 _difn=${ifn}a
1378                         elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1379                                 _difn=${ifn}b
1380                         else
1381                                 continue
1382                         fi
1383                         ${IFCONFIG_CMD} -n $_difn destroy
1384                         if [ $? -eq 0 ]; then
1385                                 _list="$_list ${ifn}a ${ifn}b"
1386                         fi
1387                 ;;
1388                 *)
1389                         # Skip if ifn does not exist.
1390                         if ! ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1391                                 continue
1392                         fi
1393                         ${IFCONFIG_CMD} -n ${ifn} destroy
1394                         if [ $? -eq 0 ]; then
1395                                 _list="$_list $ifn"
1396                         fi
1397                 ;;
1398                 esac
1399         done
1400         if [ -n "${_list# }" ]; then
1401                 echo "Destroyed clone interfaces: ${_list# }."
1402         fi
1403         debug "Destroyed clones: ${_list# }"
1404 }
1405
1406 # childif_create
1407 #       Create and configure child interfaces.  Return 0 if child
1408 #       interfaces are created.
1409 #
1410 childif_create()
1411 {
1412         local cfg child child_vlans child_wlans create_args debug_flags ifn i
1413         cfg=1
1414         ifn=$1
1415
1416         # Create wireless interfaces
1417         child_wlans=`get_if_var $ifn wlans_IF`
1418
1419         for child in ${child_wlans}; do
1420                 create_args="wlandev $ifn `get_if_var $child create_args_IF`"
1421                 debug_flags="`get_if_var $child wlandebug_IF`"
1422
1423                 if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
1424                         ${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1425                         if [ -n "${debug_flags}" ]; then
1426                                 wlandebug -i $child ${debug_flags}
1427                         fi
1428                 else
1429                         i=`${IFCONFIG_CMD} wlan create ${create_args}`
1430                         if [ -n "${debug_flags}" ]; then
1431                                 wlandebug -i $i ${debug_flags}
1432                         fi
1433                         ${IFCONFIG_CMD} $i name $child && cfg=0
1434                 fi
1435                 if autoif $child; then
1436                         ifn_start $child
1437                 fi
1438         done
1439
1440         # Create vlan interfaces
1441         child_vlans=`get_if_var $ifn vlans_IF`
1442
1443         if [ -n "${child_vlans}" ]; then
1444                 load_kld if_vlan
1445         fi
1446
1447         for child in ${child_vlans}; do
1448                 if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1449                         child="${ifn}.${child}"
1450                         create_args=`get_if_var $child create_args_IF`
1451                         ${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1452                 else
1453                         create_args="vlandev $ifn `get_if_var $child create_args_IF`"
1454                         if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
1455                                 ${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1456                         else
1457                                 i=`${IFCONFIG_CMD} vlan create ${create_args}`
1458                                 ${IFCONFIG_CMD} $i name $child && cfg=0
1459                         fi
1460                 fi
1461                 if autoif $child; then
1462                         ifn_start $child
1463                 fi
1464         done
1465
1466         return ${cfg}
1467 }
1468
1469 # childif_destroy
1470 #       Destroy child interfaces.
1471 #
1472 childif_destroy()
1473 {
1474         local cfg child child_vlans child_wlans ifn
1475         cfg=1
1476
1477         child_wlans=`get_if_var $ifn wlans_IF`
1478         for child in ${child_wlans}; do
1479                 if ! ifexists $child; then
1480                         continue
1481                 fi
1482                 ${IFCONFIG_CMD} -n $child destroy && cfg=0
1483         done
1484
1485         child_vlans=`get_if_var $ifn vlans_IF`
1486         for child in ${child_vlans}; do
1487                 if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1488                         child="${ifn}.${child}"
1489                 fi
1490                 if ! ifexists $child; then
1491                         continue
1492                 fi
1493                 ${IFCONFIG_CMD} -n $child destroy && cfg=0
1494         done
1495
1496         return ${cfg}
1497 }
1498
1499 # ng_mkpeer
1500 #       Create netgraph nodes.
1501 #
1502 ng_mkpeer()
1503 {
1504         ngctl -f - 2> /dev/null <<EOF
1505 mkpeer $*
1506 msg dummy nodeinfo
1507 EOF
1508 }
1509
1510 # ng_create_one
1511 #       Create netgraph nodes.
1512 #
1513 ng_create_one()
1514 {
1515         local t
1516
1517         ng_mkpeer $* | while read line; do
1518                 t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
1519                 if [ -n "${t}" ]; then
1520                         echo ${t}
1521                         return
1522                 fi
1523         done
1524 }
1525
1526 # ng_fec_create ifn
1527 #       Configure Fast EtherChannel for interface $ifn. Returns 0 if
1528 #       FEC arguments were found and configured; returns !0 otherwise.
1529 ng_fec_create()
1530 {
1531          local req_iface iface bogus
1532          req_iface="$1"
1533
1534          ngctl shutdown ${req_iface}: > /dev/null 2>&1
1535
1536          bogus=""
1537          while true; do
1538                  iface=`ng_create_one fec dummy fec`
1539                  if [ -z "${iface}" ]; then
1540                          exit 2
1541                  fi
1542                  if [ "${iface}" = "${req_iface}" ]; then
1543                          break
1544                  fi
1545                  bogus="${bogus} ${iface}"
1546          done
1547
1548          for iface in ${bogus}; do
1549                  ngctl shutdown ${iface}:
1550          done
1551 }
1552
1553 # fec_up
1554 #       Create Fast EtherChannel interfaces.
1555 fec_up()
1556 {
1557         local i j
1558
1559         for i in ${fec_interfaces}; do
1560                 ng_fec_create $i
1561                 for j in `get_if_var $i fecconfig_IF`; do
1562                         case ${j} in
1563                         '')
1564                                 continue
1565                                 ;;
1566                         *)
1567                                 ngctl msg ${i}: add_iface "\"${j}\""
1568                                 ;;
1569                         esac
1570                 done
1571         done
1572 }
1573
1574 # ipx_up ifn
1575 #       Configure any IPX addresses for interface $ifn. Returns 0 if
1576 #       IPX arguments were found and configured; returns 1 otherwise.
1577 #
1578 ipx_up()
1579 {
1580         local ifn
1581         ifn="$1"
1582
1583         # ifconfig_IF_ipx
1584         ifconfig_args=`_ifconfig_getargs $ifn ipx`
1585         if [ -n "${ifconfig_args}" ]; then
1586                 ${IFCONFIG_CMD} ${ifn} ${ifconfig_args}
1587                 return 0
1588         fi
1589
1590         return 1
1591 }
1592
1593 # ipx_down ifn
1594 #       Remove IPX addresses for interface $ifn. Returns 0 if IPX
1595 #       addresses were found and unconfigured. It returns 1, otherwise.
1596 #
1597 ipx_down()
1598 {
1599         local _if _ifs _ret ipxList oldifs _ipx
1600         _if=$1
1601         _ifs="^"
1602         _ret=1
1603         ipxList="`${IFCONFIG_CMD} ${_if} | grep 'ipx ' | tr "\n" "$_ifs"`"
1604         oldifs="$IFS"
1605
1606         IFS="$_ifs"
1607         for _ipx in $ipxList ; do
1608                 # get rid of extraneous line
1609                 [ -z "$_ipx" ] && break
1610
1611                 _ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
1612
1613                 IFS="$oldifs"
1614                 ${IFCONFIG_CMD} ${_if} ${_ipx} delete
1615                 IFS="$_ifs"
1616                 _ret=0
1617         done
1618         IFS="$oldifs"
1619
1620         return $_ret
1621 }
1622
1623 # ifnet_rename [ifname]
1624 #       Rename interfaces if ifconfig_IF_name is defined.
1625 #
1626 ifnet_rename()
1627 {
1628         local _if _ifname
1629
1630         # ifconfig_IF_name
1631         for _if in ${*:-$(${IFCONFIG_CMD} -l)}; do
1632                 _ifname=`get_if_var $_if ifconfig_IF_name`
1633                 if [ ! -z "$_ifname" ]; then
1634                         ${IFCONFIG_CMD} $_if name $_ifname
1635                 fi
1636         done
1637
1638         return 0
1639 }
1640
1641 # list_net_interfaces type
1642 #       List all network interfaces. The type of interface returned
1643 #       can be controlled by the type argument. The type
1644 #       argument can be any of the following:
1645 #               nodhcp  - all interfaces, excluding DHCP configured interfaces
1646 #               dhcp    - list only DHCP configured interfaces
1647 #               noautoconf      - all interfaces, excluding IPv6 Stateless
1648 #                                 Address Autoconf configured interfaces
1649 #               autoconf        - list only IPv6 Stateless Address Autoconf
1650 #                                 configured interfaces
1651 #       If no argument is specified all network interfaces are output.
1652 #       Note that the list will include cloned interfaces if applicable.
1653 #       Cloned interfaces must already exist to have a chance to appear
1654 #       in the list if ${network_interfaces} is set to `auto'.
1655 #
1656 list_net_interfaces()
1657 {
1658         local type _tmplist _list _autolist _lo _if
1659         type=$1
1660
1661         # Get a list of ALL the interfaces and make lo0 first if it's there.
1662         #
1663         _tmplist=
1664         case ${network_interfaces} in
1665         [Aa][Uu][Tt][Oo])
1666                 _autolist="`${IFCONFIG_CMD} -l`"
1667                 _lo=
1668                 for _if in ${_autolist} ; do
1669                         if autoif $_if; then
1670                                 if [ "$_if" = "lo0" ]; then
1671                                         _lo="lo0 "
1672                                 else
1673                                         _tmplist="${_tmplist} ${_if}"
1674                                 fi
1675                         fi
1676                 done
1677                 _tmplist="${_lo}${_tmplist# }"
1678         ;;
1679         *)
1680                 for _if in ${network_interfaces} ${cloned_interfaces}; do
1681                         # epair(4) uses epair[0-9] for creation and
1682                         # epair[0-9][ab] for configuration.
1683                         case $_if in
1684                         epair[0-9]*)
1685                                 _tmplist="$_tmplist ${_if}a ${_if}b"
1686                         ;;
1687                         *)
1688                                 _tmplist="$_tmplist $_if"
1689                         ;;
1690                         esac
1691                 done
1692                 #
1693                 # lo0 is effectively mandatory, so help prevent foot-shooting
1694                 #
1695                 case "$_tmplist" in
1696                 lo0|'lo0 '*|*' lo0'|*' lo0 '*)
1697                         # This is fine, do nothing
1698                         _tmplist="${_tmplist# }"
1699                 ;;
1700                 *)
1701                         _tmplist="lo0 ${_tmplist# }"
1702                 ;;
1703                 esac
1704         ;;
1705         esac
1706
1707         _list=
1708         case "$type" in
1709         nodhcp)
1710                 for _if in ${_tmplist} ; do
1711                         if ! dhcpif $_if && \
1712                            [ -n "`_ifconfig_getargs $_if`" ]; then
1713                                 _list="${_list# } ${_if}"
1714                         fi
1715                 done
1716         ;;
1717         dhcp)
1718                 for _if in ${_tmplist} ; do
1719                         if dhcpif $_if; then
1720                                 _list="${_list# } ${_if}"
1721                         fi
1722                 done
1723         ;;
1724         noautoconf)
1725                 for _if in ${_tmplist} ; do
1726                         if ! ipv6_autoconfif $_if && \
1727                            [ -n "`_ifconfig_getargs $_if ipv6`" ]; then
1728                                 _list="${_list# } ${_if}"
1729                         fi
1730                 done
1731         ;;
1732         autoconf)
1733                 for _if in ${_tmplist} ; do
1734                         if ipv6_autoconfif $_if; then
1735                                 _list="${_list# } ${_if}"
1736                         fi
1737                 done
1738         ;;
1739         *)
1740                 _list=${_tmplist}
1741         ;;
1742         esac
1743
1744         echo $_list
1745
1746         return 0
1747 }
1748
1749 # get_default_if -address_family
1750 #       Get the interface of the default route for the given address family.
1751 #       The -address_family argument must be suitable passing to route(8).
1752 #
1753 get_default_if()
1754 {
1755         local routeget oldifs defif line
1756         defif=
1757         oldifs="$IFS"
1758         IFS="
1759 "
1760         for line in `route -n get $1 default 2>/dev/null`; do
1761                 case $line in
1762                 *interface:*)
1763                         defif=${line##*: }
1764                         ;;
1765                 esac
1766         done
1767         IFS=${oldifs}
1768
1769         echo $defif
1770 }
1771
1772 # hexdigit arg
1773 #       Echo decimal number $arg (single digit) in hexadecimal format.
1774 hexdigit()
1775 {
1776         printf '%x\n' "$1"
1777 }
1778
1779 # hexprint arg
1780 #       Echo decimal number $arg (multiple digits) in hexadecimal format.
1781 hexprint()
1782 {
1783         printf '%x\n' "$1"
1784 }
1785
1786 is_wired_interface()
1787 {
1788         local media
1789
1790         case `${IFCONFIG_CMD} $1 2>/dev/null` in
1791         *media:?Ethernet*) media=Ethernet ;;
1792         esac
1793
1794         test "$media" = "Ethernet"
1795 }
1796
1797 # network6_getladdr if [flag]
1798 #       Echo link-local address from $if if any.
1799 #       If flag is defined, tentative ones will be excluded.
1800 network6_getladdr()
1801 {
1802         local _if _flag proto addr rest
1803         _if=$1
1804         _flag=$2
1805
1806         ${IFCONFIG_CMD} $_if 2>/dev/null | while read proto addr rest; do
1807                 case "${proto}/${addr}/${_flag}/${rest}" in
1808                 inet6/fe80::*//*)
1809                         echo ${addr}
1810                 ;;
1811                 inet6/fe80:://*tentative*)      # w/o flag
1812                         sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
1813                         network6_getladdr $_if $_flags
1814                 ;;
1815                 inet6/fe80::/*/*tentative*)     # w/ flag
1816                         echo ${addr}
1817                 ;;
1818                 *)
1819                         continue
1820                 ;;
1821                 esac
1822
1823                 return
1824         done
1825 }