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:
22
src/dhcp6.c
22
src/dhcp6.c
@@ -176,6 +176,7 @@ void dhcp6_packet(time_t now)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct dhcp_bridge *bridge, *alias;
|
struct dhcp_bridge *bridge, *alias;
|
||||||
|
int multicast_dest = 0;
|
||||||
|
|
||||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
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);
|
memset(&context->local6, 0, IN6ADDRSZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when
|
inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &all_servers);
|
||||||
we're listening there for DHCPv6 server reasons. */
|
if (IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
|
||||||
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
|
multicast_dest = 1;
|
||||||
|
|
||||||
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) &&
|
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
|
||||||
relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
|
if (IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
|
||||||
return;
|
multicast_dest = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when
|
||||||
|
we're listening there for DHCPv6 server reasons. */
|
||||||
|
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}))
|
if (!iface_enumerate(AF_INET6, &parm, (callback_t){.af_inet6=complete_context6}))
|
||||||
return;
|
return;
|
||||||
@@ -266,7 +274,7 @@ void dhcp6_packet(time_t now)
|
|||||||
|
|
||||||
lease_prune(NULL, now); /* lose any expired leases */
|
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);
|
&parm.ll_addr, &parm.ula_addr, sz, &from.sin6_addr, now);
|
||||||
|
|
||||||
/* The port in the source address of the original request should
|
/* 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 */
|
/* rfc3315.c */
|
||||||
#ifdef HAVE_DHCP6
|
#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,
|
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);
|
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,
|
int relay_upstream6(int iface_index, ssize_t sz, struct in6_addr *peer_address,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
struct state {
|
struct state {
|
||||||
unsigned char *clid;
|
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;
|
char *client_hostname, *hostname, *domain, *send_domain;
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
struct in6_addr *link_address, *fallback, *ll_addr, *ula_addr;
|
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))
|
#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,
|
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)
|
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();
|
reset_counter();
|
||||||
state.context = context;
|
state.context = context;
|
||||||
|
state.multicast_dest = multicast_dest;
|
||||||
state.interface = interface;
|
state.interface = interface;
|
||||||
state.iface_name = iface_name;
|
state.iface_name = iface_name;
|
||||||
state.fallback = fallback;
|
state.fallback = fallback;
|
||||||
@@ -333,20 +334,24 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||||||
else if (msg_type != DHCP6IREQ)
|
else if (msg_type != DHCP6IREQ)
|
||||||
return 0;
|
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);
|
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;
|
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 server-id provided, it must match. */
|
if (msg_type == DHCP6IREQ)
|
||||||
if (opt && (opt6_len(opt) != daemon->duid_len ||
|
{
|
||||||
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user