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