lease_delete(lease_old);
}
-struct lease *config_find_lease_by_duid(const uint8_t *duid, const uint16_t len)
+/*
+ * Either find:
+ * a) a lease with an exact DUID/IAID match; or
+ * b) a lease with a matching DUID and no IAID set
+ */
+struct lease *config_find_lease_by_duid_and_iaid(const uint8_t *duid, const uint16_t len,
+ const uint32_t iaid)
{
- struct lease *l;
+ struct lease *l, *candidate = NULL;
vlist_for_each_element(&leases, l, node) {
- if (l->duid_len == len && !memcmp(l->duid, duid, len))
+ if (l->duid_len != len || memcmp(l->duid, duid, len))
+ continue;
+
+ if (!l->iaid_set) {
+ candidate = l;
+ continue;
+ }
+
+ if (l->iaid == iaid)
return l;
}
- return NULL;
+ return candidate;
}
struct lease *config_find_lease_by_mac(const uint8_t *mac)
if (!(ctxt.c->flags & OAF_BOUND) || ctxt.c->managed_size < 0)
continue;
- char duidbuf[264];
+ char duidbuf[DUID_HEXSTRLEN];
odhcpd_hexlify(duidbuf, ctxt.c->clid_data, ctxt.c->clid_len);
ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *iface,
const struct sockaddr_in6 *addr, const void *data, const uint8_t *end)
{
- struct lease *l;
struct dhcp_assignment *first = NULL;
const struct dhcpv6_client_header *hdr = data;
time_t now = odhcpd_time();
uint8_t *clid_data = NULL, mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
size_t hostname_len = 0, response_len = 0;
bool notonlink = false, rapid_commit = false, accept_reconf = false;
- char duidbuf[261], hostname[256];
+ char duidbuf[DUID_HEXSTRLEN], hostname[256];
dhcpv6_for_each_option(start, end, otype, olen, odata) {
if (otype == DHCPV6_OPT_CLIENTID) {
else if (olen == 10 && odata[0] == 0 && odata[1] == 3)
memcpy(mac, &odata[4], sizeof(mac));
- if (olen <= 130)
+ if (olen <= DUID_MAX_LEN)
odhcpd_hexlify(duidbuf, odata, olen);
} else if (otype == DHCPV6_OPT_FQDN && olen >= 2 && olen <= 255) {
uint8_t fqdn_buf[256];
rapid_commit = true;
}
- if (!clid_data || !clid_len || clid_len > 130)
+ if (!clid_data || !clid_len || clid_len > DUID_MAX_LEN)
goto out;
- l = config_find_lease_by_duid(clid_data, clid_len);
- if (!l)
- l = config_find_lease_by_mac(mac);
-
dhcpv6_for_each_option(start, end, otype, olen, odata) {
bool is_pd = (otype == DHCPV6_OPT_IA_PD);
bool is_na = (otype == DHCPV6_OPT_IA_NA);
size_t ia_response_len = 0;
uint8_t reqlen = (is_pd) ? 62 : 128;
uint32_t reqhint = 0;
+ struct lease *l;
+
+ l = config_find_lease_by_duid_and_iaid(clid_data, clid_len, ntohl(ia->iaid));
+ if (!l)
+ l = config_find_lease_by_mac(mac);
/* Parse request hint for IA-PD */
if (is_pd) {
/* 2-byte type + 128-byte DUID, RFC8415, §11.1 */
#define DUID_MAX_LEN 130
+#define DUID_HEXSTRLEN (DUID_MAX_LEN * 2 + 1)
struct lease {
struct vlist_node node;
bool odhcpd_valid_hostname(const char *name);
int config_parse_interface(void *data, size_t len, const char *iname, bool overwrite);
-struct lease *config_find_lease_by_duid(const uint8_t *duid, const uint16_t len);
+struct lease *config_find_lease_by_duid_and_iaid(const uint8_t *duid, const uint16_t len,
+ const uint32_t iaid);
struct lease *config_find_lease_by_mac(const uint8_t *mac);
struct lease *config_find_lease_by_hostid(const uint64_t hostid);
struct lease *config_find_lease_by_ipaddr(const uint32_t ipaddr);