mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Fix packet validation in DHCPv6.
Some messages must be sent as multicast.
This commit is contained in:
18
src/dhcp6.c
18
src/dhcp6.c
@@ -176,6 +176,7 @@ void dhcp6_packet(time_t now)
|
||||
else
|
||||
{
|
||||
struct dhcp_bridge *bridge, *alias;
|
||||
int multicast_dest = 0;
|
||||
|
||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
@@ -231,13 +232,20 @@ void dhcp6_packet(time_t now)
|
||||
memset(&context->local6, 0, IN6ADDRSZ);
|
||||
}
|
||||
|
||||
inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &all_servers);
|
||||
if (IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
|
||||
multicast_dest = 1;
|
||||
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
|
||||
if (IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
|
||||
multicast_dest = 1;
|
||||
else
|
||||
{
|
||||
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when
|
||||
we're listening there for DHCPv6 server reasons. */
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) &&
|
||||
relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
|
||||
if (relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!iface_enumerate(AF_INET6, &parm, (callback_t){.af_inet6=complete_context6}))
|
||||
return;
|
||||
@@ -266,7 +274,7 @@ void dhcp6_packet(time_t now)
|
||||
|
||||
lease_prune(NULL, now); /* lose any expired leases */
|
||||
|
||||
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
||||
port = dhcp6_reply(parm.current, multicast_dest, if_index, ifr.ifr_name, &parm.fallback,
|
||||
&parm.ll_addr, &parm.ula_addr, sz, &from.sin6_addr, now);
|
||||
|
||||
/* The port in the source address of the original request should
|
||||
|
||||
@@ -1801,7 +1801,7 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
|
||||
|
||||
/* rfc3315.c */
|
||||
#ifdef HAVE_DHCP6
|
||||
unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
|
||||
unsigned short dhcp6_reply(struct dhcp_context *context, int multicast_dest, int interface, char *iface_name,
|
||||
struct in6_addr *fallback, struct in6_addr *ll_addr, struct in6_addr *ula_addr,
|
||||
size_t sz, struct in6_addr *client_addr, time_t now);
|
||||
int relay_upstream6(int iface_index, ssize_t sz, struct in6_addr *peer_address,
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
struct state {
|
||||
unsigned char *clid;
|
||||
int clid_len, ia_type, interface, hostname_auth, lease_allocate;
|
||||
int multicast_dest, 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;
|
||||
@@ -68,7 +68,7 @@ static void calculate_times(struct dhcp_context *context, unsigned int *min_time
|
||||
#define opt6_user_vendor_next(opt, end) (opt6_next(((uint8_t *) opt) - 2, end))
|
||||
|
||||
|
||||
unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
|
||||
unsigned short dhcp6_reply(struct dhcp_context *context, int multicast_dest, int interface, char *iface_name,
|
||||
struct in6_addr *fallback, struct in6_addr *ll_addr, struct in6_addr *ula_addr,
|
||||
size_t sz, struct in6_addr *client_addr, time_t now)
|
||||
{
|
||||
@@ -87,6 +87,7 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *if
|
||||
|
||||
reset_counter();
|
||||
state.context = context;
|
||||
state.multicast_dest = multicast_dest;
|
||||
state.interface = interface;
|
||||
state.iface_name = iface_name;
|
||||
state.fallback = fallback;
|
||||
@@ -333,22 +334,26 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
||||
else if (msg_type != DHCP6IREQ)
|
||||
return 0;
|
||||
|
||||
/* server-id must match except for SOLICIT, CONFIRM and REBIND messages, which MUST NOT
|
||||
have a server-id. 3315 para 15.x */
|
||||
opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1);
|
||||
|
||||
if (msg_type == DHCP6SOLICIT || msg_type == DHCP6CONFIRM || msg_type == DHCP6REBIND)
|
||||
if (msg_type == DHCP6SOLICIT || msg_type == DHCP6CONFIRM || msg_type == DHCP6REBIND || msg_type == DHCP6IREQ)
|
||||
{
|
||||
if (opt)
|
||||
/* Above message types must be multicast 3315 Section 15. */
|
||||
if (!state->multicast_dest)
|
||||
return 0;
|
||||
}
|
||||
else if (msg_type == DHCP6IREQ)
|
||||
|
||||
/* 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, it must match. */
|
||||
/* 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)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Everything else MUST have a server-id that matches ours. */
|
||||
|
||||
Reference in New Issue
Block a user