git: 0f1ca95d7740 - main - dhclient-script: store the Captive Portal URI
Date: Wed, 07 Oct 2026 14:07:46 UTC
The branch main has been updated by bapt:
URL: https://cgit.FreeBSD.org/src/commit/?id=0f1ca95d7740e0800572ed436fd61e70f76eb6c3
commit 0f1ca95d7740e0800572ed436fd61e70f76eb6c3
Author: Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2026-10-02 19:55:28 +0000
Commit: Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2026-10-07 14:07:09 +0000
dhclient-script: store the Captive Portal URI
Write the URI received in DHCP option 114 to
/var/run/captive-portal.IFACE atomically, with the legacy option 160 as
a fallback, and remove the file on EXPIRE and FAIL.
Reviewed by: bcr (manpage)
Differential Revision: https://reviews.freebsd.org/D60259
---
sbin/dhclient/dhclient-script | 32 ++++++++++++++++++++++++++++++++
sbin/dhclient/dhclient-script.8 | 11 ++++++++++-
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/sbin/dhclient/dhclient-script b/sbin/dhclient/dhclient-script
index 27c424e18118..b2fde6e3ed2a 100755
--- a/sbin/dhclient/dhclient-script
+++ b/sbin/dhclient/dhclient-script
@@ -84,6 +84,34 @@ add_new_alias() {
fi
}
+add_captive_portal() {
+ # DHCP option 114 (RFC 8910), with the legacy DHCP option 160
+ # (RFC 7710) as a fallback.
+ captive_portal_url="${new_captive_portal_url:-$new_captive_portal_legacy}"
+
+ if [ -z "$captive_portal_url" ]; then
+ rm -f /var/run/captive-portal.$interface
+ return 0
+ fi
+
+ $LOGGER "New Captive Portal ($interface): $captive_portal_url"
+
+ captive_portal_tmp=/var/run/captive-portal.${interface}.tmp
+ if ! (umask 022; echo "$captive_portal_url" > $captive_portal_tmp); then
+ rm -f $captive_portal_tmp
+ return 1
+ fi
+ if ! mv $captive_portal_tmp /var/run/captive-portal.$interface; then
+ rm -f $captive_portal_tmp
+ return 1
+ fi
+ return 0
+}
+
+delete_captive_portal() {
+ rm -f /var/run/captive-portal.$interface
+}
+
fill_classless_routes() {
set $1
while [ $# -ge 5 ]; do
@@ -349,6 +377,7 @@ BOUND|RENEW|REBIND|REBOOT)
if [ "$new_ip_address" != "$alias_ip_address" ]; then
add_new_alias
fi
+ add_captive_portal
if is_default_interface; then
add_new_resolv_conf
fi
@@ -356,6 +385,7 @@ BOUND|RENEW|REBIND|REBOOT)
EXPIRE|FAIL)
delete_old_alias
+ delete_captive_portal
if [ -n "$old_ip_address" ]; then
delete_old_address
delete_old_routes
@@ -392,6 +422,7 @@ TIMEOUT)
add_new_alias
fi
add_new_routes
+ add_captive_portal
if ! is_default_interface; then
exit_with_hooks 0
fi
@@ -402,6 +433,7 @@ TIMEOUT)
fi
eval "$IFCONFIG $interface inet -alias $new_ip_address $medium"
delete_old_routes
+ delete_captive_portal
exit_with_hooks 1
;;
esac
diff --git a/sbin/dhclient/dhclient-script.8 b/sbin/dhclient/dhclient-script.8
index dd3efd3e8698..00482da3731c 100644
--- a/sbin/dhclient/dhclient-script.8
+++ b/sbin/dhclient/dhclient-script.8
@@ -36,7 +36,7 @@
.\" see ``http://www.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.\"
-.Dd September 6, 2010
+.Dd October 5, 2026
.Dt DHCLIENT-SCRIPT 8
.Os
.Sh NAME
@@ -142,6 +142,15 @@ in order to make valid shell variables, and the variable names start with
So for example, the new subnet mask would be passed in
.Va $new_subnet_mask .
.Pp
+As an exception, the captive portal API URI from DHCP option 114
+.Pq see Xr dhcp-options 5
+is passed as
+.Va $new_captive_portal_url .
+When such a URI is received, the script also writes it to
+.Pa /var/run/captive-portal. Ns Va $interface
+so that it can be discovered by other programs.
+The file is removed when the lease expires or is lost.
+.Pp
When a binding has been completed, a lot of network parameters are
likely to need to be set up.
A new