Custom DHCP script
-
Hello, I have created the following script:
/usr/local/etc/rc.d/dhcpdoverride.sh
file:#/bin/bash killall -3 dhcpd cat /var/dhcpd/etc/dhcpd.conf.ext >> /var/dhcpd/etc/dhcpd.conf # Run: 'ps axww | grep dhcpd' to get /var/run/dhcpd.pid args /usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot /var/dhcpd -cf /etc/dhcpd.conf -pf /var/run/dhcpd.pid igb1
In the
/var/dhcpd/etc/dhcpd.conf.ext
file I have:on commit { set clip = binary-to-ascii(10, 8, ".", leased-address); set clhw = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)); execute("/etc/dhcp_update.sh", "commit", clip, clhw); } on expiry { set clip = binary-to-ascii(10, 8, ".", leased-address); set clhw = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)); execute("/etc/dhcp_update.sh", "expiry", clip, clhw); } on release { set clip = binary-to-ascii(10, 8, ".", leased-address); set clhw = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)); execute("/etc/dhcp_update.sh", "release", clip, clhw); }
This should execute the script every time one of those events is fired.
AFAIK dhcpd is chrooted, so the path
/etc/dhcp_update.sh
should be used, but I also tried/var/dhcpd/etc/dhcp_update.sh
just in case.However, I'm getting the following errors in dhcpd logs for both paths:
Jun 25 02:56:14 dhcpd 90788 execute_statement argv[0] = /etc/dhcp_update.sh Jun 25 02:56:14 dhcpd 90788 execute_statement argv[1] = commit Jun 25 02:56:14 dhcpd 90788 execute_statement argv[2] = 10.1.1.123 Jun 25 02:56:14 dhcpd 90788 execute_statement argv[3] = XX:XX:XX:XX:XX:XX Jun 25 02:56:14 dhcpd 23476 Unable to execute /etc/dhcp_update.sh: No such file or directory Jun 25 02:56:14 dhcpd 90788 execute: /etc/dhcp_update.sh exit status 32512
I have run
chmod +x /var/dhcpd/etc/dhcp_update.sh
from the webui, as I was getting permission denied errors before that.I believe the error code
32512
is actually-127
, but something funky is happening when reporting it. -
I think there is something wrong with dhcp. I tried using
ls
and/bin/ls
and got the same error:execute("/bin/pwd"); execute("/bin/ls");
Returned:
Jun 25 12:38:21 dhcpd 76036 execute_statement argv[0] = /bin/pwd Jun 25 12:38:21 dhcpd 86801 Unable to execute /bin/pwd: No such file or directory Jun 25 12:38:21 dhcpd 76036 execute: /bin/pwd exit status 32512 Jun 25 12:38:21 dhcpd 76036 execute_statement argv[0] = /bin/ls Jun 25 12:38:21 dhcpd 87045 Unable to execute /bin/ls: No such file or directory Jun 25 12:38:21 dhcpd 76036 execute: /bin/ls exit status 32512
-
@Slyke said in Custom DHCP script:
I think there is something wrong with dhcp. I tried using
ls
and/bin/ls
and got the same error:execute("/bin/pwd"); execute("/bin/ls");
Returned:
Jun 25 12:38:21 dhcpd 76036 execute_statement argv[0] = /bin/pwd Jun 25 12:38:21 dhcpd 86801 Unable to execute /bin/pwd: No such file or directory Jun 25 12:38:21 dhcpd 76036 execute: /bin/pwd exit status 32512 Jun 25 12:38:21 dhcpd 76036 execute_statement argv[0] = /bin/ls Jun 25 12:38:21 dhcpd 87045 Unable to execute /bin/ls: No such file or directory Jun 25 12:38:21 dhcpd 76036 execute: /bin/ls exit status 32512
I am pretty sure the
dhcpd
daemon on pfSense runs in achroot
environment and possibly even a FreeBSD jail. That means certain binary utilities that are present on the main pfSense image will not be present and available for thechroot
or jail clients.If you are not familiar with the concept of jails, here is the official FreeBSD documentation: https://docs.freebsd.org/en/books/handbook/jails/. Jails are essentially isolated environments that have the minimum files and permissions needed for the particular binary the jail was created for to execute and perform its assigned tasks.
-
@bmeeks Ah, that makes sense. I'm reading up on it now. Essentially what I'm trying to do is send a GET request when a client connects or disconnects to the network (using DHCP events). I'm just parsing the args and attempting to send a wget/curl command in the
/etc/dhcp_update.sh
script.Is there an easier way to do this while keeping dhcpd chrooted still? Or is there an easy way to add bash and/or curl to the process' chrooted environment? Or should I write some executable in c/c++ and send it that way? Not sure what's the easiest way to achieve this task, and the more I'm digging, the more complex and fragile the solution seems to become.
-
@bmeeks I solved it by copying both the curl and sh binaries into the chrooted folder and specifying the path to them directly:
mkdir -p /var/dhcpd/bin mkdir -p /var/dhcpd/usr/local/bin cp /bin/bash /var/dhcpd/bin/ cp /usr/local/bin/curl /var/dhcpd/usr/local/bin/
Then in my
/var/dhcpd/etc/dhcp_update.sh
script:#!/bin/sh BASE_URL="http://your-web-server.com/your-endpoint" EVENT_TYPE="$1" IP_ADDRESS="$2" MAC_ADDRESS="$3" case "$EVENT_TYPE" in "1") ONLINE_STATE="online" ;; "2"|"3") ONLINE_STATE="offline" ;; *) ONLINE_STATE="unknown" ;; esac URL="${BASE_URL}?ip=${IP_ADDRESS}&mac=${MAC_ADDRESS}&state=${ONLINE_STATE}&event=${EVENT_TYPE}" echo "DHCP Announce: $URL" /usr/local/bin/curl -X GET "$URL"
It aborted with exit code 6, which means that cURL couldn't resolve the hostname (good news!). I still haven't tested this with my proper endpoint, but I think it will work now.