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))
memset(&context->local6, 0, IN6ADDRSZ);
}
- /* 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);
+ inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &all_servers);
+ if (IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
+ multicast_dest = 1;
- if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) &&
- relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
- return;
+ 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. */
+ 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;
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
/* 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,
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;
#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)
{
reset_counter();
state.context = context;
+ state.multicast_dest = multicast_dest;
state.interface = interface;
state.iface_name = iface_name;
state.fallback = fallback;
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)
- {
- /* If server-id provided, it must match. */
- if (opt && (opt6_len(opt) != daemon->duid_len ||
- memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 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)
return 0;
}
else