Acting on "events" from uci, pushing DHCP information to an external host

How can I get l/uci to push information about the state of the OpenWRT system to an external host? I'd rather not poll the system.

What I have in mind for a start is:

Pushing parsed information about DHCP leases (IP, MAC, Client ID, Vendor Class Identifier) to another system which will talk to CoreDNS and set up specific domain names.

DHCP relay doesn't seem to be quite what I want - I don't want to run a secondary DHCP server

You'll have to run something extra to do this, on either the sender or receiver end. In no particular order:

  1. Simple: set the router to log everything to the receiver using remote syslog, then do the parsing at the receiver with rsyslogd, or tail/bash/perl etc

  2. Slightly trickier: setup a message broker such as MQTT or ZeroMQ. This is an exercise for the reader :slight_smile:

  3. Replace the built-in syslog service with rsyslog, do all the parsing on the router, then use the messaging method of choice to fire the parsed data to the receiver. The world is open to you here; you could use SSH, HTTP, DNS (yes you could!), plain UDP with your data packets carried in it... pretty much anything.

If it were me doing this though, I'd use the first option as it's the one with the smallest number of changes on the OpenWRT end of things.

1 Like
  1. is a good idea
  2. is appealing to me as I already have a broker set up and some integration with other systems - would you patch uci to publish messages?

No, I'd use something like this (note: not my work, untested, YMMV):

But as I said previously, if you just punt the log to a remote syslog receiver you can do all the heavy lifting there.

Started looking at dnsmasq scripts, found hotplug.d

Unfortunately the only variables passed into hotplug are

ACTION
HOSTNAME
IPADDR
MACADDR

and probably client ID, but my example didn't have that.

After working out how ujail was working, reading /etc/init.d/dnsmasq and hammering it into shape, I get a lot more environment variables out of a dhcp userscript:

DNSMASQ_CLIENT_ID
DNSMASQ_INTERFACE
DNSMASQ_LEASE_EXPIRES
DNSMASQ_LOG_DHCP
DNSMASQ_REQUESTED_OPTIONS
DNSMASQ_SUPPLIED_HOSTNAME
DNSMASQ_TAGS
DNSMASQ_TIME_REMAINING
DNSMASQ_VENDOR_CLASS

I'm not that happy with ujail.

Sun Oct  1 16:15:18 2023 daemon.debug dnsmasq-script[1]: /usr/lib/dnsmasq/dhcp-script.sh: /data/dhcpscript.sh: line 2: cut: not found
Sun Oct  1 16:15:18 2023 daemon.debug dnsmasq-script[1]: /usr/lib/dnsmasq/dhcp-script.sh: /data/dhcpscript.sh: line 2: tr: not found
Sun Oct  1 16:15:18 2023 daemon.debug dnsmasq-script[1]: Error loading shared library libmosquitto.so.1: No such file or directory (needed by /usr/bin/mosquitto_pub)
Sun Oct  1 16:15:18 2023 daemon.debug dnsmasq-script[1]: Error loading shared library libcjson.so.1: No such file or directory (needed by /usr/bin/mosquitto_pub)
Sun Oct  1 16:15:18 2023 daemon.debug dnsmasq-script[1]: Error relocating /usr/bin/mosquitto_pub: mosquitto_int_option: symbol not found
Sun Oct  1 16:15:18 2023 daemon.debug dnsmasq-script[1]: Error relocating /usr/bin/mosquitto_pub: mosquitto_property_add_int32: symbol not found
Sun Oct  1 16:15:18 2023 daemon.debug dnsmasq-script[1]: Error relocating /usr/bin/mosquitto_pub: mosquitto_disconnect_v5: symbol not found

Yeah, that's why I suggested using syslog forwarding and doing the heavy work elsewhere!

1 Like

the issue there is that I'm having to track state to be able to parse multiple lines of logs from dnsmasq, instead of being sent info in the right format directly from dnsmasq.

Yes, you're right.

dnsmasq only executes scripts after the lease is handed out (? after ACK?) so if I want to get right down into the nitty gritty I will need to parse syslog.

At any rate, if anyone else gets stuck with doing things the wrong way (not recommended):

  • Edit /etc/init.d/dnsmasq, change DHCPSCRIPT_DEPENDS to something like DHCPSCRIPT_DEPENDS="/usr/share/libubox/jshn.sh /usr/bin/jshn /bin/ubus /usr/bin/jq /data/bin/jo /usr/bin/mosquitto_pub /usr/bin/tr /usr/bin/cut"

(You'll need to bring your own binaries as I have there, /data/bin is my external storage)

  • Edit /etc/config/dhcp to have a line like option dhcpscript '/data/dhcpscript.sh'

  • Create a script like /data/dhcpscript.sh

This is what mine looks like

#!/bin/sh
export | cut -f2 -d ' ' | tr -d "'" | /data/bin/jo | jq --arg ARGH "$1 $2 $3 $4" -c .ARGS='$ARGH' | mosquitto_pub -h mymqttserver -t dhcp -s

What this does:

  • Take the environment variables inherited from dnsmasq and transform them into JSON, then publishes to a topic on my MQTT broker.

The messages look like:

{
    "DNSMASQ_CLIENT_ID": "00:53:ff:ff:ff:ff",
    "DNSMASQ_INTERFACE": "br-lan",
    "DNSMASQ_LEASE_EXPIRES": 1696780585,
    "DNSMASQ_LOG_DHCP": 1,
    "DNSMASQ_REQUESTED_OPTIONS": "1,2,3,6,69",
    "DNSMASQ_SUPPLIED_HOSTNAME": "somehostname",
    "DNSMASQ_TAGS": "lan",
    "DNSMASQ_TIME_REMAINING": 43200,
    "DNSMASQ_VENDOR_CLASS": "vendor",
    "PWD": "/",
    "SHLVL": 1,
    "USER_DHCPSCRIPT": "/data/dhcpscript.sh",
    "container": "ujail",
    "ARGS": "old 00:53:ff:ff:ff:ff 10.0.0.200 somehostname"
}

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.