[Dnsmasq-discuss] dhcp-script: environment var DNSMASQ_INTERFACE not always set

Geert Stappers stappers at stappers.nl
Tue Aug 8 04:59:39 UTC 2023


On Sun, Aug 06, 2023 at 08:00:11PM +0000, Bastian Bittorf wrote:
> Hello hackers,
> 
> according to 'man dnsmasq' the var DNSMASQ_INTERFACE stores the name
> of the interface on which the request arrived; this is not set for "old"
> actions when dnsmasq restarts.
> 
> all this in done in src/helper.c:
> my_setenv("DNSMASQ_INTERFACE", strlen(data.interface) != 0 ? data.interface : NULL, &err);
> 
> With my (up-to-date) OpenWRT setup this seems sometimes not the case.
> Ontop of my dhcp-script.sh[1] i do (something like):
> 
> 
> #!/bin/sh
> MODE="$1"
> MAC="$2"
> IP="$3"
> HOST="$4"
> 
> if [ -n "$DNSMASQ_INTERFACE" ]; then
>   log "provided dev: $DNSMASQ_INTERFACE mode: $MODE mac: $MAC ip: $IP host: $HOST"
> else
>   DEV="$( guess_dev "$IP" )"
>   log "guessed dev: $DEV mode: $MODE mac: $MAC ip: $IP host: $HOST"
> fi
> 
> 
> Here the log output, when env-var DNSMASQ_INTERFACE is empty/unset and MODE is arp-add/add(!):
> There are 2 interesting lines - both from the same client (linux, under my control):
> 
> provided dev: br-mastergate mode: old mac: e4:f8:9c:73:8b:1f ip: 100.66.19.131 host: filmforecast
> guessed dev:  br-mastergate mode: add mac: e4:f8:9c:73:8b:1f ip: 100.66.19.131 host: unset
> 
> root at box:~ logread | grep e4:f8:9c:73:8b:1f
> Sun Aug  6 21:12:38 2023 daemon.info kalua: /usr/lib/dnsmasq/dhcp-sc: dhcp_script() provided dev: br-mastergate mode: old mac: e4:f8:9c:73:8b:1f ip: 100.66.19.131 host: filmforecast

Network 19

> Sun Aug  6 21:12:38 2023 daemon.info kalua: /usr/lib/dnsmasq/dhcp-sc: dhcp_old() 'e4:f8:9c:73:8b:1f' is from 'br-mastergate' = roaming-DEV HOST: filmforecast
> Sun Aug  6 21:16:01 2023 daemon.info hostapd: phy1-ap0: STA e4:f8:9c:73:8b:1f IEEE 802.11: authenticated
> Sun Aug  6 21:16:01 2023 daemon.info kalua: /usr/sbin/cron.wireless_: iwevent() EVENT 6993: 'phy1-ap0: new station e4:f8:9c:73:8b:1f'
> Sun Aug  6 21:16:01 2023 daemon.info hostapd: phy1-ap0: STA e4:f8:9c:73:8b:1f IEEE 802.11: associated (aid 3)
> Sun Aug  6 21:16:01 2023 daemon.notice hostapd: phy1-ap0: AP-STA-CONNECTED e4:f8:9c:73:8b:1f auth_alg=open


> Sun Aug  6 21:16:01 2023 daemon.info dnsmasq-dhcp[19331]: DHCPREQUEST(br-mastergate) 100.65.42.131 e4:f8:9c:73:8b:1f
> Sun Aug  6 21:16:01 2023 daemon.info dnsmasq-dhcp[19331]: DHCPNAK(br-mastergate) 100.65.42.131 e4:f8:9c:73:8b:1f wrong address

Network 42 DHCPREQUEST  _and_  DHCPNAK


