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