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