diff --git a/src/rfc3315.c b/src/rfc3315.c index ad38544..94ce42d 100644 --- a/src/rfc3315.c +++ b/src/rfc3315.c @@ -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