[procd init] interface trigger for non-daemon (executables that are not running permanently)

the non-daemon being NFTABLES (userland nft) and having put in place a procd init script it works to the extent of nft actions like starting (invoking at boot and from cli) | stopping (cli) | restarting (cli) are working as expected however it seems that

service_triggers()
procd_add_interface_trigger "interface.*.up" "$iface" $script restart

does not work. Having set PROCD_DEBUG=1 and executing ifdown $iface ; ifup $iface makes it apparent that a service restart is not triggered once the $iface is up.

Is it expected that triggers are only working for daemons but not for executables that are not running permanently?

try netifd trigger or hotplug.

Thanks for the feedback/suggestion, though I am still interested about an answer to the question since the documentation does not state whether procd_add_interface_trigger requires a daemon process running.


How is that supposed to be working/implemented?

Usage: netifd [options]
Options:
 -d <mask>:             Mask for debug messages
 -s <path>:             Path to the ubus socket
 -p <path>:             Path to netifd addons (default: /lib/netifd)
 -c <path>:             Path to UCI configuration
 -h <path>:             Path to the hotplug script
 -r <path>:             Path to resolv.conf
 -l <level>:            Log output level (default: 2)
 -S:                    Use stderr instead of syslog for log messages
                        (default: /sbin/hotplug-call)

/etc/init.d/network
procd_add_reload_trigger 'yourservice'

( personally... i'd be messing with /etc/init.d/firewall or hijacking fw3 via wrapper to implement... two layers for firewall logic is nice to begin with or if necessary but gets painful after a while )

but I do see the complexities with fw3 and there has been lots of talk re: this... i'm sure one of the few caring dev's who put work in here will school us on the intricacies... specifically your question re: nftables and procd service viability/handling... if there is no binary?

That I did Updated nftables and it works to the extent mentioned initially.


There is a binary but just not running permanently. The situation with the fw3 binary appears to be similar since there is "/etc/hotplug.d/iface/20-firewall". Thus it seems prudent to replicate it for the NFT case.

It would be just easier/tidier if procd_add_interface_trigger would also work for binaries that are not running permanently.

1 Like

Works for me, e.g. adblock is not running in the background and uses interface trigger as well. Please post your init script and the output of:

ubus call service list '{"name":"xxx","verbose": true}'

after you've started your service.

#!/bin/sh /etc/rc.common

START=19
USE_PROCD=1
PROCD_DEBUG=1
CONF=/etc/nftables.conf
DESC="firewall service"
NAME=nftables
BIN=/usr/sbin/nft
SCRIPT=/etc/init.d/nft

start_service() {
	# Return
	#  0 if start OK
	#  2 if start NOK

	if [ ! -r "$CONF" ] ; then
		return 2
		logger -st $NAME $DESC "Error: No such config file $CONF"
	fi

	procd_open_instance
	procd_set_param command $BIN -f $CONF
	procd_append_param command || return 0
	procd_set_param file $CONF
	procd_close_instance
}

service_triggers() {
	procd_add_interface_trigger "interface.*.up" br-mgt $SCRIPT restart
	logger -st "test trigger"
}

stop_service() {
	$BIN flush ruleset
	logger -st $NAME $DESC "stopped and ruleset flushed"
}

boot() {
	start
}

{
        "nft": {
                "instances": {
                        "instance1": {
                                "running": false,
                                "command": [
                                        "/usr/sbin/nft",
                                        "-f",
                                        "/etc/nftables.conf"
                                ],
                                "term_timeout": 5
                        }
                },
                "triggers": [
                        [
                                "interface.*.up",
                                [
                                        "if",
                                        [
                                                "eq",
                                                "interface",
                                                "br-mgt"
                                        ],
                                        [
                                                "run_script",
                                                "/etc/init.d/nft",
                                                "restart"
                                        ]
                                ],
                                1000
                        ]
                ]
        }
}

Now, with ifdown mgt ; ifup mgt script is not being triggered.

On a first sight your script looks ok. Please make sure, that you receive an ifup event on ubus. You can trace that e.g. with:

ubus monitor | grep '"method":"up","data":{"interface":"br-mgt"}}'

That did not print anything but ubus monitor | grep '"method":"up","data":{"interface":"mgt"}}' does (device naming convention).

<- 0c06ed4e #101a5d63 invoke: {"objid":270163299,"method":"up","data":{"interface":"mgt"}}

also syslog prints:

netifd: bridge 'br-mgt' link is up
netifd: Interface 'mgt' has link connectivity

For good order sake changed

service_triggers() {
	procd_add_interface_trigger "interface.*.up" mgt $SCRIPT restart
	echo "test trigger"
}

but to no avail, the script is not being triggered either.

Did you restart the init script after your change that the changed interface gets registered?

Yes, but that has not changed the outcome. Also tried some variations, to no avail though

service_triggers() {
	procd_add_interface_trigger "interface.*" mgt $SCRIPT flush ruleset
}
service_triggers() {
	procd_add_interface_trigger "interface.*" "mgt" /etc/init.d/nft flush ruleset
}
service_triggers() {
	procd_add_interface_trigger "interface.*" br-mgt $SCRIPT flush ruleset
}
service_triggers() {
	procd_add_interface_trigger "interface.*" "br-mgt" /etc/init.d/nft flush ruleset
}

For the time being a hotplug script is in place as workaround, tough apparently would have preferred without.

Your last parameter is not quoted thus interpreted as 5 options. Put quotes around the whole command!

/etc/init.d/adblock:				procd_add_interface_trigger "interface.*.up" "${trigger}" "${adb_init}" "${type}"

( thanks dibot :wink: )

not sure that is really necessary, works without quotes in the stop section at least. Nonetheless, implemented that suggestion but that does not change the outcome.