network.subr revision 242181
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 242181 2012-10-27 17:06:26Z 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		if checkyesno ipv6_gateway_enable; then
508			return 1
509		else
510			return 0
511		fi
512	;;
513	esac
514
515	_tmpargs=`_ifconfig_getargs $_if ipv6`
516	for _arg in $_tmpargs; do
517		case $_arg in
518		accept_rtadv)
519			return 0
520			;;
521		esac
522	done
523
524	# backward compatibility: $ipv6_ifconfig_IF
525	_tmpargs=`get_if_var $_if ipv6_ifconfig_IF`
526	for _arg in $_tmpargs; do
527		case $_arg in
528		accept_rtadv)
529			return 0
530			;;
531		esac
532	done
533
534	return 1
535}
536
537# ifexists if
538#	Returns 0 if the interface exists and 1 otherwise.
539ifexists()
540{
541	[ -z "$1" ] && return 1
542	ifconfig -n $1 > /dev/null 2>&1
543}
544
545# ipv4_up if
546#	add IPv4 addresses to the interface $if
547ipv4_up()
548{
549	local _if _ret
550	_if=$1
551	_ret=1
552
553	# Add 127.0.0.1/8 to lo0 unless otherwise specified.
554	if [ "${_if}" = "lo0" ]; then
555		ifconfig_args=`get_if_var ${_if} ifconfig_IF`
556		if [ -z "${ifconfig_args}" ]; then
557			ifconfig ${_if} inet 127.0.0.1/8 alias
558		fi
559	fi
560	ifalias_up ${_if} inet && _ret=0
561	ipv4_addrs_common ${_if} alias && _ret=0
562
563	return $_ret
564}
565
566# ipv6_up if
567#	add IPv6 addresses to the interface $if
568ipv6_up()
569{
570	local _if _ret
571	_if=$1
572	_ret=1
573
574	if ! ipv6if $_if; then
575		return 0
576	fi
577
578	ifalias_up ${_if} inet6 && _ret=0
579	ipv6_prefix_hostid_addr_common ${_if} alias && _ret=0
580	ipv6_accept_rtadv_up ${_if} && _ret=0
581
582	return $_ret
583}
584
585# ipv4_down if
586#	remove IPv4 addresses from the interface $if
587ipv4_down()
588{
589	local _if _ifs _ret inetList oldifs _inet
590	_if=$1
591	_ifs="^"
592	_ret=1
593
594	inetList="`ifconfig ${_if} | grep 'inet ' | tr "\n" "$_ifs"`"
595
596	oldifs="$IFS"
597	IFS="$_ifs"
598	for _inet in $inetList ; do
599		# get rid of extraneous line
600		[ -z "$_inet" ] && break
601
602		_inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
603
604		IFS="$oldifs"
605		ifconfig ${_if} ${_inet} delete
606		IFS="$_ifs"
607		_ret=0
608	done
609	IFS="$oldifs"
610
611	ifalias_down ${_if} inet && _ret=0
612	ipv4_addrs_common ${_if} -alias && _ret=0
613
614	return $_ret
615}
616
617# ipv6_down if
618#	remove IPv6 addresses from the interface $if
619ipv6_down()
620{
621	local _if _ifs _ret inetList oldifs _inet6
622	_if=$1
623	_ifs="^"
624	_ret=1
625
626	if ! ipv6if $_if; then
627		return 0
628	fi
629
630	ipv6_accept_rtadv_down ${_if} && _ret=0
631	ipv6_prefix_hostid_addr_common ${_if} -alias && _ret=0
632	ifalias_down ${_if} inet6 && _ret=0
633
634	inetList="`ifconfig ${_if} | grep 'inet6 ' | tr "\n" "$_ifs"`"
635
636	oldifs="$IFS"
637	IFS="$_ifs"
638	for _inet6 in $inetList ; do
639		# get rid of extraneous line
640		[ -z "$_inet6" ] && break
641
642		_inet6=`expr "$_inet6" : '.*\(inet6 \([0-9a-f:]*\)\).*'`
643
644		IFS="$oldifs"
645		ifconfig ${_if} ${_inet6} -alias
646		IFS="$_ifs"
647		_ret=0
648	done
649	IFS="$oldifs"
650
651	return $_ret
652}
653
654# ipv4_addrs_common if action
655#	Evaluate the ifconfig_if_ipv4 arguments for interface $if and
656#	use $action to add or remove IPv4 addresses from $if.
657ipv4_addrs_common()
658{
659	local _ret _if _action _cidr _cidr_addr
660	local _ipaddr _netmask _range _ipnet _iplow _iphigh _ipcount
661	_ret=1
662	_if=$1
663	_action=$2
664
665	# get ipv4-addresses
666	cidr_addr=`get_if_var $_if ipv4_addrs_IF`
667
668	for _cidr in ${cidr_addr}; do
669		_ipaddr=${_cidr%%/*}
670		_netmask="/"${_cidr##*/}
671		_range=${_ipaddr##*.}
672		_ipnet=${_ipaddr%.*}
673		_iplow=${_range%-*}
674		_iphigh=${_range#*-}
675
676		# clear netmask when removing aliases
677		if [ "${_action}" = "-alias" ]; then
678			_netmask=""
679		fi
680
681		_ipcount=${_iplow}
682		while [ "${_ipcount}" -le "${_iphigh}" ]; do
683			eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
684			_ipcount=$((${_ipcount}+1))
685			_ret=0
686
687			# only the first ipaddr in a subnet need the real netmask
688			if [ "${_action}" != "-alias" ]; then
689				_netmask="/32"
690			fi
691		done
692	done
693
694	return $_ret
695}
696
697# ifalias_up if af
698#	Configure aliases for network interface $if.
699#	It returns 0 if at least one alias was configured or
700#	1 if there were none.
701#
702ifalias_up()
703{
704	local _ret
705	_ret=1
706
707	case "$2" in
708	inet)
709		_ret=`ifalias_ipv4_up "$1"`
710		;;
711	inet6)
712		_ret=`ifalias_ipv6_up "$1"`
713		;;
714	esac
715
716	return $_ret
717}
718
719# ifalias_ipv4_up if
720#	Helper function for ifalias_up().  Handles IPv4.
721#
722ifalias_ipv4_up()
723{
724	local _ret alias ifconfig_args
725	_ret=1
726
727	# ifconfig_IF_aliasN which starts with "inet"
728	alias=0
729	while : ; do
730		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
731		case "${ifconfig_args}" in
732		inet\ *)
733			ifconfig $1 ${ifconfig_args} alias && _ret=0
734			;;
735		inet6\ *)
736			;;
737		"")
738			break
739			;;
740		*)
741			warn "\$ifconfig_$1_alias${alias} needs " \
742			    "\"inet\" keyword for an IPv4 address."
743			ifconfig $1 ${ifconfig_args} alias && _ret=0
744			;;
745		esac
746		alias=$((${alias} + 1))
747	done
748
749	return $_ret
750}
751
752# ifalias_ipv6_up if
753#	Helper function for ifalias_up().  Handles IPv6.
754#
755ifalias_ipv6_up()
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	alias=0
777	while : ; do
778		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
779		case "${ifconfig_args}" in
780		"")
781			break
782			;;
783		*)
784			ifconfig $1 inet6 ${ifconfig_args} alias && _ret=0
785			warn "\$ipv6_ifconfig_$1_alias${alias} is obsolete." \
786			    "  Use ifconfig_$1_aliasN instead."
787			;;
788		esac
789		alias=$((${alias} + 1))
790	done
791
792	return $_ret
793}
794
795# ifalias_down if af
796#	Remove aliases for network interface $if.
797#	It returns 0 if at least one alias was removed or
798#	1 if there were none.
799#
800ifalias_down()
801{
802	local _ret
803	_ret=1
804
805	case "$2" in
806	inet)
807		_ret=`ifalias_ipv4_down "$1"`
808		;;
809	inet6)
810		_ret=`ifalias_ipv6_down "$1"`
811		;;
812	esac
813
814	return $_ret
815}
816
817# ifalias_ipv4_down if
818#	Helper function for ifalias_down().  Handles IPv4.
819#
820ifalias_ipv4_down()
821{
822	local _ret alias ifconfig_args
823	_ret=1
824
825	# ifconfig_IF_aliasN which starts with "inet"
826	alias=0
827	while : ; do
828		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
829		case "${ifconfig_args}" in
830		inet\ *)
831			ifconfig $1 ${ifconfig_args} -alias && _ret=0
832			;;
833		"")
834			break
835			;;
836		esac
837		alias=$((${alias} + 1))
838	done
839
840	return $_ret
841}
842
843# ifalias_ipv6_down if
844#	Helper function for ifalias_down().  Handles IPv6.
845#
846ifalias_ipv6_down()
847{
848	local _ret alias ifconfig_args
849	_ret=1
850
851	# ifconfig_IF_aliasN which starts with "inet6"
852	alias=0
853	while : ; do
854		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
855		case "${ifconfig_args}" in
856		inet6\ *)
857			ifconfig $1 ${ifconfig_args} -alias && _ret=0
858			;;
859		"")
860			break
861			;;
862		esac
863		alias=$((${alias} + 1))
864	done
865
866	# backward compatibility: ipv6_ifconfig_IF_aliasN.
867	alias=0
868	while : ; do
869		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
870		case "${ifconfig_args}" in
871		"")
872			break
873			;;
874		*)
875			ifconfig $1 inet6 ${ifconfig_args} -alias && _ret=0
876			warn "\$ipv6_ifconfig_$1_alias${alias} is obsolete." \
877			    "  Use ifconfig_$1_aliasN instead."
878			;;
879		esac
880		alias=$((${alias} + 1))
881	done
882
883	return $_ret
884}
885
886# ipv6_prefix_hostid_addr_common if action
887#	Add or remove IPv6 prefix + hostid addr on the interface $if
888#
889ipv6_prefix_hostid_addr_common()
890{
891	local _if _action prefix laddr hostid j address
892	_if=$1
893	_action=$2
894	prefix=`get_if_var ${_if} ipv6_prefix_IF`
895
896	if [ -n "${prefix}" ]; then
897		laddr=`network6_getladdr ${_if}`
898		hostid=${laddr#fe80::}
899		hostid=${hostid%\%*}
900
901		for j in ${prefix}; do
902			address=$j\:${hostid}
903			ifconfig ${_if} inet6 ${address} prefixlen 64 ${_action}
904
905			# if I am a router, add subnet router
906			# anycast address (RFC 2373).
907			if checkyesno ipv6_gateway_enable; then
908				ifconfig ${_if} inet6 $j:: prefixlen 64 \
909					${_action} anycast
910			fi
911		done
912	fi
913}
914
915# ipv6_accept_rtadv_up if
916#	Enable accepting Router Advertisement and send Router
917#	Solicitation message
918ipv6_accept_rtadv_up()
919{
920	if ipv6_autoconfif $1; then
921		ifconfig $1 inet6 accept_rtadv up
922		if ! checkyesno rtsold_enable; then
923			rtsol ${rtsol_flags} $1
924		fi
925	fi
926}
927
928# ipv6_accept_rtadv_down if
929#	Disable accepting Router Advertisement
930ipv6_accept_rtadv_down()
931{
932	if ipv6_autoconfif $1; then
933		ifconfig $1 inet6 -accept_rtadv
934	fi
935}
936
937# ifscript_up if
938#	Evaluate a startup script for the $if interface.
939#	It returns 0 if a script was found and processed or
940#	1 if no script was found.
941#
942ifscript_up()
943{
944	if [ -r /etc/start_if.$1 ]; then
945		. /etc/start_if.$1
946		return 0
947	else
948		return 1
949	fi
950}
951
952# ifscript_down if
953#	Evaluate a shutdown script for the $if interface.
954#	It returns 0 if a script was found and processed or
955#	1 if no script was found.
956#
957ifscript_down()
958{
959	if [ -r /etc/stop_if.$1 ]; then
960		. /etc/stop_if.$1
961		return 0
962	else
963		return 1
964	fi
965}
966
967# clone_up
968#	Create cloneable interfaces.
969#
970clone_up()
971{
972	local _prefix _list ifn
973	_prefix=
974	_list=
975
976	# create_args_IF
977	for ifn in ${cloned_interfaces}; do
978		ifconfig ${ifn} create `get_if_var ${ifn} create_args_IF`
979		if [ $? -eq 0 ]; then
980			_list="${_list}${_prefix}${ifn}"
981			[ -z "$_prefix" ] && _prefix=' '
982		fi
983	done
984	debug "Cloned: ${_list}"
985}
986
987# clone_down
988#	Destroy cloned interfaces. Destroyed interfaces are echoed to
989#	standard output.
990#
991clone_down()
992{
993	local _prefix _list ifn
994	_prefix=
995	_list=
996
997	for ifn in ${cloned_interfaces}; do
998		ifconfig -n ${ifn} destroy
999		if [ $? -eq 0 ]; then
1000			_list="${_list}${_prefix}${ifn}"
1001			[ -z "$_prefix" ] && _prefix=' '
1002		fi
1003	done
1004	debug "Destroyed clones: ${_list}"
1005}
1006
1007# childif_create
1008#	Create and configure child interfaces.  Return 0 if child
1009#	interfaces are created.
1010#
1011childif_create()
1012{
1013	local cfg child child_vlans child_wlans create_args debug_flags ifn i
1014	cfg=1
1015	ifn=$1
1016
1017	# Create wireless interfaces
1018	child_wlans=`get_if_var $ifn wlans_IF`
1019
1020	for child in ${child_wlans}; do
1021		create_args="wlandev $ifn `get_if_var $child create_args_IF`"
1022		debug_flags="`get_if_var $child wlandebug_IF`"
1023
1024		if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
1025			ifconfig $child create ${create_args} && cfg=0
1026			if [ -n "${debug_flags}" ]; then
1027				wlandebug -i $child ${debug_flags}
1028			fi
1029		else
1030			i=`ifconfig wlan create ${create_args}`
1031			if [ -n "${debug_flags}" ]; then
1032				wlandebug -i $i ${debug_flags}
1033			fi
1034			ifconfig $i name $child && cfg=0
1035		fi
1036		if autoif $child; then
1037			ifn_start $child
1038		fi
1039	done
1040
1041	# Create vlan interfaces
1042	child_vlans=`get_if_var $ifn vlans_IF`
1043
1044	if [ -n "${child_vlans}" ]; then
1045		load_kld if_vlan
1046	fi
1047
1048	for child in ${child_vlans}; do
1049		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1050			child="${ifn}.${child}"
1051			create_args=`get_if_var $child create_args_IF`
1052			ifconfig $child create ${create_args} && cfg=0
1053		else
1054			create_args="vlandev $ifn `get_if_var $child create_args_IF`"
1055			if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
1056				ifconfig $child create ${create_args} && cfg=0
1057			else
1058				i=`ifconfig vlan create ${create_args}`
1059				ifconfig $i name $child && cfg=0
1060			fi
1061		fi
1062		if autoif $child; then
1063			ifn_start $child
1064		fi
1065	done
1066
1067	return ${cfg}
1068}
1069
1070# childif_destroy
1071#	Destroy child interfaces.
1072#
1073childif_destroy()
1074{
1075	local cfg child child_vlans child_wlans ifn
1076	cfg=1
1077
1078	child_wlans=`get_if_var $ifn wlans_IF`
1079	for child in ${child_wlans}; do
1080		if ! ifexists $child; then
1081			continue
1082		fi
1083		ifconfig -n $child destroy && cfg=0
1084	done
1085
1086	child_vlans=`get_if_var $ifn vlans_IF`
1087	for child in ${child_vlans}; do
1088		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1089			child="${ifn}.${child}"
1090		fi
1091		if ! ifexists $child; then
1092			continue
1093		fi
1094		ifconfig -n $child destroy && cfg=0
1095	done
1096
1097	return ${cfg}
1098}
1099
1100# ng_mkpeer
1101#	Create netgraph nodes.
1102#
1103ng_mkpeer()
1104{
1105	ngctl -f - 2> /dev/null <<EOF
1106mkpeer $*
1107msg dummy nodeinfo
1108EOF
1109}
1110
1111# ng_create_one
1112#	Create netgraph nodes.
1113#
1114ng_create_one()
1115{
1116	local t
1117
1118	ng_mkpeer $* | while read line; do
1119		t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
1120		if [ -n "${t}" ]; then
1121			echo ${t}
1122			return
1123		fi
1124	done
1125}
1126
1127# gif_up
1128#	Create gif(4) tunnel interfaces.
1129gif_up()
1130{
1131	local i peers
1132
1133	for i in ${gif_interfaces}; do
1134		peers=`get_if_var $i gifconfig_IF`
1135		case ${peers} in
1136		'')
1137			continue
1138			;;
1139		*)
1140			if expr $i : 'gif[0-9][0-9]*$' >/dev/null 2>&1; then
1141				ifconfig $i create >/dev/null 2>&1
1142			else
1143				gif=`ifconfig gif create`
1144				ifconfig $gif name $i
1145			fi
1146			ifconfig $i tunnel ${peers}
1147			ifconfig $i up
1148			;;
1149		esac
1150	done
1151}
1152
1153# ng_fec_create ifn
1154#	Configure Fast EtherChannel for interface $ifn. Returns 0 if
1155#	FEC arguments were found and configured; returns !0 otherwise.
1156ng_fec_create()
1157{
1158	 local req_iface iface bogus
1159	 req_iface="$1"
1160
1161	 ngctl shutdown ${req_iface}: > /dev/null 2>&1
1162
1163	 bogus=""
1164	 while true; do
1165		 iface=`ng_create_one fec dummy fec`
1166		 if [ -z "${iface}" ]; then
1167			 exit 2
1168		 fi
1169		 if [ "${iface}" = "${req_iface}" ]; then
1170			 break
1171		 fi
1172		 bogus="${bogus} ${iface}"
1173	 done
1174
1175	 for iface in ${bogus}; do
1176		 ngctl shutdown ${iface}:
1177	 done
1178}
1179
1180# fec_up
1181#	Create Fast EtherChannel interfaces.
1182fec_up()
1183{
1184	local i j
1185
1186	for i in ${fec_interfaces}; do
1187		ng_fec_create $i
1188		for j in `get_if_var $i fecconfig_IF`; do
1189			case ${j} in
1190			'')
1191				continue
1192				;;
1193			*)
1194				ngctl msg ${i}: add_iface "\"${j}\""
1195				;;
1196			esac
1197		done
1198	done
1199}
1200
1201# ipx_up ifn
1202#	Configure any IPX addresses for interface $ifn. Returns 0 if
1203#	IPX arguments were found and configured; returns 1 otherwise.
1204#
1205ipx_up()
1206{
1207	local ifn
1208	ifn="$1"
1209
1210	# ifconfig_IF_ipx
1211	ifconfig_args=`_ifconfig_getargs $ifn ipx`
1212	if [ -n "${ifconfig_args}" ]; then
1213		ifconfig ${ifn} ${ifconfig_args}
1214		return 0
1215	fi
1216
1217	return 1
1218}
1219
1220# ipx_down ifn
1221#	Remove IPX addresses for interface $ifn. Returns 0 if IPX
1222#	addresses were found and unconfigured. It returns 1, otherwise.
1223#
1224ipx_down()
1225{
1226	local _if _ifs _ret ipxList oldifs _ipx
1227	_if=$1
1228	_ifs="^"
1229	_ret=1
1230	ipxList="`ifconfig ${_if} | grep 'ipx ' | tr "\n" "$_ifs"`"
1231	oldifs="$IFS"
1232
1233	IFS="$_ifs"
1234	for _ipx in $ipxList ; do
1235		# get rid of extraneous line
1236		[ -z "$_ipx" ] && break
1237
1238		_ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
1239
1240		IFS="$oldifs"
1241		ifconfig ${_if} ${_ipx} delete
1242		IFS="$_ifs"
1243		_ret=0
1244	done
1245	IFS="$oldifs"
1246
1247	return $_ret
1248}
1249
1250# ifnet_rename
1251#	Rename all requested interfaces.
1252#
1253ifnet_rename()
1254{
1255	local _if _ifname
1256
1257	# ifconfig_IF_name
1258	for _if in `ifconfig -l`; do
1259		_ifname=`get_if_var $_if ifconfig_IF_name`
1260		if [ ! -z "$_ifname" ]; then
1261			ifconfig $_if name $_ifname
1262		fi
1263	done
1264
1265	return 0
1266}
1267
1268# list_net_interfaces type
1269#	List all network interfaces. The type of interface returned
1270#	can be controlled by the type argument. The type
1271#	argument can be any of the following:
1272#		nodhcp	- all interfaces, excluding DHCP configured interfaces
1273#		dhcp	- list only DHCP configured interfaces
1274#		noautoconf	- all interfaces, excluding IPv6 Stateless
1275#				  Address Autoconf configured interfaces
1276#		autoconf	- list only IPv6 Stateless Address Autoconf
1277#				  configured interfaces
1278#	If no argument is specified all network interfaces are output.
1279#	Note that the list will include cloned interfaces if applicable.
1280#	Cloned interfaces must already exist to have a chance to appear
1281#	in the list if ${network_interfaces} is set to `auto'.
1282#
1283list_net_interfaces()
1284{
1285	local type _tmplist _list _autolist _lo _if
1286	type=$1
1287
1288	# Get a list of ALL the interfaces and make lo0 first if it's there.
1289	#
1290	_tmplist=
1291	case ${network_interfaces} in
1292	[Aa][Uu][Tt][Oo])
1293		_autolist="`ifconfig -l`"
1294		_lo=
1295		for _if in ${_autolist} ; do
1296			if autoif $_if; then
1297				if [ "$_if" = "lo0" ]; then
1298					_lo="lo0 "
1299				else
1300					_tmplist="${_tmplist} ${_if}"
1301				fi
1302			fi
1303		done
1304		_tmplist="${_lo}${_tmplist# }"
1305		;;
1306	*)
1307		_tmplist="${network_interfaces} ${cloned_interfaces}"
1308
1309		# lo0 is effectively mandatory, so help prevent foot-shooting
1310		#
1311		case "$_tmplist" in
1312		lo0|'lo0 '*|*' lo0'|*' lo0 '*) ;; # This is fine, do nothing
1313		*)	_tmplist="lo0 ${_tmplist}" ;;
1314		esac
1315		;;
1316	esac
1317
1318	_list=
1319	case "$type" in
1320	nodhcp)
1321		for _if in ${_tmplist} ; do
1322			if ! dhcpif $_if && \
1323			   [ -n "`_ifconfig_getargs $_if`" ]; then
1324				_list="${_list# } ${_if}"
1325			fi
1326		done
1327		;;
1328	dhcp)
1329		for _if in ${_tmplist} ; do
1330			if dhcpif $_if; then
1331				_list="${_list# } ${_if}"
1332			fi
1333		done
1334		;;
1335	noautoconf)
1336		for _if in ${_tmplist} ; do
1337			if ! ipv6_autoconfif $_if && \
1338			   [ -n "`_ifconfig_getargs $_if ipv6`" ]; then
1339				_list="${_list# } ${_if}"
1340			fi
1341		done
1342		;;
1343	autoconf)
1344		for _if in ${_tmplist} ; do
1345			if ipv6_autoconfif $_if; then
1346				_list="${_list# } ${_if}"
1347			fi
1348		done
1349		;;
1350	*)
1351		_list=${_tmplist}
1352		;;
1353	esac
1354
1355	echo $_list
1356
1357	return 0
1358}
1359
1360# get_default_if -address_family
1361#	Get the interface of the default route for the given address family.
1362#	The -address_family argument must be suitable passing to route(8).
1363#
1364get_default_if()
1365{
1366	local routeget oldifs defif line
1367	defif=
1368	oldifs="$IFS"
1369	IFS="
1370"
1371	for line in `route -n get $1 default 2>/dev/null`; do
1372		case $line in
1373		*interface:*)
1374			defif=${line##*: }
1375			;;
1376		esac
1377	done
1378	IFS=${oldifs}
1379
1380	echo $defif
1381}
1382
1383# hexdigit arg
1384#	Echo decimal number $arg (single digit) in hexadecimal format.
1385hexdigit()
1386{
1387	printf '%x\n' "$1"
1388}
1389
1390# hexprint arg
1391#	Echo decimal number $arg (multiple digits) in hexadecimal format.
1392hexprint()
1393{
1394	printf '%x\n' "$1"
1395}
1396
1397is_wired_interface()
1398{
1399	local media
1400
1401	case `ifconfig $1 2>/dev/null` in
1402	*media:?Ethernet*) media=Ethernet ;;
1403	esac
1404
1405	test "$media" = "Ethernet"
1406}
1407
1408# network6_getladdr if [flag]
1409#	Echo link-local address from $if if any.
1410#	If flag is defined, tentative ones will be excluded.
1411network6_getladdr()
1412{
1413	local proto addr rest
1414	ifconfig $1 2>/dev/null | while read proto addr rest; do
1415		case ${proto} in
1416		inet6)
1417			case ${addr} in
1418			fe80::*)
1419				if [ -z "$2" ]; then
1420					echo ${addr}
1421					return
1422				fi
1423				case ${rest} in
1424				*tentative*)
1425					continue
1426					;;
1427				*)
1428					echo ${addr}
1429					return
1430				esac
1431			esac
1432		esac
1433	done
1434}
1435