> Sun Aug  6 21:16:01 2023 daemon.info kalua: /usr/sbin/cron.wireless_: wifi_signal_get() dev: phy1-ap0 mac: e4:f8:9c:73:8b:1f try: 3 signal: -64 file: ''
> Sun Aug  6 21:16:01 2023 daemon.info kalua: /usr/sbin/cron.wireless_: iwevent() worker(7175) dev:phy1-ap0 ch:5 MODE: new MAC: e4:f8:9c:73:8b:1f - signal: '-64' border: '-73' try: 4

> Sun Aug  6 21:16:01 2023 daemon.info kalua: /usr/sbin/cron.wireless_: iwevent() mac2ipv4(20) grabbed ip from arp: e4:f8:9c:73:8b:1f -> 100.65.42.131
> Sun Aug  6 21:16:01 2023 daemon.info kalua: /usr/sbin/cron.wireless_: iwevent() worker(7175) dev:phy1-ap0 ch:5 MODE: new MAC: e4:f8:9c:73:8b:1f - ip: '100.65.42.131' signal: '-64' (is_good)

Network 42


> Sun Aug  6 21:16:01 2023 daemon.info dnsmasq-dhcp[19331]: DHCPDISCOVER(br-mastergate) 100.65.42.131 e4:f8:9c:73:8b:1f

A  discover, usualy  0.0.0.0,  this time  100.65.42.131    (Note the 42)


> Sun Aug  6 21:16:01 2023 daemon.info dnsmasq-dhcp[19331]: DHCPOFFER(br-mastergate) 100.66.19.131 e4:f8:9c:73:8b:1f

Note the 19


> Sun Aug  6 21:16:01 2023 daemon.info dnsmasq-dhcp[19331]: DHCPREQUEST(br-mastergate) 100.66.19.131 e4:f8:9c:73:8b:1f
> Sun Aug  6 21:16:01 2023 daemon.info dnsmasq-dhcp[19331]: DHCPACK(br-mastergate) 100.66.19.131 e4:f8:9c:73:8b:1f filmforecast

> Sun Aug  6 21:16:01 2023 daemon.info kalua: /usr/lib/dnsmasq/dhcp-sc: dhcp_script() provided dev: br-mastergate mode: old mac: e4:f8:9c:73:8b:1f ip: 100.66.19.131 host: filmforecast

dhcp_script


> Sun Aug  6 21:16:01 2023 daemon.info kalua: /usr/lib/dnsmasq/dhcp-sc: dhcp_old() 'e4:f8:9c:73:8b:1f' is from 'br-mastergate' = roaming-DEV HOST: filmforecast

dhcp_old


70 seconds

> Sun Aug  6 21:17:11 2023 daemon.info kalua: /usr/lib/dnsmasq/dhcp-sc: dhcp_script() guessed dev: br-mastergate mode: add mac: e4:f8:9c:73:8b:1f ip: 100.66.19.131 host: unset

dhcp_script


> Sun Aug  6 21:17:11 2023 daemon.info kalua: /usr/lib/dnsmasq/dhcp-sc: dhcp_add() 'e4:f8:9c:73:8b:1f' is from 'br-mastergate' = roaming-DEV HOST: unset

dhcp_add


> Sun Aug  6 21:17:11 2023 daemon.info kalua: /usr/lib/dnsmasq/dhcp-sc: F36-stube_dhcp-add() [OK] _weblogin login_check e4:f8:9c:73:8b:1f

dhcp_F36-stube_dhcp-add


> 
> the environment during the "guessed dev" call (without DNSMASQ_INTERFACE set)
> was written ontop of the dhcp-script with:
> {
> echo "# $@"
> set
> } >>"/tmp/dhcp-$2-$1-$3"
> 
> root at F36-stube:~ cat /tmp/dhcp-e4:f8:9c:73:8b:1f-arp-add-100.66.19.131 
> # arp-add e4:f8:9c:73:8b:1f 100.66.19.131
> FUNCNAME=''
> HOME='/'
> HOSTNAME='F36-stube'
> IFS=' 	
> '
> LINENO=''
> OPTIND='1'
> PATH='/usr/sbin:/usr/bin:/sbin:/bin'
> PPID='19337'
> PS1='\w \$ '
> PS2='> '
> PS4='+ '
> PWD='/'
> SHLVL='1'
> TERM='linux'
> USER_DHCPSCRIPT='/etc/dhcp-script.d/10dhcpscript'
> 
> root at F36-stube:~ dnsmasq --version
> Dnsmasq version 2.89  Copyright (c) 2000-2022 Simon Kelley
> ...
> 
> Maybe somebody has an idea why this can happen, looking through the  
> source it is not obvious and *should not happen* 8-) => except 'data.interface' is unknown.
> This happens on different CPU architectures, at least: mips, arm and powerpc.
> 
> I'am happy to test patches or suggestions.

