diff options
author | Simon Kelley <simon@thekelleys.org.uk> | 2023-04-24 15:07:55 +0100 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2023-04-24 17:43:02 +0100 |
commit | 7500157cff8ea28ab03e6e62e0d1575e4d01746b (patch) | |
tree | b9eb21e6b2cb137a119d4d0b51a990c639a2154b | |
parent | 52e6ad2761e4e39c3e89fe3b8d68b98cf538a27c (diff) | |
download | dnsmasq-7500157cff8ea28ab03e6e62e0d1575e4d01746b.tar.gz |
Improve RFC3315 para 15 packet validation.
Thanks to Shashikumar Shashil for spotting the ommision.
-rw-r--r-- | src/rfc3315.c | 34 |
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) |