Add address filtering for leasequery.

This commit is contained in:
Simon Kelley
2025-04-23 16:47:50 +01:00
parent 692ed0dd32
commit 48658ebc54
5 changed files with 41 additions and 9 deletions

View File

@@ -1438,9 +1438,10 @@ DHCP options. This make extra space available in the DHCP packet for
options but can, rarely, confuse old or broken clients. This flag
forces "simple and safe" behaviour to avoid problems in such a case.
.TP
.B --leasequery
.B --leasequery[=<addr>]
Enable RFC 4388 leasequery. The dnsmasq DHCP server will answer LEASEQUERY messages from DHCP relays
when this option is given. To correctly answer lease queries it is necessary to store extra data in
when this option is given. If an address is given, only queries from a relay at that address are allowed. Repeat
the --leasequery option to specify multiple addresses. To correctly answer lease queries it is necessary to store extra data in
the lease database, and this is also enabled by the \fB--leasequery\fP option. The extra fields
(agent-info and vendorclass) are stored in the leases file in a somewhat backwards compatible manner.
Enabling and then disabling leasequery will not cause problems; the extra information will be aged

View File

@@ -384,7 +384,7 @@ void dhcp_packet(time_t now, int pxe_fd)
{
/* Send to BOOTP relay. */
if (is_relay_use_source)
/* restore as-recieved value */
/* restore as-received value */
mess->giaddr.s_addr = INADDR_BROADCAST;
else
{

View File

@@ -854,7 +854,6 @@ struct dhcp_lease {
char *old_hostname; /* hostname before it moved to another lease */
int flags;
time_t expires; /* lease expiry */
time_t last_transaction;
#ifdef HAVE_BROKEN_RTC
unsigned int length;
#endif
@@ -1187,7 +1186,7 @@ extern struct daemon {
char *runfile;
char *lease_change_command;
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
struct bogus_addr *bogus_addr, *ignore_addr;
struct bogus_addr *bogus_addr, *ignore_addr, *leasequery_addr;
struct server *servers, *servers_tail, *local_domains, **serverarray;
struct rebind_domain *no_rebind;
int server_has_wildcard;

View File

@@ -395,7 +395,7 @@ static const struct myoption opts[] =
{ "use-stale-cache", 2, 0 , LOPT_STALE_CACHE },
{ "no-ident", 0, 0, LOPT_NO_IDENT },
{ "max-tcp-connections", 1, 0, LOPT_MAX_PROCS },
{ "leasequery", 0, 0, LOPT_LEASEQUERY },
{ "leasequery", 2, 0, LOPT_LEASEQUERY },
{ NULL, 0, 0, 0 }
};
@@ -501,7 +501,7 @@ static struct {
{ '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
{ LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
{ LOPT_SHARED_NET, ARG_DUP, "<iface>|<addr>,<addr>", gettext_noop("Specify extra networks sharing a broadcast domain for DHCP"), NULL},
{ LOPT_LEASEQUERY, OPT_LEASEQUERY, NULL, gettext_noop("Enable RFC 4388 leasequery functions for DHCPv4"), NULL},
{ LOPT_LEASEQUERY, ARG_DUP, "[<addr>]", gettext_noop("Enable RFC 4388 leasequery functions for DHCPv4"), NULL },
{ '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
{ '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
{ LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
@@ -2916,6 +2916,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
} while (arg);
break;
#ifdef HAVE_DHCP
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
case LOPT_LEASEQUERY:
set_option_bool(OPT_LEASEQUERY);
if (!arg)
break;
#pragma GCC diagnostic pop
#endif
case 'B': /* --bogus-nxdomain */
case LOPT_IGNORE_ADDR: /* --ignore-address */
{
@@ -2951,6 +2960,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
baddr->next = daemon->bogus_addr;
daemon->bogus_addr = baddr;
}
#ifdef HAVE_DHCP
else if (option == LOPT_LEASEQUERY)
{
baddr->next = daemon->leasequery_addr;
daemon->leasequery_addr = baddr;
}
#endif
else
{
baddr->next = daemon->ignore_addr;

View File

@@ -1062,8 +1062,24 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (leasequery_source.s_addr == 0)
return 0;
daemon->metrics[METRIC_DHCPLEASEQUERY]++;
inet_ntop(AF_INET, &leasequery_source, daemon->workspacename, ADDRSTRLEN);
if (daemon->leasequery_addr)
{
struct bogus_addr *baddrp;
for (baddrp = daemon->leasequery_addr; baddrp; baddrp = baddrp->next)
if (!baddrp->is6 && baddrp->addr.addr4.s_addr == leasequery_source.s_addr)
break;
if (!baddrp)
{
my_syslog(MS_DHCP | LOG_WARNING, _("leasequery from %s not permitted"), daemon->workspacename);
return 0;
}
}
daemon->metrics[METRIC_DHCPLEASEQUERY]++;
log_packet("DHCPLEASEQUERY", mess->ciaddr.s_addr ? &mess->ciaddr : NULL, emac_len != 0 ? emac : NULL, emac_len,
iface_name, "from ", daemon->workspacename, mess->xid);