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