xref: /freebsd/usr.sbin/bsdconfig/networking/share/device.subr (revision 8a166cafe0965f6bd72cd3d2f5372704f05cb5e8)
1if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_SUBR=1
2#
3# Copyright (c) 2006-2012 Devin Teske
4# All Rights Reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26#
27# $FreeBSD$
28#
29############################################################ INCLUDES
30
31BSDCFG_SHARE="/usr/share/bsdconfig"
32. $BSDCFG_SHARE/common.subr || exit 1
33f_dprintf "%s: loading includes..." networking/device.subr
34f_include $BSDCFG_SHARE/dialog.subr
35f_include $BSDCFG_SHARE/sysrc.subr
36f_include $BSDCFG_SHARE/networking/common.subr
37f_include $BSDCFG_SHARE/networking/ipaddr.subr
38f_include $BSDCFG_SHARE/networking/media.subr
39f_include $BSDCFG_SHARE/networking/netmask.subr
40f_include $BSDCFG_SHARE/networking/resolv.subr
41f_include $BSDCFG_SHARE/networking/routing.subr
42
43BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
44f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
45
46TCP_HELPFILE=$BSDCFG_LIBE/$APP_DIR/include/tcp.hlp
47
48############################################################ GLOBALS
49
50#
51# Settings used while interacting with various dialog(1) menus
52#
53: ${DIALOG_MENU_NETDEV_KICK_INTERFACES=1}
54: ${DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK=3}
55
56############################################################ FUNCTIONS
57
58# f_device_desc $device_name
59#
60# Print a description for a device name (eg., `fxp0').
61#
62f_device_desc()
63{
64	local device="$1" d="[1234567890]" desc=""
65
66	# Check variables
67	[ "$device" ] || return $SUCCESS
68
69	#
70	# Return sysctl MIB dev.NAME.UNIT.%desc if it exists,
71	# otherwise fall through to below static list.
72	#
73	if f_have sysctl; then
74		local devname devunit
75		devname="${device%%$d*}"
76		devunit="${device#$devname}"
77		devunit="${devunit%%[a-zA-Z_]*}"
78		sysctl -n "dev.$devname.$devunit.%desc" 2> /dev/null &&
79			return $SUCCESS
80	fi
81
82	case "$device" in
83	# Network devices
84	ae$d)    desc="Attansic/Atheros L2 Fast Ethernet";;
85	age$d)   desc="Attansic/Atheros L1 Gigabit Ethernet";;
86	alc$d)   desc="Atheros AR8131/AR8132 PCIe Ethernet";;
87	ale$d)   desc="Atheros AR8121/AR8113/AR8114 PCIe Ethernet";;
88	an$d)    desc="Aironet 4500/4800 802.11 wireless adapter";;
89	ath$d)   desc="Atheros IEEE 802.11 wireless adapter";;
90	aue$d)   desc="ADMtek USB Ethernet adapter";;
91	axe$d)   desc="ASIX Electronics USB Ethernet adapter";;
92	bce$d)   desc="Broadcom NetXtreme II Gigabit Ethernet card";;
93	bfe$d)   desc="Broadcom BCM440x PCI Ethernet card";;
94	bge$d)   desc="Broadcom BCM570x PCI Gigabit Ethernet card";;
95	bm$d)    desc="Apple BMAC Built-in Ethernet";;
96	bwn$d)   desc="Broadcom BCM43xx IEEE 802.11 wireless adapter";;
97	cas$d)   desc="Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet";;
98	cc3i$d)  desc="SDL HSSI sync serial PCI card";;
99	cue$d)   desc="CATC USB Ethernet adapter";;
100	cxgb$d)  desc="Chelsio T3 10Gb Ethernet card";;
101	dc$d)    desc="DEC/Intel 21143 (and clones) PCI Fast Ethernet card";;
102	de$d)    desc="DEC DE435 PCI NIC or other DC21040-AA based card";;
103	disc$d)  desc="Software discard network interface";;
104	ed$d)    desc="Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA";;
105	el$d)    desc="3Com 3C501 Ethernet card";;
106	em$d)    desc="Intel(R) PRO/1000 Ethernet card";;
107	en$d)    desc="Efficient Networks ATM PCI card";;
108	ep$d)    desc="3Com 3C509 Ethernet card/3C589 PCMCIA";;
109	et$d)    desc="Agere ET1310 based PCI Express Gigabit Ethernet card";;
110	ex$d)    desc="Intel EtherExpress Pro/10 Ethernet card";;
111	fe$d)    desc="Fujitsu MB86960A/MB86965A Ethernet card";;
112	fpa$d)   desc="DEC DEFPA PCI FDDI card";;
113	fwe$d)   desc="FireWire Ethernet emulation";;
114	fwip$d)  desc="IP over FireWire";;
115	fxp$d)   desc="Intel EtherExpress Pro/100B PCI Fast Ethernet card";;
116	gem$d)   desc="Apple GMAC or Sun ERI/GEM Ethernet adapter";;
117	hme$d)   desc="Sun HME (Happy Meal Ethernet) Ethernet adapter";;
118	ie$d)    desc="AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210";;
119	igb$d)   desc="Intel(R) PRO/1000 PCI Express Gigabit Ethernet card";;
120	ipw$d)   desc="Intel PRO/Wireless 2100 IEEE 802.11 adapter";;
121	iwi$d)   desc="Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter";;
122	iwn$d)   desc="Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter";;
123	ix$d)    desc="Intel Etherexpress Ethernet card";;
124	ixgb$d)  desc="Intel(R) PRO/10Gb Ethernet card";;
125	ixgbe$d) desc="Intel(R) PRO/10Gb Ethernet card";;
126	jme$d)   desc="JMicron JMC250 Gigabit/JMC260 Fast Ethernet";;
127	kue$d)   desc="Kawasaki LSI USB Ethernet adapter";;
128	le$d)    desc="AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter";;
129	lge$d)   desc="Level 1 LXT1001 Gigabit Ethernet card";;
130	lnc$d)   desc="Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet";;
131	lp$d)    desc="Parallel Port IP (PLIP) peer connection";;
132	lo$d)    desc="Loop-back (local) network interface";;
133	malo$d)  desc="Marvell Libertas 88W8335 802.11 wireless adapter";;
134	msk$d)   desc="Marvell/SysKonnect Yukon II Gigabit Ethernet";;
135	mxge$d)  desc="Myricom Myri10GE 10Gb Ethernet card";;
136	nfe$d)   desc="NVIDIA nForce MCP Ethernet";;
137	ng${d}_*|ng$d${d}_*|ng$d$d${d}_*|ng$d$d$d${d}_*|ng$d$d$d$d${d}_*)
138	         desc="Vimage netgraph(4) bridged Ethernet device";;
139	nge$d)   desc="NatSemi PCI Gigabit Ethernet card";;
140	nve$d)   desc="NVIDIA nForce MCP Ethernet";;
141	nxge$d)  desc="Neterion Xframe 10GbE Server/Storage adapter";;
142	pcn$d)   desc="AMD Am79c79x PCI Ethernet card";;
143	plip$d)  desc="Parallel Port IP (PLIP) peer connection";;
144	ral$d)   desc="Ralink Technology IEEE 802.11 wireless adapter";;
145	ray$d)   desc="Raytheon Raylink 802.11 wireless adapter";;
146	re$d)    desc="RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter";;
147	rl$d)    desc="RealTek 8129/8139 PCI Ethernet card";;
148	rue$d)   desc="RealTek USB Ethernet card";;
149	rum$d)   desc="Ralink Technology USB IEEE 802.11 wireless adapter";;
150	sf$d)    desc="Adaptec AIC-6915 PCI Ethernet card";;
151	sge$d)   desc="Silicon Integrated Systems SiS190/191 Ethernet";;
152	sis$d)   desc="SiS 900/SiS 7016 PCI Ethernet card";;
153	sk$d)    desc="SysKonnect PCI Gigabit Ethernet card";;
154	sn$d)    desc="SMC/Megahertz Ethernet card";;
155	snc$d)   desc="SONIC Ethernet card";;
156	sr$d)    desc="SDL T1/E1 sync serial PCI card";;
157	ste$d)   desc="Sundance ST201 PCI Ethernet card";;
158	stge$d)  desc="Sundance/Tamarack TC9021 Gigabit Ethernet";;
159	ti$d)    desc="Alteon Networks PCI Gigabit Ethernet card";;
160	tl$d)    desc="Texas Instruments ThunderLAN PCI Ethernet card";;
161	tx$d)    desc="SMC 9432TX Ethernet card";;
162	txp$d)   desc="3Com 3cR990 Ethernet card";;
163	uath$d)  desc="Atheros AR5005UG and AR5005UX USB wireless adapter";;
164	upgt$d)  desc="Conexant/Intersil PrismGT USB wireless adapter";;
165	ural$d)  desc="Ralink Technology RT2500USB 802.11 wireless adapter";;
166	urtw$d)  desc="Realtek 8187L USB wireless adapter";;
167	vge$d)   desc="VIA VT612x PCI Gigabit Ethernet card";;
168	vlan$d|vlan$d$d|vlan$d$d$d|vlan$d$d$d$d|vlan$d$d$d$d$d)
169	         desc="IEEE 802.1Q VLAN network interface";;
170	vr$d)    desc="VIA VT3043/VT86C100A Rhine PCI Ethernet card";;
171	vx$d)    desc="3COM 3c590 / 3c595 Ethernet card";;
172	wb$d)    desc="Winbond W89C840F PCI Ethernet card";;
173	wi$d)    desc="Lucent WaveLAN/IEEE 802.11 wireless adapter";;
174	wpi$d)   desc="Intel 3945ABG IEEE 802.11 wireless adapter";;
175	wx$d)    desc="Intel Gigabit Ethernet (82452) card";;
176	xe$d)    desc="Xircom/Intel EtherExpress Pro100/16 Ethernet card";;
177	xl$d)    desc="3COM 3c90x / 3c90xB PCI Ethernet card";;
178	zyd$d)   desc="ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter";;
179	# Unknown device
180	*)       desc="<unknown network interface type>";;
181	esac
182	printf "%s\n" "$desc"
183}
184
185# f_dialog_menu_netdev
186#
187# Display a list of network devices with descriptions.
188#
189f_dialog_menu_netdev()
190{
191	#
192	# Display a message to let the user know we're working...
193	# (message will remain until we throw up the next dialog)
194	#
195	f_dialog_info "$msg_probing_network_interfaces"
196
197	#
198	# Get list of usable network interfaces
199	#
200	local d='[[:digit:]]+:'
201	local iflist="`echo "$(ifconfig -l):" | sed -E -e "
202		# Convert all spaces to colons
203		y/ /:/
204
205		# Prune unsavory interfaces
206		s/lo$d//g
207		s/ppp$d//g
208		s/sl$d//g
209		s/faith$d//g
210
211		# Convert all colons back into spaces
212		y/:/ /
213	"`"
214
215	#
216	# Optionally kick interfaces in the head to get them to accurately
217	# track the carrier status in realtime (required on FreeBSD).
218	#
219	if [ "$DIALOG_MENU_NETDEV_KICK_INTERFACES" ]; then
220		DIALOG_MENU_NETDEV_KICK_INTERFACES=
221
222		local ifn
223		for ifn in $iflist; do
224			f_quietly ifconfig $ifn up
225		done
226
227		if [ "$DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK" ]; then
228			# interfaces need time to update carrier status
229			sleep $DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK
230		fi
231	fi
232
233	#
234	# Mark any "active" interfaces with an asterisk (*)
235	# to the right of the device name.
236	#
237	interfaces=$(
238		for ifn in $iflist; do
239			active=$( ifconfig $ifn | awk \
240			'
241				( $1 == "status:" ) \
242				{
243					if ( $2 == "active" ) { print 1; exit }
244				}
245			' )
246			printf "'%s%s' '%s'\n" \
247				$ifn "${active:+*}" "$( f_device_desc $ifn )"
248		done
249	)
250	if [ ! "$interfaces" ]; then
251		f_dialog_msgbox "$msg_no_network_interfaces"
252		return $FAILURE
253	fi
254
255	local hline="$hline_arrows_tab_enter"
256
257	#
258	# Ask user to select an interface
259	#
260	local prompt size
261	prompt="$msg_select_network_interface"
262	size=$( eval f_dialog_menu_size \
263	        	\"\$DIALOG_TITLE\"     \
264	        	\"\$DIALOG_BACKTITLE\" \
265	        	\"\$prompt\"           \
266	        	\"\$hline\"            \
267	        	$interfaces            )
268	local dialog_menu
269	dialog_menu=$( eval $DIALOG \
270		--clear --title \"\$DIALOG_TITLE\" \
271		--backtitle \"\$DIALOG_BACKTITLE\" \
272		--hline \"\$hline\"                \
273		--ok-label \"\$msg_ok\"            \
274		--cancel-label \"\$msg_cancel\"    \
275		--menu \"\$prompt\" $size          \
276		$interfaces                        \
277		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
278	)
279	local retval=$?
280	setvar DIALOG_MENU_$$ "$dialog_menu"
281	return $retval
282}
283
284# f_dialog_menu_netdev_edit $interface $ipaddr $netmask $options $dhcp
285#
286# Allow a user to edit network interface settings. Current values are not
287# probed but rather taken from the positional arguments.
288#
289f_dialog_menu_netdev_edit()
290{
291	local interface="$1" ipaddr="$2" netmask="$3" options="$4" dhcp="$5"
292	local prompt menu_list size
293
294	#
295	# Create a duplicate set of variables for change-tracking...
296	#
297	local ipaddr_orig="$2"  \
298	      netmask_orig="$3" \
299	      options_orig="$4" \
300	      dhcp_orig="$5"
301
302	local hline="$hline_arrows_tab_enter"
303	prompt=$( printf "$msg_network_configuration" "$interface" )
304
305	#
306	# Loop forever until the user has finished configuring the different
307	# components of the network interface.
308	#
309	# To apply the settings, we need to know each of the following:
310	# 	- IP Address
311	# 	- Network subnet mask
312	# 	- Additional ifconfig(8) options
313	#
314	# It is only when we have all of the above values that we can make the
315	# changes effective because all three options must be specified at-once
316	# to ifconfig(8).
317	#
318	while :; do
319		local dhcp_status="$msg_disabled"
320		[ "$dhcp" ] && dhcp_status="$msg_enabled"
321
322		#
323		# Display configuration-edit menu
324		#
325		menu_list="
326			'X $msg_save_exit' '$msg_return_to_previous_menu'
327			'2 $msg_dhcp'      '$dhcp_status'
328			'3 $msg_ipaddr4'   '$ipaddr'
329			'4 $msg_netmask'   '$netmask'
330			'5 $msg_options'   '$options'
331		"
332		size=$( eval f_dialog_menu_size \
333		        	\"\$DIALOG_TITLE\"     \
334		        	\"\$DIALOG_BACKTITLE\" \
335		        	\"\$prompt\"           \
336		        	\"\$hline\"            \
337		        	$menu_list             )
338		local dialog_menu
339		dialog_menu=$( eval $DIALOG \
340			--clear --title \"\$DIALOG_TITLE\" \
341			--backtitle \"\$DIALOG_BACKTITLE\" \
342			--hline \"\$hline\"                \
343			--ok-label \"\$msg_ok\"            \
344			--cancel-label \"\$msg_cancel\"    \
345			--help-button                      \
346			--help-label \"\$msg_help\"        \
347			${USE_XDIALOG:+--help \"\"}        \
348			--menu \"\$prompt\" $size          \
349			$menu_list                         \
350			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
351		)
352
353		local retval=$?
354		setvar DIALOG_MENU_$$ "$dialog_menu"
355		local tag="$( f_dialog_menutag )"
356
357		if [ $retval -eq 2 ]; then
358			# The Help button was pressed
359			f_show_help "$TCP_HELPFILE"
360			continue
361		elif [ $retval -ne $SUCCESS ]; then
362			# "Cancel" was chosen (-1) or ESC was pressed (255)
363			return $retval
364		fi
365
366		#
367		# Call the below ``modifier functions'' whose job it is to take
368		# input from the user and assign the newly-acquired values back
369		# to the ipaddr, netmask, and options variables for us to re-
370		# read and display in the summary dialog.
371		#
372		case "$tag" in
373		X\ *) break;;
374		2\ *) #
375		      # Do not proceed if/when there are NFS-mounts currently
376		      # active. If the network is changed while NFS-exported
377		      # directories are mounted, the system may hang (if any
378		      # NFS mounts are using that interface).
379		      #
380		      if f_nfs_mounted && ! f_jailed; then
381		      	local setting="$( printf "$msg_current_dhcp_status" \
382		      	                         "$interface" "$dhcp_status" )"
383			f_show_msg "$msg_nfs_mounts_may_cause_hang" "$setting"
384		      	continue
385		      fi
386
387		      #
388		      # Toggle DHCP status
389		      #
390		      if [ "$dhcp_status" = "$msg_enabled" ]; then
391		      	dhcp=
392		      else
393		      	trap - SIGINT
394		      	( # Execute within sub-shell to allow/catch Ctrl-C
395		      	  trap 'exit $FAILURE' SIGINT
396		      	  msg=$( printf "$msg_scanning_for_dhcp" "$interface" )
397		      	  if [ "$USE_XDIALOG" ]; then
398		      	  	(
399		      	  	  f_quietly ifconfig $interface delete
400		      	  	  f_quietly dhclient $interface
401		      	  	) |
402		      	  	  f_xdialog_info "$msg"
403		      	  else
404		      	  	f_dialog_info "$msg"
405		      	  	f_quietly ifconfig $interface delete
406		      	  	f_quietly dhclient $interface
407		      	  fi
408		      	)
409		      	retval=$?
410		      	trap 'interrupt' SIGINT
411		      	if [ $retval -eq $SUCCESS ]; then
412		      		dhcp=1
413		      		ipaddr=$( f_ifconfig_inet $interface )
414		      		netmask=$( f_ifconfig_netmask $interface )
415		      		options=
416
417		      		# Fixup search/domain in resolv.conf(5)
418		      		hostname=$( f_sysrc_get \
419				            	'hostname:-$(hostname)' )
420		      		f_dialog_resolv_conf_update "$hostname"
421		      	fi
422		      fi
423		      ;;
424		3\ *) f_dialog_input_ipaddr "$interface" "$ipaddr"
425		      [ $? -eq $SUCCESS ] && dhcp=;;
426		4\ *) f_dialog_input_netmask "$interface" "$netmask"
427		      [ $? -eq $SUCCESS -a "$_netmask" ] && dhcp=;;
428		5\ *) f_dialog_menu_media_options "$interface" "$options"
429		      [ $? -eq $SUCCESS ] && dhcp=;;
430		esac
431	done
432
433	#
434	# Save only if the user changed at least one feature of the interface
435	#
436	if [ "$ipaddr"  != "$ipaddr_orig"  -o \
437	     "$netmask" != "$netmask_orig" -o \
438	     "$options" != "$options_orig" -o \
439	     "$dhcp"    != "$dhcp_orig" ]
440	then
441		f_show_info "$msg_saving_network_interface" "$interface"
442
443		local value=
444		if [ "$dhcp" ]; then
445			f_sysrc_delete defaultrouter
446			value=DHCP
447		else
448			value="inet $ipaddr netmask $netmask"
449			value="$value${options:+ }$options"
450		fi
451
452		f_sysrc_set ifconfig_$interface "$value"
453	fi
454
455	#
456	# Re/Apply the settings if desired
457	#
458	if [ ! "$dhcp" ]; then
459		if f_yesno "$msg_bring_interface_up" "$interface"
460		then
461			f_show_info "$msg_bring_interface_up" "$interface"
462
463			local dr="$( f_sysrc_get defaultrouter )" err
464			if [ "$dr" = "NO" -o ! "$dr" ]; then
465				dr=$( f_route_get_default )
466				[ "$dr" ] && f_sysrc_set defaultrouter "$dr"
467			fi
468			#
469			# Make a backup of resolv.conf(5) before using
470			# ifconfig(8) and then restore it afterward. This
471			# allows preservation of nameservers acquired via
472			# DHCP on FreeBSD-8.x (normally lost as ifconfig(8)
473			# usage causes dhclient(8) to exit which scrubs
474			# resolv.conf(5) by-default upon termination).
475			#
476			f_quietly cp -fp "$RESOLV_CONF" "$RESOLV_CONF.$$"
477			err=$( ifconfig $interface inet $ipaddr \
478			       	netmask $netmask $options 2>&1 )
479			if [ $? -eq $SUCCESS ]; then
480				if [ "$dr" -a "$dr" != "NO" ]; then
481					err=$( route add default "$dr" 2>&1 )
482					[ $? -eq $SUCCESS ] || \
483						dialog_msgbox "$err"
484				fi
485			else
486				dialog_msgbox "$err"
487			fi
488			if cmp -s "$RESOLV_CONF" "$RESOLV_CONF.$$"; then
489				f_quietly rm -f "$RESOLV_CONF.$$"
490			else
491				f_quietly mv -f "$RESOLV_CONF.$$" "$RESOLV_CONF"
492			fi
493		fi
494	fi
495
496	return $SUCCESS
497}
498
499############################################################ MAIN
500
501f_dprintf "%s: Successfully loaded." networking/device.subr
502
503fi # ! $_NETWORKING_DEVICE_SUBR
504