network.subr revision 230453
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 230453 2012-01-22 10:57:32Z 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
35#	applied, 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	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#
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	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#
84ifconfig_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#
189ifconfig_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.
218get_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.
259ifconfig_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.
287autoif()
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.
305dhcpif()
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.
334syncdhcpif()
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.
359wpaif()
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.
378afexists()
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.
405noafif()
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.
433ipv6if()
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.
477ipv6_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.
535ifexists()
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
543ipv4_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
564ipv6_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
583ipv4_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
615ipv6_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.
653ipv4_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#
698ifalias_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#
718ifalias_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#
751ifalias_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#
796ifalias_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#
816ifalias_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#
842ifalias_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#
885ipv6_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
914ipv6_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
926ipv6_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#
938ifscript_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#
953ifscript_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#
966clone_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#
987clone_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#
1007childif_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#
1069childif_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#
1099ng_mkpeer()
1100{
1101	ngctl -f - 2> /dev/null <<EOF
1102mkpeer $*
1103msg dummy nodeinfo
1104EOF
1105}
1106
1107# ng_create_one
1108#	Create netgraph nodes.
1109#
1110ng_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.
1125gif_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.
1152ng_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.
1178fec_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#
1201ipx_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#
1220ipx_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#
1249ifnet_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#
1279list_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#
1360get_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.
1381hexdigit()
1382{
1383	printf '%x\n' "$1"
1384}
1385
1386# hexprint arg
1387#	Echo decimal number $arg (multiple digits) in hexadecimal format.
1388hexprint()
1389{
1390	printf '%x\n' "$1"
1391}
1392
1393is_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.
1407network6_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}
1431