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