wg-quick: freebsd: workaround SIOCGIFSTATUS race in FreeBSD kernel
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
		
							parent
							
								
									4471ee711c
								
							
						
					
					
						commit
						090639ae90
					
				@ -137,18 +137,30 @@ del_routes() {
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if_exists() {
 | 
			
		||||
	# HACK: The goal is simply to determine whether or not the interface exists. The
 | 
			
		||||
	# straight-forward way of doing this would be `ifconfig $INTERFACE`, but this
 | 
			
		||||
	# invokes the SIOCGIFSTATUS ioctl, which races with interface shutdown inside
 | 
			
		||||
	# the tun driver, resulting in a kernel panic. So we work around it the stupid
 | 
			
		||||
	# way by using the one utility that appears to call if_nametoindex fairly early
 | 
			
		||||
	# and fails if it doesn't exist: `arp`.
 | 
			
		||||
	if arp -i "$INTERFACE" -a -n >/dev/null 2>&1; then
 | 
			
		||||
		return 0
 | 
			
		||||
	else
 | 
			
		||||
		return 1
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
del_if() {
 | 
			
		||||
	local line monitor_pid
 | 
			
		||||
	[[ $HAVE_SET_DNS -eq 0 ]] || unset_dns
 | 
			
		||||
	exec 39< <(exec route -n monitor 2>/dev/null)
 | 
			
		||||
	monitor_pid=$!
 | 
			
		||||
	cmd rm -f "/var/run/wireguard/$INTERFACE.sock"
 | 
			
		||||
	while ifconfig "$INTERFACE" >/dev/null 2>&1; do
 | 
			
		||||
		while read -r line; do
 | 
			
		||||
			[[ $line =~ ^RTM_IFANNOUNCE:.* ]] && break
 | 
			
		||||
		done <&39
 | 
			
		||||
	while if_exists; do
 | 
			
		||||
		# HACK: it would be nice to `route monitor` here and wait for RTM_IFANNOUNCE
 | 
			
		||||
		# but it turns out that the announcement is made before the interface
 | 
			
		||||
		# disappears so we sometimes get a hang. So, we're instead left with polling
 | 
			
		||||
		# in a sleep loop like this.
 | 
			
		||||
		sleep 0.1
 | 
			
		||||
	done
 | 
			
		||||
	kill $monitor_pid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
up_if() {
 | 
			
		||||
@ -274,7 +286,8 @@ monitor_daemon() {
 | 
			
		||||
	# endpoints change.
 | 
			
		||||
	while read -r event; do
 | 
			
		||||
		[[ $event == RTM_* ]] || continue
 | 
			
		||||
		ifconfig "$INTERFACE" >/dev/null 2>&1 || break
 | 
			
		||||
		[[ -e /var/run/wireguard/$INTERFACE.sock ]] || break
 | 
			
		||||
		if_exists || break
 | 
			
		||||
		[[ $AUTO_ROUTE4 -eq 1 || $AUTO_ROUTE6 -eq 1 ]] && set_endpoint_direct_route
 | 
			
		||||
		# TODO: set the mtu as well, but only if up
 | 
			
		||||
	done < <(route -n monitor)) & disown
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user