Tidy up check for muticast DHCPv6 requests.

Anything sent by a client must be multicast. A relay can unicast
to a server.
This commit is contained in:
Simon Kelley
2026-01-31 20:40:21 +00:00
parent 60e90e2224
commit 714d36229a

View File

@@ -21,7 +21,7 @@
struct state {
unsigned char *clid;
int multicast_dest, clid_len, ia_type, interface, hostname_auth, lease_allocate;
int clid_len, ia_type, interface, hostname_auth, lease_allocate;
char *client_hostname, *hostname, *domain, *send_domain;
struct dhcp_context *context;
struct in6_addr *link_address, *fallback, *ll_addr, *ula_addr;
@@ -80,6 +80,10 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int multicast_dest, int
return 0;
msg_type = *((unsigned char *)daemon->dhcp_packet.iov_base);
/* request from a client must be multicast RFC-9915 section 16 */
if (msg_type != DHCP6RELAYFORW && !multicast_dest)
return 0;
/* Mark these so we only match each at most once, to avoid tangled linked lists */
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
@@ -87,7 +91,6 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int multicast_dest, int
reset_counter();
state.context = context;
state.multicast_dest = multicast_dest;
state.interface = interface;
state.iface_name = iface_name;
state.fallback = fallback;
@@ -337,22 +340,17 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1);
if (msg_type == DHCP6SOLICIT || msg_type == DHCP6CONFIRM || msg_type == DHCP6REBIND || msg_type == DHCP6IREQ)
if (msg_type == DHCP6SOLICIT || msg_type == DHCP6CONFIRM || msg_type == DHCP6REBIND)
{
/* Above message types must be multicast 3315 Section 15. */
if (!state->multicast_dest)
/* SOLICIT, CONFIRM and REBIND messages MUST NOT have a server-id. 3315 para 15.x */
if (opt)
return 0;
/* server-id must match except for SOLICIT, CONFIRM and REBIND messages, which MUST NOT
have a server-id. 3315 para 15.x */
if (msg_type == DHCP6IREQ)
{
/* If server-id provided in IREQ, it must match. */
if (opt && (opt6_len(opt) != daemon->duid_len ||
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
return 0;
}
else if (opt)
}
else if (msg_type == DHCP6IREQ)
{
/* If server-id provided in IREQ, it must match. */
if (opt && (opt6_len(opt) != daemon->duid_len ||
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
return 0;
}
else