The patch implements handling of advertise messages
as described in RFC3315 paragraph 17.1.2. Client will
stop collecting advertise messages if preference option
is equal to 255 or if the first RT has elapsed. Status
codes are handled in the advertise message depending on
the startup parameters
Signed-off-by: Hans Dedecker <hans.dedecker@gmail.com>
// Collect all advertised servers
// Collect all advertised servers
-static int dhcpv6_handle_advert(enum dhcpv6_msg orig, _unused const int rc,
+static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc,
const void *opt, const void *end)
{
uint16_t olen, otype;
const void *opt, const void *end)
{
uint16_t olen, otype;
+ uint8_t *odata, pref = 0;
struct dhcpv6_server_cand cand = {false, false, 0, 0, {0}, NULL, NULL, 0, 0};
bool have_na = false;
int have_pd = 0;
struct dhcpv6_server_cand cand = {false, false, 0, 0, {0}, NULL, NULL, 0, 0};
bool have_na = false;
int have_pd = 0;
if (otype == DHCPV6_OPT_SERVERID && olen <= 130) {
memcpy(cand.duid, odata, olen);
cand.duid_len = olen;
if (otype == DHCPV6_OPT_SERVERID && olen <= 130) {
memcpy(cand.duid, odata, olen);
cand.duid_len = olen;
- } else if (otype == DHCPV6_OPT_STATUS && olen >= 2 && !odata[0]
- && odata[1] == DHCPV6_NoPrefixAvail) {
- cand.preference -= 2000;
+ } else if (otype == DHCPV6_OPT_STATUS && olen >= 2) {
+ int error = ((int)odata[0] << 8 | (int)odata[1]);
+
+ switch (error) {
+ case DHCPV6_NoPrefixAvail:
+ // Status code on global level
+ if (pd_mode == IA_MODE_FORCE)
+ return -1;
+ cand.preference -= 2000;
+ break;
+
+ case DHCPV6_NoAddrsAvail:
+ // Status code on global level
+ if (na_mode == IA_MODE_FORCE)
+ return -1;
+ break;
+
+ default :
+ break;
+ }
} else if (otype == DHCPV6_OPT_PREF && olen >= 1 &&
cand.preference >= 0) {
} else if (otype == DHCPV6_OPT_PREF && olen >= 1 &&
cand.preference >= 0) {
- cand.preference = odata[0];
+ cand.preference = pref = odata[0];
} else if (otype == DHCPV6_OPT_RECONF_ACCEPT) {
cand.wants_reconfigure = true;
} else if (otype == DHCPV6_OPT_IA_PD && request_prefix) {
} else if (otype == DHCPV6_OPT_RECONF_ACCEPT) {
cand.wants_reconfigure = true;
} else if (otype == DHCPV6_OPT_IA_PD && request_prefix) {
odhcp6c_clear_state(STATE_IA_PD);
}
odhcp6c_clear_state(STATE_IA_PD);
}
+ return (rc > 1 || (pref == 255 && cand.preference > 0)) ? 1 : -1;
odhcp6c_add_state(STATE_SERVER_ID, hdr, sizeof(hdr));
odhcp6c_add_state(STATE_SERVER_ID, c->duid, c->duid_len);
accept_reconfig = c->wants_reconfigure;
odhcp6c_add_state(STATE_SERVER_ID, hdr, sizeof(hdr));
odhcp6c_add_state(STATE_SERVER_ID, c->duid, c->duid_len);
accept_reconfig = c->wants_reconfigure;
- odhcp6c_add_state(STATE_IA_NA, c->ia_na, c->ia_na_len);
- odhcp6c_add_state(STATE_IA_PD, c->ia_pd, c->ia_pd_len);
+ if (c->ia_na_len)
+ odhcp6c_add_state(STATE_IA_NA, c->ia_na, c->ia_na_len);
+ if (c->ia_pd_len)
+ odhcp6c_add_state(STATE_IA_PD, c->ia_pd, c->ia_pd_len);
}
for (size_t i = 0; i < cand_len / sizeof(*c); ++i) {
}
for (size_t i = 0; i < cand_len / sizeof(*c); ++i) {
- else if (request_prefix || na_mode != IA_MODE_NONE)
+ else if ((request_prefix && c->ia_pd_len) || (na_mode != IA_MODE_NONE && c->ia_na_len))
return DHCPV6_STATEFUL;
else
return DHCPV6_STATELESS;
return DHCPV6_STATEFUL;
else
return DHCPV6_STATELESS;