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