summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2023-04-24 15:07:55 +0100
committerSimon Kelley <simon@thekelleys.org.uk>2023-04-24 17:43:02 +0100
commit7500157cff8ea28ab03e6e62e0d1575e4d01746b (patch)
treeb9eb21e6b2cb137a119d4d0b51a990c639a2154b
parent52e6ad2761e4e39c3e89fe3b8d68b98cf538a27c (diff)
downloaddnsmasq-7500157cff8ea28ab03e6e62e0d1575e4d01746b.tar.gz
Improve RFC3315 para 15 packet validation.
Thanks to Shashikumar Shashil for spotting the ommision.
-rw-r--r--src/rfc3315.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/src/rfc3315.c b/src/rfc3315.c
index d513844..c2e2692 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -333,12 +333,29 @@ 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 */
- if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ && msg_type != DHCP6REBIND &&
- (!(opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1)) ||
- opt6_len(opt) != daemon->duid_len ||
- memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 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);
+
+ if (msg_type == DHCP6SOLICIT || msg_type == DHCP6CONFIRM || msg_type == DHCP6REBIND)
+ {
+ if (opt)
+ 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))
+ return 0;
+ }
+ else
+ {
+ /* Everything else MUST have a server-id that matches ours. */
+ if (!opt || opt6_len(opt) != daemon->duid_len ||
+ memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0)
+ return 0;
+ }
o = new_opt6(OPTION6_SERVER_ID);
put_opt6(daemon->duid, daemon->duid_len);
@@ -1105,6 +1122,11 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
case DHCP6IREQ:
{
+ /* 3315 para 15.12 */
+ if (opt6_find(state->packet_options, state->end, OPTION6_IA_NA, 1) ||
+ opt6_find(state->packet_options, state->end, OPTION6_IA_TA, 1))
+ return 0;
+
/* We can't discriminate contexts based on address, as we don't know it.
If there is only one possible context, we can use its tags */
if (state->context && state->context->netid.net && !state->context->current)