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