Suggestion:  Dig deeper


> Thanks for your great work & bye,
> Bastian Bittorf

Groeten
Geert Stappers

[1]
#!/bin/sh
. /tmp/loader

MODE="${1:-unset}"
MAC="${2:-ff:00:00:00:00:00}"		# FIXME! this enforces an invalid mac, see sanitizer_mac()
IP="${3:-127.0.0.1}"
HOST="${4:-unset}"

case "$MODE" in
	arp-add) MODE=add ;;
	arp-del) MODE=del ;;
	old) test -e /tmp/CRON_OVERLOAD && exit 0 ;;
esac

case "$MAC" in
	'00:00:00:00:00:00')
		MODE='cron-watchdog'
	;;
	*'-'*)
		_log it dhcp_script daemon info "ignore non-ethernet events: $MAC"
		exit 0
	;;
esac

if   [ -n "$DNSMASQ_INTERFACE" ]; then
	# see: man dnsmasq - we get some env vars, debug with 'set >/tmp/foo' ontop of this script
	# DNSMASQ_CLIENT_ID
	# DNSMASQ_DATA_MISSING
	# DNSMASQ_DOMAIN
	# DNSMASQ_INTERFACE => DNSMASQ_INTERFACE stores the name of the interface on which the request arrived; this is not set for "old" actions when dnsmasq restarts.
	# DNSMASQ_LEASE_EXPIRES
	# DNSMASQ_TIME_REMAINING

	export DNSMASQ_INTERFACE		# needed in netfilter_user_reachable()
	DEV="$DNSMASQ_INTERFACE"
	_log it dhcp_script daemon info "provided dev: $DEV mode: $MODE mac: $MAC ip: $IP host: $HOST"
elif [ -e "$TMPDIR/firmware_burn" ]; then
	exit 0
else
	case "$IP" in fe80::*) exit 0 ;; esac	# ignore IPv6 linklocal, ip2dev() does not work here reliable anyway

	# https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2023q3/017193.html
	DEV="$( _net ip2dev $IP )"
	_log it dhcp_script daemon info "guessed dev: $DEV mode: $MODE mac: $MAC ip: $IP host: $HOST"
fi

case "$DEV" in
	'br-mastergate')
		TYPE='roaming'

		case "$MODE" in
			'add')
				echo "$MAC $IP $DNSMASQ_LEASE_EXPIRES" >>"$TMPDIR/roaming_dhcp_worker"
				# recent entries on top ("tac")
				grep -sn '' "$TMPDIR/roaming_dhcp_worker" | sort -rn | cut -d: -f2- >"$TMPDIR/roaming_dhcp"
			;;
			'del')
				sed -i "/^$MAC/d" "$TMPDIR/roaming_dhcp_worker"
				sed -i "/^$MAC/d" "$TMPDIR/roaming_dhcp"
			;;
		esac
	;;
	$WANDEV)
		TYPE='wan'
	;;
	$LANDEV)
		TYPE='lan'

		case "$MODE" in
			'add'|'old')
				bool_true 'system. at monitoring[0].report_lan_dhcp' && {
					SHOW_HOST="$HOST"
					[ "$SHOW_HOST" = 'unset' ] && SHOW_HOST="$( _net mac2vendor "$MAC" short )"
					echo >>$SCHEDULER_IMPORTANT "_log remote 'lan_dhcp: date: $( date ) CLIENT: mac: $MAC ip: $IP hostname: $SHOW_HOST ROUTER: $HOSTNAME'"
				}
			;;
		esac
	;;
	$WIFIDEV)
		TYPE='wifi'
	;;
	$LODEV)
		TYPE='loopback'
	;;
	'by-mybridge'|'gateway0')	# just for better logging
		TYPE='batman'
	;;
	*)
		TYPE='unknown'
	;;
