]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - etc/network.subr
I think 23dBm is the correct value to use here. CRDA uses 20dBm + 3dB max antenna
[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
28 #
29 # Subroutines commonly used from network startup scripts.
30 # Requires that rc.conf be loaded first.
31 #
32
33 # ifn_start ifn
34 #       Bring up and configure an interface.  If some configuration is
35 #       applied print the interface configuration.
36 #
37 ifn_start()
38 {
39         local ifn cfg
40         ifn="$1"
41         cfg=1
42
43         [ -z "$ifn" ] && err 1 "ifn_start called without an interface"
44
45         ifscript_up ${ifn} && cfg=0
46         ifconfig_up ${ifn} && cfg=0
47         afexists inet && ipv4_up ${ifn} && cfg=0
48         afexists inet6 && ipv6_up ${ifn} && cfg=0
49         afexists ipx && ipx_up ${ifn} && cfg=0
50         childif_create ${ifn} && cfg=0
51
52         return $cfg
53 }
54
55 # ifn_stop ifn
56 #       Shutdown and de-configure an interface.  If action is taken
57 #       print the interface name.
58 #
59 ifn_stop()
60 {
61         local ifn cfg
62         ifn="$1"
63         cfg=1
64
65         [ -z "$ifn" ] && err 1 "ifn_stop called without an interface"
66
67         afexists ipx && ipx_down ${ifn} && cfg=0
68         afexists inet6 && ipv6_down ${ifn} && cfg=0
69         afexists inet && ipv4_down ${ifn} && cfg=0
70         ifconfig_down ${ifn} && cfg=0
71         ifscript_down ${ifn} && cfg=0
72         childif_destroy ${ifn} && cfg=0
73
74         return $cfg
75 }
76
77 # ifconfig_up if
78 #       Evaluate ifconfig(8) arguments for interface $if and
79 #       run ifconfig(8) with those arguments. It returns 0 if
80 #       arguments were found and executed or 1 if the interface
81 #       had no arguments.  Pseudo arguments DHCP and WPA are handled
82 #       here.
83 #
84 ifconfig_up()
85 {
86         local _cfg _ipv6_opts ifconfig_args
87         _cfg=1
88
89         # Make sure lo0 always comes up.
90         if [ "$1" = "lo0" ]; then
91                 _cfg=0
92         fi
93
94         # ifconfig_IF
95         ifconfig_args=`ifconfig_getargs $1`
96         if [ -n "${ifconfig_args}" ]; then
97                 eval ifconfig $1 ${ifconfig_args}
98                 _cfg=0
99         fi
100
101         # inet6 specific
102         if afexists inet6; then
103                 if checkyesno ipv6_activate_all_interfaces; then
104                         _ipv6_opts="-ifdisabled"
105                 elif [ "$1" != "lo0" ]; then
106                         _ipv6_opts="ifdisabled"
107                 fi
108
109                 # backward compatibility: $ipv6_enable
110                 case $ipv6_enable in
111                 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
112                         _ipv6_opts="${_ipv6_opts} accept_rtadv"
113                         ;;
114                 esac
115
116                 if [ -n "${_ipv6_opts}" ]; then
117                         ifconfig $1 inet6 ${_ipv6_opts}
118                 fi
119
120                 # ifconfig_IF_ipv6
121                 ifconfig_args=`ifconfig_getargs $1 ipv6`
122                 if [ -n "${ifconfig_args}" ]; then
123                         ifconfig $1 inet6 -ifdisabled
124                         ifconfig $1 ${ifconfig_args}
125                         _cfg=0
126                 fi
127
128                 # backward compatiblity: $ipv6_ifconfig_IF
129                 ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF`
130                 if [ -n "${ifconfig_args}" ]; then
131                         warn "\$ipv6_ifconfig_$1 is obsolete." \
132                             "  Use ifconfig_$1_ipv6 instead."
133                         ifconfig $1 inet6 -ifdisabled
134                         ifconfig $1 inet6 ${ifconfig_args}
135                         _cfg=0
136                 fi
137         fi
138
139         if [ ${_cfg} -eq 0 ]; then
140                 ifconfig $1 up
141         fi
142
143         if wpaif $1; then
144                 /etc/rc.d/wpa_supplicant start $1
145                 _cfg=0          # XXX: not sure this should count
146         fi
147
148         if dhcpif $1; then
149                 if [ $_cfg -ne 0 ] ; then
150                         ifconfig $1 up
151                 fi
152                 if syncdhcpif $1; then
153                         /etc/rc.d/dhclient start $1
154                 fi
155                 _cfg=0
156         fi
157
158         return $_cfg
159 }
160
161 # ifconfig_down if
162 #       returns 1 if wpa_supplicant or dhclient was stopped or
163 #       the interface exists.
164 #
165 ifconfig_down()
166 {
167         local _cfg
168         _cfg=1
169
170         if wpaif $1; then
171                 /etc/rc.d/wpa_supplicant stop $1
172                 _cfg=0
173         fi
174
175         if dhcpif $1; then
176                 /etc/rc.d/dhclient stop $1
177                 _cfg=0
178         fi
179
180         if ifexists $1; then
181                 ifconfig $1 down
182                 _cfg=0
183         fi
184
185         return $_cfg
186 }
187
188 # get_if_var if var [default]
189 #       Return the value of the pseudo-hash corresponding to $if where
190 #       $var is a string containg the sub-string "IF" which will be
191 #       replaced with $if after the characters defined in _punct are
192 #       replaced with '_'. If the variable is unset, replace it with
193 #       $default if given.
194 get_if_var()
195 {
196         local _if _punct _punct_c _var _default prefix suffix
197
198         if [ $# -ne 2 -a $# -ne 3 ]; then
199                 err 3 'USAGE: get_if_var name var [default]'
200         fi
201
202         _if=$1
203         _punct=". - / +"
204         for _punct_c in $_punct; do
205                 _if=`ltr ${_if} ${_punct_c} '_'`
206         done
207         _var=$2
208         _default=$3
209
210         prefix=${_var%%IF*}
211         suffix=${_var##*IF}
212         eval echo \${${prefix}${_if}${suffix}-${_default}}
213 }
214
215 # _ifconfig_getargs if [af]
216 #       Echos the arguments for the supplied interface to stdout.
217 #       returns 1 if empty.  In general, ifconfig_getargs should be used
218 #       outside this file.
219 _ifconfig_getargs()
220 {
221         local _ifn _af
222         _ifn=$1
223         _af=${2+_$2}
224
225         if [ -z "$_ifn" ]; then
226                 return 1
227         fi
228
229         get_if_var $_ifn ifconfig_IF$_af "$ifconfig_DEFAULT"
230 }
231
232 # ifconfig_getargs if [af]
233 #       Takes the result from _ifconfig_getargs and removes pseudo
234 #       args such as DHCP and WPA.
235 ifconfig_getargs()
236 {
237         local _tmpargs _arg _args
238         _tmpargs=`_ifconfig_getargs $1 $2`
239         if [ $? -eq 1 ]; then
240                 return 1
241         fi
242         _args=
243
244         for _arg in $_tmpargs; do
245                 case $_arg in
246                 [Dd][Hh][Cc][Pp]) ;;
247                 [Nn][Oo][Aa][Uu][Tt][Oo]) ;;
248                 [Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
249                 [Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
250                 [Ww][Pp][Aa]) ;;
251                 *)
252                         _args="$_args $_arg"
253                         ;;
254                 esac
255         done
256
257         echo $_args
258 }
259
260 # autoif
261 #       Returns 0 if the interface should be automaticly configured at
262 #       boot time and 1 otherwise.
263 autoif()
264 {
265         local _tmpargs _arg
266         _tmpargs=`_ifconfig_getargs $1`
267
268         for _arg in $_tmpargs; do
269                 case $_arg in
270                 [Nn][Oo][Aa][Uu][Tt][Oo])
271                         return 1
272                         ;;
273                 esac
274         done
275
276         return 0
277 }
278
279 # dhcpif if
280 #       Returns 0 if the interface is a DHCP interface and 1 otherwise.
281 dhcpif()
282 {
283         local _tmpargs _arg
284         _tmpargs=`_ifconfig_getargs $1`
285
286         for _arg in $_tmpargs; do
287                 case $_arg in
288                 [Dd][Hh][Cc][Pp])
289                         return 0
290                         ;;
291                 [Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
292                         return 0
293                         ;;
294                 [Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
295                         return 0
296                         ;;
297                 esac
298         done
299
300         return 1
301 }
302
303 # syncdhcpif
304 #       Returns 0 if the interface should be configured synchronously and
305 #       1 otherwise.
306 syncdhcpif()
307 {
308         local _tmpargs _arg
309         _tmpargs=`_ifconfig_getargs $1`
310
311         for _arg in $_tmpargs; do
312                 case $_arg in
313                 [Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
314                         return 1
315                         ;;
316                 [Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
317                         return 0
318                         ;;
319                 esac
320         done
321
322         checkyesno synchronous_dhclient
323 }
324
325 # wpaif if
326 #       Returns 0 if the interface is a WPA interface and 1 otherwise.
327 wpaif()
328 {
329         local _tmpargs _arg
330         _tmpargs=`_ifconfig_getargs $1`
331
332         for _arg in $_tmpargs; do
333                 case $_arg in
334                 [Ww][Pp][Aa])
335                         return 0
336                         ;;
337                 esac
338         done
339
340         return 1
341 }
342
343 # afexists af
344 #       Returns 0 if the address family is enabled in the kernel
345 #       1 otherwise.
346 afexists()
347 {
348         local _af
349         _af=$1
350
351         case ${_af} in
352         inet|inet6)
353                 check_kern_features ${_af}
354                 ;;
355         ipx)
356                 ${SYSCTL_N} net.ipx > /dev/null 2>&1
357                 ;;
358         atm)
359                 if [ -x /sbin/atmconfig ]; then
360                         /sbin/atmconfig diag list > /dev/null 2>&1
361                 else
362                         return 1
363                 fi
364                 ;;
365         *)
366                 err 1 "afexists(): Unsupported address family: $_af"
367                 ;;
368         esac
369 }
370
371 # noafif if
372 #       Returns 0 if the interface has no af configuration and 1 otherwise.
373 noafif()
374 {
375         local _if
376         _if=$1
377
378         case $_if in
379         pflog[0-9]*|\
380         pfsync[0-9]*|\
381         an[0-9]*|\
382         ath[0-9]*|\
383         ipw[0-9]*|\
384         ipfw[0-9]*|\
385         iwi[0-9]*|\
386         iwn[0-9]*|\
387         ral[0-9]*|\
388         wi[0-9]*|\
389         wl[0-9]*|\
390         wpi[0-9]*)
391                 return 0
392                 ;;
393         esac
394
395         return 1
396 }
397
398 # ipv6if if
399 #       Returns 0 if the interface should be configured for IPv6 and
400 #       1 otherwise.
401 ipv6if()
402 {
403         local _if _tmpargs i
404         _if=$1
405
406         if ! afexists inet6; then
407                 return 1
408         fi
409
410         # lo0 is always IPv6-enabled
411         case $_if in
412         lo0)
413                 return 0
414                 ;;
415         esac
416
417         case "${ipv6_network_interfaces}" in
418         $_if|"$_if "*|*" $_if"|*" $_if "*|[Aa][Uu][Tt][Oo])
419                 # True if $ifconfig_IF_ipv6 is defined.
420                 _tmpargs=`_ifconfig_getargs $_if ipv6`
421                 if [ -n "${_tmpargs}" ]; then
422                         return 0
423                 fi
424
425                 # backward compatibility: True if $ipv6_ifconfig_IF is defined.
426                 _tmpargs=`get_if_var $_if ipv6_ifconfig_IF`
427                 if [ -n "${_tmpargs}" ]; then
428                         return 0
429                 fi
430                 ;;
431         esac
432
433         return 1
434 }
435
436 # ipv6_autoconfif if
437 #       Returns 0 if the interface should be configured for IPv6 with
438 #       Stateless Address Configuration, 1 otherwise.
439 ipv6_autoconfif()
440 {
441         local _if _tmpargs _arg
442         _if=$1
443
444         case $_if in
445         lo0|\
446         stf[0-9]*|\
447         faith[0-9]*|\
448         lp[0-9]*|\
449         sl[0-9]*)
450                 return 1
451                 ;;
452         esac
453         if noafif $_if; then
454                 return 1
455         fi
456         if ! ipv6if $_if; then
457                 return 1
458         fi
459         if checkyesno ipv6_gateway_enable; then
460                 return 1
461         fi
462         _tmpargs=`get_if_var $_if ipv6_prefix_IF`
463         if [ -n "${_tmpargs}" ]; then
464                 return 1
465         fi
466         # backward compatibility: $ipv6_enable
467         case $ipv6_enable in
468         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
469                 return 0
470         ;;
471         esac
472
473         _tmpargs=`_ifconfig_getargs $_if ipv6`
474         for _arg in $_tmpargs; do
475                 case $_arg in
476                 accept_rtadv)
477                         return 0
478                         ;;
479                 esac
480         done
481
482         # backward compatibility: $ipv6_ifconfig_IF
483         _tmpargs=`get_if_var $_if ipv6_ifconfig_IF`
484         for _arg in $_tmpargs; do
485                 case $_arg in
486                 accept_rtadv)
487                         return 0
488                         ;;
489                 esac
490         done
491
492         return 1
493 }
494
495 # ifexists if
496 #       Returns 0 if the interface exists and 1 otherwise.
497 ifexists()
498 {
499         [ -z "$1" ] && return 1
500         ifconfig -n $1 > /dev/null 2>&1
501 }
502
503 # ipv4_up if
504 #       add IPv4 addresses to the interface $if
505 ipv4_up()
506 {
507         local _if _ret
508         _if=$1
509         _ret=1
510
511         # Add 127.0.0.1/8 to lo0 unless otherwise specified.
512         if [ "${_if}" = "lo0" ]; then
513                 ifconfig_args=`ifconfig_getargs ${_if}`
514                 if [ -z "${ifconfig_args}" ]; then
515                         ifconfig ${_if} inet 127.0.0.1/8 alias
516                 fi
517         fi
518         ifalias_up ${_if} inet && _ret=0
519         ipv4_addrs_common ${_if} alias && _ret=0
520
521         return $_ret
522 }
523
524 # ipv6_up if
525 #       add IPv6 addresses to the interface $if
526 ipv6_up()
527 {
528         local _if _ret
529         _if=$1
530         _ret=1
531
532         if ! ipv6if $_if; then
533                 return 0
534         fi
535
536         ifalias_up ${_if} inet6 && _ret=0
537         ipv6_prefix_hostid_addr_up ${_if} && _ret=0
538         ipv6_accept_rtadv_up ${_if} && _ret=0
539
540         # wait for DAD
541         sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
542         sleep 1
543
544         return $_ret
545 }
546
547 # ipv4_down if
548 #       remove IPv4 addresses from the interface $if
549 ipv4_down()
550 {
551         local _if _ifs _ret inetList oldifs _inet
552         _if=$1
553         _ifs="^"
554         _ret=1
555
556         inetList="`ifconfig ${_if} | grep 'inet ' | tr "\n" "$_ifs"`"
557
558         oldifs="$IFS"
559         IFS="$_ifs"
560         for _inet in $inetList ; do
561                 # get rid of extraneous line
562                 [ -z "$_inet" ] && break
563
564                 _inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
565
566                 IFS="$oldifs"
567                 ifconfig ${_if} ${_inet} delete
568                 IFS="$_ifs"
569                 _ret=0
570         done
571         IFS="$oldifs"
572
573         ifalias_down ${_if} inet && _ret=0
574         ipv4_addrs_common ${_if} -alias && _ret=0
575
576         return $_ret
577 }
578
579 # ipv6_down if
580 #       remove IPv6 addresses from the interface $if
581 ipv6_down()
582 {
583         local _if _ifs _ret inetList oldifs _inet6
584         _if=$1
585         _ifs="^"
586         _ret=1
587
588         if ! ipv6if $_if; then
589                 return 0
590         fi
591
592         ipv6_accept_rtadv_down ${_if} && _ret=0
593         ifalias_down ${_if} inet6 && _ret=0
594
595         inetList="`ifconfig ${_if} | grep 'inet6 ' | tr "\n" "$_ifs"`"
596
597         oldifs="$IFS"
598         IFS="$_ifs"
599         for _inet6 in $inetList ; do
600                 # get rid of extraneous line
601                 [ -z "$_inet6" ] && break
602
603                 _inet6=`expr "$_inet6" : '.*\(inet6 \([0-9a-f:]*\)\).*'`
604
605                 IFS="$oldifs"
606                 ifconfig ${_if} ${_inet6} -alias
607                 IFS="$_ifs"
608                 _ret=0
609         done
610         IFS="$oldifs"
611
612         return $_ret
613 }
614
615 # ipv4_addrs_common if action
616 #       Evaluate the ifconfig_if_ipv4 arguments for interface $if and
617 #       use $action to add or remove IPv4 addresses from $if.
618 ipv4_addrs_common()
619 {
620         local _ret _if _action _cidr _cidr_addr
621         local _ipaddr _netmask _range _ipnet _iplow _iphigh _ipcount
622         _ret=1
623         _if=$1
624         _action=$2
625
626         # get ipv4-addresses
627         cidr_addr=`get_if_var $_if ipv4_addrs_IF`
628
629         for _cidr in ${cidr_addr}; do
630                 _ipaddr=${_cidr%%/*}
631                 _netmask="/"${_cidr##*/}
632                 _range=${_ipaddr##*.}
633                 _ipnet=${_ipaddr%.*}
634                 _iplow=${_range%-*}
635                 _iphigh=${_range#*-}
636
637                 # clear netmask when removing aliases
638                 if [ "${_action}" = "-alias" ]; then
639                         _netmask=""
640                 fi
641
642                 _ipcount=${_iplow}
643                 while [ "${_ipcount}" -le "${_iphigh}" ]; do
644                         eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
645                         _ipcount=$((${_ipcount}+1))
646                         _ret=0
647
648                         # only the first ipaddr in a subnet need the real netmask
649                         if [ "${_action}" != "-alias" ]; then
650                                 _netmask="/32"
651                         fi
652                 done
653         done
654
655         return $_ret
656 }
657
658 # ifalias_up if af
659 #       Configure aliases for network interface $if.
660 #       It returns 0 if at least one alias was configured or
661 #       1 if there were none.
662 #
663 ifalias_up()
664 {
665         local _ret
666         _ret=1
667
668         case "$2" in
669         inet)
670                 _ret=`ifalias_ipv4_up "$1"`
671                 ;;
672         inet6)
673                 _ret=`ifalias_ipv6_up "$1"`
674                 ;;
675         esac
676
677         return $_ret
678 }
679
680 # ifalias_ipv4_up if
681 #       Helper function for ifalias_up().  Handles IPv4.
682 #
683 ifalias_ipv4_up()
684 {
685         local _ret alias ifconfig_args
686         _ret=1
687
688         # ifconfig_IF_aliasN which starts with "inet"
689         alias=0
690         while : ; do
691                 ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
692                 case "${ifconfig_args}" in
693                 inet\ *)
694                         ifconfig $1 ${ifconfig_args} alias && _ret=0
695                         ;;
696                 "")
697                         break
698                         ;;
699                 esac
700                 alias=$((${alias} + 1))
701         done
702
703         return $_ret
704 }
705
706 # ifalias_ipv6_up if
707 #       Helper function for ifalias_up().  Handles IPv6.
708 #
709 ifalias_ipv6_up()
710 {
711         local _ret alias ifconfig_args
712         _ret=1
713
714         # ifconfig_IF_aliasN which starts with "inet6"
715         alias=0
716         while : ; do
717                 ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
718                 case "${ifconfig_args}" in
719                 inet6\ *)
720                         ifconfig $1 ${ifconfig_args} alias && _ret=0
721                         ;;
722                 "")
723                         break
724                         ;;
725                 esac
726                 alias=$((${alias} + 1))
727         done
728
729         # backward compatibility: ipv6_ifconfig_IF_aliasN.
730         alias=0
731         while : ; do
732                 ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
733                 case "${ifconfig_args}" in
734                 "")
735                         break
736                         ;;
737                 *)
738                         ifconfig $1 inet6 ${ifconfig_args} alias && _ret=0
739                         warn "\$ipv6_ifconfig_$1_alias${alias} is obsolete." \
740                             "  Use ifconfig_$1_aliasN instead."
741                         ;;
742                 esac
743                 alias=$((${alias} + 1))
744         done
745
746         return $_ret
747 }
748
749 # ifalias_down if af
750 #       Remove aliases for network interface $if.
751 #       It returns 0 if at least one alias was removed or
752 #       1 if there were none.
753 #
754 ifalias_down()
755 {
756         local _ret
757         _ret=1
758
759         case "$2" in
760         inet)
761                 _ret=`ifalias_ipv4_down "$1"`
762                 ;;
763         inet6)
764                 _ret=`ifalias_ipv6_down "$1"`
765                 ;;
766         esac
767
768         return $_ret
769 }
770
771 # ifalias_ipv4_down if
772 #       Helper function for ifalias_down().  Handles IPv4.
773 #
774 ifalias_ipv4_down()
775 {
776         local _ret alias ifconfig_args
777         _ret=1
778
779         # ifconfig_IF_aliasN which starts with "inet"
780         alias=0
781         while : ; do
782                 ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
783                 case "${ifconfig_args}" in
784                 inet\ *)
785                         ifconfig $1 ${ifconfig_args} -alias && _ret=0
786                         ;;
787                 "")
788                         break
789                         ;;
790                 esac
791                 alias=$((${alias} + 1))
792         done
793
794         return $_ret
795 }
796
797 # ifalias_ipv6_down if
798 #       Helper function for ifalias_down().  Handles IPv6.
799 #
800 ifalias_ipv6_down()
801 {
802         local _ret alias ifconfig_args
803         _ret=1
804
805         # ifconfig_IF_aliasN which starts with "inet6"
806         alias=0
807         while : ; do
808                 ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
809                 case "${ifconfig_args}" in
810                 inet6\ *)
811                         ifconfig $1 ${ifconfig_args} -alias && _ret=0
812                         ;;
813                 "")
814                         break
815                         ;;
816                 esac
817                 alias=$((${alias} + 1))
818         done
819
820         # backward compatibility: ipv6_ifconfig_IF_aliasN.
821         alias=0
822         while : ; do
823                 ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
824                 case "${ifconfig_args}" in
825                 "")
826                         break
827                         ;;
828                 *)
829                         ifconfig $1 inet6 ${ifconfig_args} -alias && _ret=0
830                         warn "\$ipv6_ifconfig_$1_alias${alias} is obsolete." \
831                             "  Use ifconfig_$1_aliasN instead."
832                         ;;
833                 esac
834                 alias=$((${alias} + 1))
835         done
836
837         return $_ret
838 }
839
840 # ipv6_prefix_hostid_addr_up if
841 #       add IPv6 prefix + hostid addr to the interface $if
842 ipv6_prefix_hostid_addr_up()
843 {
844         local _if prefix laddr hostid j address
845         _if=$1
846         prefix=`get_if_var ${_if} ipv6_prefix_IF`
847
848         if [ -n "${prefix}" ]; then
849                 laddr=`network6_getladdr ${_if}`
850                 hostid=${laddr#fe80::}
851                 hostid=${hostid%\%*}
852
853                 for j in ${prefix}; do
854                         address=$j\:${hostid}
855                         ifconfig ${_if} inet6 ${address} prefixlen 64 alias
856
857                         # if I am a router, add subnet router
858                         # anycast address (RFC 2373).
859                         if checkyesno ipv6_gateway_enable; then
860                                 ifconfig ${_if} inet6 $j:: prefixlen 64 \
861                                         alias anycast
862                         fi
863                 done
864         fi
865 }
866
867 # ipv6_accept_rtadv_up if
868 #       Enable accepting Router Advertisement and send Router
869 #       Solicitation message
870 ipv6_accept_rtadv_up()
871 {
872         if ipv6_autoconfif $1; then
873                 ifconfig $1 inet6 accept_rtadv up
874                 if ! checkyesno rtsold_enable; then
875                         rtsol ${rtsol_flags} $1
876                 fi
877         fi
878 }
879
880 # ipv6_accept_rtadv_down if
881 #       Disable accepting Router Advertisement
882 ipv6_accept_rtadv_down()
883 {
884         if ipv6_autoconfif $1; then
885                 ifconfig $1 inet6 -accept_rtadv
886         fi
887 }
888
889 # ifscript_up if
890 #       Evaluate a startup script for the $if interface.
891 #       It returns 0 if a script was found and processed or
892 #       1 if no script was found.
893 #
894 ifscript_up()
895 {
896         if [ -r /etc/start_if.$1 ]; then
897                 . /etc/start_if.$1
898                 return 0
899         else
900                 return 1
901         fi
902 }
903
904 # ifscript_down if
905 #       Evaluate a shutdown script for the $if interface.
906 #       It returns 0 if a script was found and processed or
907 #       1 if no script was found.
908 #
909 ifscript_down()
910 {
911         if [ -r /etc/stop_if.$1 ]; then
912                 . /etc/stop_if.$1
913                 return 0
914         else
915                 return 1
916         fi
917 }
918
919 # clone_up
920 #       Create cloneable interfaces.
921 #
922 clone_up()
923 {
924         local _prefix _list ifn
925         _prefix=
926         _list=
927
928         # create_args_IF
929         for ifn in ${cloned_interfaces}; do
930                 ifconfig ${ifn} create `get_if_var ${ifn} create_args_IF`
931                 if [ $? -eq 0 ]; then
932                         _list="${_list}${_prefix}${ifn}"
933                         [ -z "$_prefix" ] && _prefix=' '
934                 fi
935         done
936         debug "Cloned: ${_list}"
937 }
938
939 # clone_down
940 #       Destroy cloned interfaces. Destroyed interfaces are echoed to
941 #       standard output.
942 #
943 clone_down()
944 {
945         local _prefix _list ifn
946         _prefix=
947         _list=
948
949         for ifn in ${cloned_interfaces}; do
950                 ifconfig -n ${ifn} destroy
951                 if [ $? -eq 0 ]; then
952                         _list="${_list}${_prefix}${ifn}"
953                         [ -z "$_prefix" ] && _prefix=' '
954                 fi
955         done
956         debug "Destroyed clones: ${_list}"
957 }
958
959 # childif_create
960 #       Create and configure child interfaces.  Return 0 if child
961 #       interfaces are created.
962 #
963 childif_create()
964 {
965         local cfg child child_vlans child_wlans create_args debug_flags ifn i
966         cfg=1
967         ifn=$1
968
969         # Create wireless interfaces
970         child_wlans=`get_if_var $ifn wlans_IF`
971
972         for child in ${child_wlans}; do
973                 create_args="wlandev $ifn `get_if_var $child create_args_IF`"
974                 debug_flags="`get_if_var $child wlandebug_IF`"
975
976                 if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
977                         ifconfig $child create ${create_args} && cfg=0
978                         if [ -n "${debug_flags}" ]; then
979                                 wlandebug -i $child ${debug_flags}
980                         fi
981                 else
982                         i=`ifconfig wlan create ${create_args}`
983                         if [ -n "${debug_flags}" ]; then
984                                 wlandebug -i $i ${debug_flags}
985                         fi
986                         ifconfig $i name $child && cfg=0
987                 fi
988                 if autoif $child; then
989                         ifn_start $child
990                 fi
991         done
992
993         # Create vlan interfaces
994         child_vlans=`get_if_var $ifn vlans_IF`
995
996         if [ -n "${child_vlans}" ]; then
997                 load_kld if_vlan
998         fi
999
1000         for child in ${child_vlans}; do
1001                 if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1002                         child="${ifn}.${child}"
1003                         create_args=`get_if_var $child create_args_IF`
1004                         ifconfig $child create ${create_args} && cfg=0
1005                 else
1006                         create_args="vlandev $ifn `get_if_var $child create_args_IF`"
1007                         if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
1008                                 ifconfig $child create ${create_args} && cfg=0
1009                         else
1010                                 i=`ifconfig vlan create ${create_args}`
1011                                 ifconfig $i name $child && cfg=0
1012                         fi
1013                 fi
1014                 if autoif $child; then
1015                         ifn_start $child
1016                 fi
1017         done
1018
1019         return ${cfg}
1020 }
1021
1022 # childif_destroy
1023 #       Destroy child interfaces.
1024 #
1025 childif_destroy()
1026 {
1027         local cfg child child_vlans child_wlans ifn
1028         cfg=1
1029
1030         child_wlans=`get_if_var $ifn wlans_IF`
1031         for child in ${child_wlans}; do
1032                 if ! ifexists $child; then
1033                         continue
1034                 fi
1035                 ifconfig -n $child destroy && cfg=0
1036         done
1037
1038         child_vlans=`get_if_var $ifn vlans_IF`
1039         for child in ${child_vlans}; do
1040                 if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1041                         child="${ifn}.${child}"
1042                 fi
1043                 if ! ifexists $child; then
1044                         continue
1045                 fi
1046                 ifconfig -n $child destroy && cfg=0
1047         done
1048
1049         return ${cfg}
1050 }
1051
1052 # ng_mkpeer
1053 #       Create netgraph nodes.
1054 #
1055 ng_mkpeer()
1056 {
1057         ngctl -f - 2> /dev/null <<EOF
1058 mkpeer $*
1059 msg dummy nodeinfo
1060 EOF
1061 }
1062
1063 # ng_create_one
1064 #       Create netgraph nodes.
1065 #
1066 ng_create_one()
1067 {
1068         local t
1069
1070         ng_mkpeer $* | while read line; do
1071                 t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
1072                 if [ -n "${t}" ]; then
1073                         echo ${t}
1074                         return
1075                 fi
1076         done
1077 }
1078
1079 # gif_up
1080 #       Create gif(4) tunnel interfaces.
1081 gif_up()
1082 {
1083         local i peers
1084
1085         for i in ${gif_interfaces}; do
1086                 peers=`get_if_var $i gifconfig_IF`
1087                 case ${peers} in
1088                 '')
1089                         continue
1090                         ;;
1091                 *)
1092                         if expr $i : 'gif[0-9][0-9]*$' >/dev/null 2>&1; then
1093                                 ifconfig $i create >/dev/null 2>&1
1094                         else
1095                                 gif=`ifconfig gif create`
1096                                 ifconfig $gif name $i
1097                         fi
1098                         ifconfig $i tunnel ${peers}
1099                         ifconfig $i up
1100                         ;;
1101                 esac
1102         done
1103 }
1104
1105 # ng_fec_create ifn
1106 #       Configure Fast EtherChannel for interface $ifn. Returns 0 if
1107 #       FEC arguments were found and configured; returns !0 otherwise.
1108 ng_fec_create()
1109 {
1110          local req_iface iface bogus
1111          req_iface="$1"
1112
1113          ngctl shutdown ${req_iface}: > /dev/null 2>&1
1114
1115          bogus=""
1116          while true; do
1117                  iface=`ng_create_one fec dummy fec`
1118                  if [ -z "${iface}" ]; then
1119                          exit 2
1120                  fi
1121                  if [ "${iface}" = "${req_iface}" ]; then
1122                          break
1123                  fi
1124                  bogus="${bogus} ${iface}"
1125          done
1126
1127          for iface in ${bogus}; do
1128                  ngctl shutdown ${iface}:
1129          done
1130 }
1131
1132 # fec_up
1133 #       Create Fast EtherChannel interfaces.
1134 fec_up()
1135 {
1136         local i j
1137
1138         for i in ${fec_interfaces}; do
1139                 ng_fec_create $i
1140                 for j in `get_if_var $i fecconfig_IF`; do
1141                         case ${j} in
1142                         '')
1143                                 continue
1144                                 ;;
1145                         *)
1146                                 ngctl msg ${i}: add_iface "\"${j}\""
1147                                 ;;
1148                         esac
1149                 done
1150         done
1151 }
1152
1153 # ipx_up ifn
1154 #       Configure any IPX addresses for interface $ifn. Returns 0 if
1155 #       IPX arguments were found and configured; returns 1 otherwise.
1156 #
1157 ipx_up()
1158 {
1159         local ifn
1160         ifn="$1"
1161
1162         # ifconfig_IF_ipx
1163         ifconfig_args=`_ifconfig_getargs $ifn ipx`
1164         if [ -n "${ifconfig_args}" ]; then
1165                 ifconfig ${ifn} ${ifconfig_args}
1166                 return 0
1167         fi
1168
1169         return 1
1170 }
1171
1172 # ipx_down ifn
1173 #       Remove IPX addresses for interface $ifn. Returns 0 if IPX
1174 #       addresses were found and unconfigured. It returns 1, otherwise.
1175 #
1176 ipx_down()
1177 {
1178         local _if _ifs _ret ipxList oldifs _ipx
1179         _if=$1
1180         _ifs="^"
1181         _ret=1
1182         ipxList="`ifconfig ${_if} | grep 'ipx ' | tr "\n" "$_ifs"`"
1183         oldifs="$IFS"
1184
1185         IFS="$_ifs"
1186         for _ipx in $ipxList ; do
1187                 # get rid of extraneous line
1188                 [ -z "$_ipx" ] && break
1189
1190                 _ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
1191
1192                 IFS="$oldifs"
1193                 ifconfig ${_if} ${_ipx} delete
1194                 IFS="$_ifs"
1195                 _ret=0
1196         done
1197         IFS="$oldifs"
1198
1199         return $_ret
1200 }
1201
1202 # ifnet_rename
1203 #       Rename all requested interfaces.
1204 #
1205 ifnet_rename()
1206 {
1207         local _if _ifname
1208
1209         # ifconfig_IF_name
1210         for _if in `ifconfig -l`; do
1211                 _ifname=`get_if_var $_if ifconfig_IF_name`
1212                 if [ ! -z "$_ifname" ]; then
1213                         ifconfig $_if name $_ifname
1214                 fi
1215         done
1216
1217         return 0
1218 }
1219
1220 # list_net_interfaces type
1221 #       List all network interfaces. The type of interface returned
1222 #       can be controlled by the type argument. The type
1223 #       argument can be any of the following:
1224 #               nodhcp  - all interfaces, excluding DHCP configured interfaces
1225 #               dhcp    - list only DHCP configured interfaces
1226 #               noautoconf      - all interfaces, excluding IPv6 Stateless
1227 #                                 Address Autoconf configured interfaces
1228 #               autoconf        - list only IPv6 Stateless Address Autoconf
1229 #                                 configured interfaces
1230 #       If no argument is specified all network interfaces are output.
1231 #       Note that the list will include cloned interfaces if applicable.
1232 #       Cloned interfaces must already exist to have a chance to appear
1233 #       in the list if ${network_interfaces} is set to `auto'.
1234 #
1235 list_net_interfaces()
1236 {
1237         local type _tmplist _list _autolist _lo _if
1238         type=$1
1239
1240         # Get a list of ALL the interfaces and make lo0 first if it's there.
1241         #
1242         _tmplist=
1243         case ${network_interfaces} in
1244         [Aa][Uu][Tt][Oo])
1245                 _autolist="`ifconfig -l`"
1246                 _lo=
1247                 for _if in ${_autolist} ; do
1248                         if autoif $_if; then
1249                                 if [ "$_if" = "lo0" ]; then
1250                                         _lo="lo0 "
1251                                 else
1252                                         _tmplist="${_tmplist} ${_if}"
1253                                 fi
1254                         fi
1255                 done
1256                 _tmplist="${_lo}${_tmplist# }"
1257                 ;;
1258         *)
1259                 _tmplist="${network_interfaces} ${cloned_interfaces}"
1260
1261                 # lo0 is effectively mandatory, so help prevent foot-shooting
1262                 #
1263                 case "$_tmplist" in
1264                 lo0|'lo0 '*|*' lo0'|*' lo0 '*) ;; # This is fine, do nothing
1265                 *)      _tmplist="lo0 ${_tmplist}" ;;
1266                 esac
1267                 ;;
1268         esac
1269
1270         _list=
1271         case "$type" in
1272         nodhcp)
1273                 for _if in ${_tmplist} ; do
1274                         if ! dhcpif $_if && \
1275                            [ -n "`_ifconfig_getargs $_if`" ]; then
1276                                 _list="${_list# } ${_if}"
1277                         fi
1278                 done
1279                 ;;
1280         dhcp)
1281                 for _if in ${_tmplist} ; do
1282                         if dhcpif $_if; then
1283                                 _list="${_list# } ${_if}"
1284                         fi
1285                 done
1286                 ;;
1287         noautoconf)
1288                 for _if in ${_tmplist} ; do
1289                         if ! ipv6_autoconfif $_if && \
1290                            [ -n "`_ifconfig_getargs $_if ipv6`" ]; then
1291                                 _list="${_list# } ${_if}"
1292                         fi
1293                 done
1294                 ;;
1295         autoconf)
1296                 for _if in ${_tmplist} ; do
1297                         if ipv6_autoconfif $_if; then
1298                                 _list="${_list# } ${_if}"
1299                         fi
1300                 done
1301                 ;;
1302         *)
1303                 _list=${_tmplist}
1304                 ;;
1305         esac
1306
1307         echo $_list
1308
1309         return 0
1310 }
1311
1312 # get_default_if -address_family
1313 #       Get the interface of the default route for the given address family.
1314 #       The -address_family argument must be suitable passing to route(8).
1315 #
1316 get_default_if()
1317 {
1318         local routeget oldifs defif line
1319         defif=
1320         oldifs="$IFS"
1321         IFS="
1322 "
1323         for line in `route -n get $1 default 2>/dev/null`; do
1324                 case $line in
1325                 *interface:*)
1326                         defif=${line##*: }
1327                         ;;
1328                 esac
1329         done
1330         IFS=${oldifs}
1331
1332         echo $defif
1333 }
1334
1335 # hexdigit arg
1336 #       Echo decimal number $arg (single digit) in hexadecimal format.
1337 hexdigit()
1338 {
1339         printf '%x\n' "$1"
1340 }
1341
1342 # hexprint arg
1343 #       Echo decimal number $arg (multiple digits) in hexadecimal format.
1344 hexprint()
1345 {
1346         printf '%x\n' "$1"
1347 }
1348
1349 is_wired_interface()
1350 {
1351         local media
1352
1353         case `ifconfig $1 2>/dev/null` in
1354         *media:?Ethernet*) media=Ethernet ;;
1355         esac
1356
1357         test "$media" = "Ethernet"
1358 }
1359
1360 # network6_getladdr if [flag]
1361 #       Echo link-local address from $if if any.
1362 #       If flag is defined, tentative ones will be excluded.
1363 network6_getladdr()
1364 {
1365         local proto addr rest
1366         ifconfig $1 2>/dev/null | while read proto addr rest; do
1367                 case ${proto} in
1368                 inet6)
1369                         case ${addr} in
1370                         fe80::*)
1371                                 if [ -z "$2" ]; then
1372                                         echo ${addr}
1373                                         return
1374                                 fi
1375                                 case ${rest} in
1376                                 *tentative*)
1377                                         continue
1378                                         ;;
1379                                 *)
1380                                         echo ${addr}
1381                                         return
1382                                 esac
1383                         esac
1384                 esac
1385         done
1386 }