esac

case "$HOST" in
	'reanimateV2')
		# seed watch_reanimate_dead_neighbour()
		MODE='invalid'
		_http robotstxt_generate
	;;
esac

if [ "$MODE" = 'old' ]; then
	_log it dhcp_$MODE daemon info "'$MAC' is from '$DEV' = ${TYPE}-DEV HOST: $HOST"
else
	_log it dhcp_$MODE daemon info "'$MAC' is from '$DEV' = ${TYPE}-DEV HOST: $HOST"

	case "$MODE-$HOST" in
		'add-check_if_reachable')
			MODE="$HOST"
			_log it dhcp_add_check_if_reachable daemon info "MAC: $MAC IP: $IP DEV: $DEV"
			_netfilter user_add "$MAC" "$IP"
		;;
	esac
fi

case "$MODE" in
	add|old)
		bool_true 'system. at weblogin[0].enabled' && {
			case "$MODE" in
				'old')
					_netfilter user_probe "$MAC" && exit 0
					# maybe unknown after unscheduled reboot, so go further
				;;
				'add')
					case "$TYPE" in
						'roaming')
							echo >>$SCHEDULER_IMPORTANT "_net roaming_report_new $MAC $IP $DNSMASQ_LEASE_EXPIRES"
						;;
					esac
				;;
			esac

			USER="$MAC"
			SIGNAL="${HOSTNAME}_dhcp-${MODE}"				# keyword 'dhcp' is important for login_check()
			export REMOTE_ADDR="$IP"

			if _weblogin login_check "$USER" '' "$MAC" "$SIGNAL" ; then
				# for "very fast unsplashing" and not showing 'please use credentials'
				$IPT -t mangle -I PREROUTING -j ACCEPT
				_log it $SIGNAL daemon info "[OK] _weblogin login_check $USER"
				_netfilter user_add "$MAC" "$IP"
				# remove the hack for "very fast unsplashing"
				$IPT -t mangle -D PREROUTING -j ACCEPT
			else
				if _weblogin login_check "$USER" "$HOSTNAME" "$MAC" "$SIGNAL" ; then
					_log it $SIGNAL daemon info "[OK] _weblogin login_check $USER/$HOSTNAME (2nd try)"
					_netfilter user_add "$MAC" "$IP"
				else
					_log it $SIGNAL daemon info "[ERR] _weblogin login_check $USER/$HOSTNAME"
				fi
			fi
		}

		echo >>$SCHEDULER "_netfilter portforwarding_request $IP $MAC $HOST"
	;;
	del)
#		if bool_true 'system. at weblogin[0].dhcpautologout'; then
			echo >>$SCHEDULER "_netfilter user_del $MAC dhcp_del"
#		else
#			_netfilter set_arp reachable "$MAC" "$IP" "$DEV"
#		fi
	;;
esac

# wrong place but works:
[ -e '/etc/crontabs/root' ] && {
	[ $( _stopwatch stop '/tmp/CRON_LASTCALL' interim,nolog,seconds ) -gt 900 ] && {
		mkdir '/tmp/LOCK_dhcpscript_cron_restart' && {
			_stopwatch start '/tmp/CRON_LASTCALL' global
			_log it watch_cron daemon alert "cron died, restarting"
			/etc/init.d/S51crond_fff+ restart
			rm -fR '/tmp/LOCK_dhcpscript_cron_restart'
		}
	}
}

true
-- 
Silence is hard to parse



More information about the Dnsmasq-discuss mailing list