From a6dccae41b6068a9bee3ccb85cff0081c1e412d2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20H=C3=A4rdeman?= Date: Sun, 19 Oct 2025 09:47:37 +0200 Subject: [PATCH] odhcpd: struct lease -> struct lease_cfg MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Both the DHCPv4 and DHCPv6 RFCs use the term "lease" to refer to what in the odhcpd codebase is "struct assignment". Some examples: RFC2131, §2.2: In this document, the period over which a network address is allocated to a client is referred to as a "lease" [11]. The client may extend its lease with subsequent requests. The client may issue a message to release the address back to the server when the client no longer needs the address. The client may ask for a permanent assignment by asking for an infinite lease. Even when assigning "permanent" addresses, a server may choose to give out lengthy but non-infinite leases to allow detection of the fact that the client has been retired. RFC8415, §4.2: lease A contract by which the server grants the use of an address or delegated prefix to the client for a specified period of time. For example in §7.3: RENEW (5) A client sends a Renew message to the server that originally provided the client's leases and configuration parameters to extend the lifetimes on the leases assigned to the client and to update other configuration parameters. There's also a bit of confusion in the odhcpd codebase, where the two are sometimes used interchangeably, see e.g. handle_*_leases() in ubus.c which correspond to the ubus methods "ipv4leases" and "ipv6leases" but which then returns "assignments", or dhcpv4_lease() in dhcpv4.c, which returns an "assignment". There's more examples. To put it differently, "assignment" when used in the RFCs is essentially the verb, the server assigns, and "lease" is the noun - the server assigns a lease. So rename "struct lease" to "struct lease_cfg" to better describe what it is used for. I.e. it contains the cfg for a host which can provide the parameters for a static lease (and it comes from a "host" uci section) but it isn't a *lease* per se. This is a bit a of pet peeve of mine, but I found it quite confusing when I first started hacking on odhcpd. It also lays the foundation for later patches which rework/split/rename "struct assignment". Signed-off-by: David Härdeman Link: https://github.com/openwrt/odhcpd/pull/292 Signed-off-by: Álvaro Fernández Rojas --- src/config.c | 271 ++++++++++++++++++++++++------------------------ src/dhcpv4.c | 34 +++--- src/dhcpv6-ia.c | 42 ++++---- src/odhcpd.h | 47 +++++---- src/ubus.c | 10 +- 5 files changed, 204 insertions(+), 200 deletions(-) diff --git a/src/config.c b/src/config.c index a54c64c..1133578 100644 --- a/src/config.c +++ b/src/config.c @@ -26,11 +26,13 @@ static struct blob_buf b; static int reload_pipe[2] = { -1, -1 }; -static int lease_cmp(const void *k1, const void *k2, void *ptr); -static void lease_update(struct vlist_tree *tree, struct vlist_node *node_new, - struct vlist_node *node_old); +static int lease_cfg_cmp(const void *k1, const void *k2, void *ptr); +static void lease_cfg_update(struct vlist_tree *tree, struct vlist_node *node_new, + struct vlist_node *node_old); + +struct vlist_tree lease_cfgs = VLIST_TREE_INIT(lease_cfgs, lease_cfg_cmp, + lease_cfg_update, true, false); -struct vlist_tree leases = VLIST_TREE_INIT(leases, lease_cmp, lease_update, true, false); AVL_TREE(interfaces, avl_strcmp, false, NULL); struct config config = { .legacy = false, @@ -204,18 +206,18 @@ const struct uci_blob_param_list interface_attr_list = { .info = iface_attr_info, }; -const struct blobmsg_policy lease_attrs[LEASE_ATTR_MAX] = { - [LEASE_ATTR_IP] = { .name = "ip", .type = BLOBMSG_TYPE_STRING }, - [LEASE_ATTR_MAC] = { .name = "mac", .type = BLOBMSG_TYPE_ARRAY }, - [LEASE_ATTR_DUID] = { .name = "duid", .type = BLOBMSG_TYPE_ARRAY }, - [LEASE_ATTR_HOSTID] = { .name = "hostid", .type = BLOBMSG_TYPE_STRING }, - [LEASE_ATTR_LEASETIME] = { .name = "leasetime", .type = BLOBMSG_TYPE_STRING }, - [LEASE_ATTR_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING }, +const struct blobmsg_policy lease_cfg_attrs[LEASE_CFG_ATTR_MAX] = { + [LEASE_CFG_ATTR_IP] = { .name = "ip", .type = BLOBMSG_TYPE_STRING }, + [LEASE_CFG_ATTR_MAC] = { .name = "mac", .type = BLOBMSG_TYPE_ARRAY }, + [LEASE_CFG_ATTR_DUID] = { .name = "duid", .type = BLOBMSG_TYPE_ARRAY }, + [LEASE_CFG_ATTR_HOSTID] = { .name = "hostid", .type = BLOBMSG_TYPE_STRING }, + [LEASE_CFG_ATTR_LEASETIME] = { .name = "leasetime", .type = BLOBMSG_TYPE_STRING }, + [LEASE_CFG_ATTR_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING }, }; -const struct uci_blob_param_list lease_attr_list = { - .n_params = LEASE_ATTR_MAX, - .params = lease_attrs, +const struct uci_blob_param_list lease_cfg_attr_list = { + .n_params = LEASE_CFG_ATTR_MAX, + .params = lease_cfg_attrs, }; enum { @@ -569,13 +571,13 @@ err: return 0; } -static void free_lease(struct lease *l) +static void free_lease_cfg(struct lease_cfg *lease_cfg) { - if (!l) + if (!lease_cfg) return; - free(l->hostname); - free(l); + free(lease_cfg->hostname); + free(lease_cfg); } static bool parse_duid(struct duid *duid, struct blob_attr *c) @@ -623,104 +625,104 @@ static bool parse_duid(struct duid *duid, struct blob_attr *c) return true; } -int set_lease_from_blobmsg(struct blob_attr *ba) +int config_set_lease_cfg_from_blobmsg(struct blob_attr *ba) { - struct blob_attr *tb[LEASE_ATTR_MAX], *c; - struct lease *l = NULL; + struct blob_attr *tb[LEASE_CFG_ATTR_MAX], *c; + struct lease_cfg *lease_cfg = NULL; int mac_count = 0; struct ether_addr *macs; int duid_count = 0; struct duid *duids; - blobmsg_parse(lease_attrs, LEASE_ATTR_MAX, tb, blob_data(ba), blob_len(ba)); + blobmsg_parse(lease_cfg_attrs, LEASE_CFG_ATTR_MAX, tb, blob_data(ba), blob_len(ba)); - if ((c = tb[LEASE_ATTR_MAC])) { + if ((c = tb[LEASE_CFG_ATTR_MAC])) { mac_count = blobmsg_check_array_len(c, BLOBMSG_TYPE_STRING, blob_raw_len(c)); if (mac_count < 0) goto err; } - if ((c = tb[LEASE_ATTR_DUID])) { + if ((c = tb[LEASE_CFG_ATTR_DUID])) { duid_count = blobmsg_check_array_len(c, BLOBMSG_TYPE_STRING, blob_raw_len(c)); if (duid_count < 0) goto err; } - l = calloc_a(sizeof(*l), - &macs, mac_count * sizeof(*macs), - &duids, duid_count * sizeof(*duids)); - if (!l) + lease_cfg = calloc_a(sizeof(*lease_cfg), + &macs, mac_count * sizeof(*macs), + &duids, duid_count * sizeof(*duids)); + if (!lease_cfg) goto err; - if ((c = tb[LEASE_ATTR_MAC])) { + if ((c = tb[LEASE_CFG_ATTR_MAC])) { struct blob_attr *cur; size_t rem; int i = 0; - l->mac_count = mac_count; - l->macs = macs; + lease_cfg->mac_count = mac_count; + lease_cfg->macs = macs; blobmsg_for_each_attr(cur, c, rem) - if (!ether_aton_r(blobmsg_get_string(cur), &l->macs[i++])) + if (!ether_aton_r(blobmsg_get_string(cur), &lease_cfg->macs[i++])) goto err; } - if ((c = tb[LEASE_ATTR_DUID])) { + if ((c = tb[LEASE_CFG_ATTR_DUID])) { struct blob_attr *cur; size_t rem; unsigned i = 0; - l->duid_count = duid_count; - l->duids = duids; + lease_cfg->duid_count = duid_count; + lease_cfg->duids = duids; blobmsg_for_each_attr(cur, c, rem) if (!parse_duid(&duids[i++], cur)) goto err; } - if ((c = tb[LEASE_ATTR_NAME])) { - l->hostname = strdup(blobmsg_get_string(c)); - if (!l->hostname || !odhcpd_valid_hostname(l->hostname)) + if ((c = tb[LEASE_CFG_ATTR_NAME])) { + lease_cfg->hostname = strdup(blobmsg_get_string(c)); + if (!lease_cfg->hostname || !odhcpd_valid_hostname(lease_cfg->hostname)) goto err; } - if ((c = tb[LEASE_ATTR_IP])) - if (inet_pton(AF_INET, blobmsg_get_string(c), &l->ipaddr) < 0) + if ((c = tb[LEASE_CFG_ATTR_IP])) + if (inet_pton(AF_INET, blobmsg_get_string(c), &lease_cfg->ipaddr) < 0) goto err; - if ((c = tb[LEASE_ATTR_HOSTID])) { + if ((c = tb[LEASE_CFG_ATTR_HOSTID])) { errno = 0; - l->hostid = strtoull(blobmsg_get_string(c), NULL, 16); + lease_cfg->hostid = strtoull(blobmsg_get_string(c), NULL, 16); if (errno) goto err; } else { - uint32_t i4a = ntohl(l->ipaddr) & 0xff; - l->hostid = ((i4a / 100) << 8) | (((i4a % 100) / 10) << 4) | (i4a % 10); + uint32_t i4a = ntohl(lease_cfg->ipaddr) & 0xff; + lease_cfg->hostid = ((i4a / 100) << 8) | (((i4a % 100) / 10) << 4) | (i4a % 10); } - if ((c = tb[LEASE_ATTR_LEASETIME])) { + if ((c = tb[LEASE_CFG_ATTR_LEASETIME])) { uint32_t time = parse_leasetime(c); if (time == 0) goto err; - l->leasetime = time; + lease_cfg->leasetime = time; } - INIT_LIST_HEAD(&l->assignments); - vlist_add(&leases, &l->node, l); + INIT_LIST_HEAD(&lease_cfg->assignments); + vlist_add(&lease_cfgs, &lease_cfg->node, lease_cfg); return 0; err: - free_lease(l); + free_lease_cfg(lease_cfg); return -1; } -static int set_lease_from_uci(struct uci_section *s) +static int set_lease_cfg_from_uci(struct uci_section *s) { blob_buf_init(&b, 0); - uci_to_blob(&b, s, &lease_attr_list); + uci_to_blob(&b, s, &lease_cfg_attr_list); - return set_lease_from_blobmsg(b.head); + return config_set_lease_cfg_from_blobmsg(b.head); } /* Parse NTP Options for DHCPv6 Address */ @@ -1742,59 +1744,60 @@ static int set_interface(struct uci_section *s) return config_parse_interface(blob_data(b.head), blob_len(b.head), s->e.name, true); } -static void lease_delete_assignments(struct lease *l, bool v6) +static void lease_cfg_delete_assignments(struct lease_cfg *lease_cfg, bool v6) { struct dhcp_assignment *a, *tmp; unsigned int flag = v6 ? OAF_DHCPV6 : OAF_DHCPV4; - list_for_each_entry_safe(a, tmp, &l->assignments, lease_list) { + list_for_each_entry_safe(a, tmp, &lease_cfg->assignments, lease_cfg_list) { if (a->flags & flag) free_assignment(a); } } -static void lease_update_assignments(struct lease *l) +static void lease_cfg_update_assignments(struct lease_cfg *lease_cfg) { struct dhcp_assignment *a; - list_for_each_entry(a, &l->assignments, lease_list) { + list_for_each_entry(a, &lease_cfg->assignments, lease_cfg_list) { if (a->hostname) free(a->hostname); a->hostname = NULL; - if (l->hostname) - a->hostname = strdup(l->hostname); + if (lease_cfg->hostname) + a->hostname = strdup(lease_cfg->hostname); - a->leasetime = l->leasetime; + a->leasetime = lease_cfg->leasetime; } } -static int lease_cmp(const void *k1, const void *k2, _unused void *ptr) +static int lease_cfg_cmp(const void *k1, const void *k2, _unused void *ptr) { - const struct lease *l1 = k1, *l2 = k2; + const struct lease_cfg *lease_cfg1 = k1, *lease_cfg2 = k2; int cmp = 0; - if (l1->duid_count != l2->duid_count) - return l1->duid_count - l2->duid_count; + if (lease_cfg1->duid_count != lease_cfg2->duid_count) + return lease_cfg1->duid_count - lease_cfg2->duid_count; - for (size_t i = 0; i < l1->duid_count; i++) { - if (l1->duids[i].len != l2->duids[i].len) - return l1->duids[i].len - l2->duids[i].len; + for (size_t i = 0; i < lease_cfg1->duid_count; i++) { + if (lease_cfg1->duids[i].len != lease_cfg2->duids[i].len) + return lease_cfg1->duids[i].len - lease_cfg2->duids[i].len; - if (l1->duids[i].len && l2->duids[i].len) { - cmp = memcmp(l1->duids[i].id, l2->duids[i].id, l1->duids[i].len); + if (lease_cfg1->duids[i].len && lease_cfg2->duids[i].len) { + cmp = memcmp(lease_cfg1->duids[i].id, lease_cfg2->duids[i].id, + lease_cfg1->duids[i].len); if (cmp) return cmp; } } - if (l1->mac_count != l2->mac_count) - return l1->mac_count - l2->mac_count; + if (lease_cfg1->mac_count != lease_cfg2->mac_count) + return lease_cfg1->mac_count - lease_cfg2->mac_count; - for (size_t i = 0; i < l1->mac_count; i++) { - cmp = memcmp(l1->macs[i].ether_addr_octet, - l2->macs[i].ether_addr_octet, - sizeof(l1->macs[i].ether_addr_octet)); + for (size_t i = 0; i < lease_cfg1->mac_count; i++) { + cmp = memcmp(lease_cfg1->macs[i].ether_addr_octet, + lease_cfg2->macs[i].ether_addr_octet, + sizeof(lease_cfg1->macs[i].ether_addr_octet)); if (cmp) return cmp; } @@ -1802,129 +1805,129 @@ static int lease_cmp(const void *k1, const void *k2, _unused void *ptr) return 0; } -static void lease_change_config(struct lease *l_old, struct lease *l_new) +static void lease_cfg_change(struct lease_cfg *lease_cfg_old, struct lease_cfg *lease_cfg_new) { bool update = false; - if ((!!l_new->hostname != !!l_old->hostname) || - (l_new->hostname && strcmp(l_new->hostname, l_old->hostname))) { - free(l_old->hostname); - l_old->hostname = NULL; + if ((!!lease_cfg_new->hostname != !!lease_cfg_old->hostname) || + (lease_cfg_new->hostname && strcmp(lease_cfg_new->hostname, lease_cfg_old->hostname))) { + free(lease_cfg_old->hostname); + lease_cfg_old->hostname = NULL; - if (l_new->hostname) - l_old->hostname = strdup(l_new->hostname); + if (lease_cfg_new->hostname) + lease_cfg_old->hostname = strdup(lease_cfg_new->hostname); update = true; } - if (l_old->leasetime != l_new->leasetime) { - l_old->leasetime = l_new->leasetime; + if (lease_cfg_old->leasetime != lease_cfg_new->leasetime) { + lease_cfg_old->leasetime = lease_cfg_new->leasetime; update = true; } - if (l_old->ipaddr != l_new->ipaddr) { - l_old->ipaddr = l_new->ipaddr; - lease_delete_assignments(l_old, false); + if (lease_cfg_old->ipaddr != lease_cfg_new->ipaddr) { + lease_cfg_old->ipaddr = lease_cfg_new->ipaddr; + lease_cfg_delete_assignments(lease_cfg_old, false); } - if (l_old->hostid != l_new->hostid) { - l_old->hostid = l_new->hostid; - lease_delete_assignments(l_old, true); + if (lease_cfg_old->hostid != lease_cfg_new->hostid) { + lease_cfg_old->hostid = lease_cfg_new->hostid; + lease_cfg_delete_assignments(lease_cfg_old, true); } if (update) - lease_update_assignments(l_old); + lease_cfg_update_assignments(lease_cfg_old); - free_lease(l_new); + free_lease_cfg(lease_cfg_new); } -static void lease_delete(struct lease *l) +static void lease_cfg_delete(struct lease_cfg *lease_cfg) { struct dhcp_assignment *a, *tmp; - list_for_each_entry_safe(a, tmp, &l->assignments, lease_list) + list_for_each_entry_safe(a, tmp, &lease_cfg->assignments, lease_cfg_list) free_assignment(a); - free_lease(l); + free_lease_cfg(lease_cfg); } -static void lease_update(_unused struct vlist_tree *tree, struct vlist_node *node_new, - struct vlist_node *node_old) +static void lease_cfg_update(_unused struct vlist_tree *tree, struct vlist_node *node_new, + struct vlist_node *node_old) { - struct lease *lease_new = container_of(node_new, struct lease, node); - struct lease *lease_old = container_of(node_old, struct lease, node); + struct lease_cfg *lease_cfg_new = container_of(node_new, struct lease_cfg, node); + struct lease_cfg *lease_cfg_old = container_of(node_old, struct lease_cfg, node); if (node_old && node_new) - lease_change_config(lease_old, lease_new); + lease_cfg_change(lease_cfg_old, lease_cfg_new); else if (node_old) - lease_delete(lease_old); + lease_cfg_delete(lease_cfg_old); } /* * Either find: - * a) a lease with an exact DUID/IAID match; or - * b) a lease with a matching DUID and no IAID set + * a) a lease cfg with an exact DUID/IAID match; or + * b) a lease cfg 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_cfg * +config_find_lease_cfg_by_duid_and_iaid(const uint8_t *duid, const uint16_t len, const uint32_t iaid) { - struct lease *l, *candidate = NULL; + struct lease_cfg *lease_cfg, *candidate = NULL; - vlist_for_each_element(&leases, l, node) { - for (size_t i = 0; i < l->duid_count; i++) { - if (l->duids[i].len != len) + vlist_for_each_element(&lease_cfgs, lease_cfg, node) { + for (size_t i = 0; i < lease_cfg->duid_count; i++) { + if (lease_cfg->duids[i].len != len) continue; - if (memcmp(l->duids[i].id, duid, len)) + if (memcmp(lease_cfg->duids[i].id, duid, len)) continue; - if (!l->duids[i].iaid_set) { - candidate = l; + if (!lease_cfg->duids[i].iaid_set) { + candidate = lease_cfg; continue; } - if (l->duids[i].iaid == iaid) - return l; + if (lease_cfg->duids[i].iaid == iaid) + return lease_cfg; } } return candidate; } -struct lease *config_find_lease_by_mac(const uint8_t *mac) +struct lease_cfg *config_find_lease_cfg_by_mac(const uint8_t *mac) { - struct lease *l; + struct lease_cfg *lease_cfg; - vlist_for_each_element(&leases, l, node) { - for (size_t i = 0; i < l->mac_count; i++) { - if (!memcmp(l->macs[i].ether_addr_octet, mac, - sizeof(l->macs[i].ether_addr_octet))) - return l; + vlist_for_each_element(&lease_cfgs, lease_cfg, node) { + for (size_t i = 0; i < lease_cfg->mac_count; i++) { + if (!memcmp(lease_cfg->macs[i].ether_addr_octet, mac, + sizeof(lease_cfg->macs[i].ether_addr_octet))) + return lease_cfg; } } return NULL; } -struct lease *config_find_lease_by_hostid(const uint64_t hostid) +struct lease_cfg *config_find_lease_cfg_by_hostid(const uint64_t hostid) { - struct lease *l; + struct lease_cfg *lease_cfg; - vlist_for_each_element(&leases, l, node) { - if (l->hostid == hostid) - return l; + vlist_for_each_element(&lease_cfgs, lease_cfg, node) { + if (lease_cfg->hostid == hostid) + return lease_cfg; } return NULL; } -struct lease *config_find_lease_by_ipaddr(const uint32_t ipaddr) +struct lease_cfg *config_find_lease_cfg_by_ipaddr(const uint32_t ipaddr) { - struct lease *l; + struct lease_cfg *lease_cfg; - vlist_for_each_element(&leases, l, node) { - if (l->ipaddr == ipaddr) - return l; + vlist_for_each_element(&lease_cfgs, lease_cfg, node) { + if (lease_cfg->ipaddr == ipaddr) + return lease_cfg; } return NULL; @@ -2290,7 +2293,7 @@ void odhcpd_reload(void) sprintf(uci_network_path, "%s/network", config.uci_cfgdir); } - vlist_update(&leases); + vlist_update(&lease_cfgs); avl_for_each_element(&interfaces, i, avl) clean_interface(i); @@ -2325,11 +2328,11 @@ void odhcpd_reload(void) set_interface(s); } - /* 3. Static leases */ + /* 3. Static lease cfgs */ uci_foreach_element(&dhcp->sections, e) { struct uci_section* s = uci_to_section(e); if (!strcmp(s->type, "host")) - set_lease_from_uci(s); + set_lease_cfg_from_uci(s); } /* 4. IPv6 PxE */ @@ -2373,7 +2376,7 @@ void odhcpd_reload(void) error("Unable to open piofolder '%s': %m", path); } - vlist_flush(&leases); + vlist_flush(&lease_cfgs); ubus_apply_network(); diff --git a/src/dhcpv4.c b/src/dhcpv4.c index 56c3831..2b0e3a5 100644 --- a/src/dhcpv4.c +++ b/src/dhcpv4.c @@ -386,7 +386,7 @@ static bool dhcpv4_assign(struct interface *iface, struct dhcp_assignment *a, if (ntohl(raddr) < start || ntohl(raddr) > end) { debug("The requested IP address is outside the pool: %s", inet_ntop(AF_INET, &raddr, ipv4_str, sizeof(ipv4_str))); - } else if (config_find_lease_by_ipaddr(raddr)) { + } else if (config_find_lease_cfg_by_ipaddr(raddr)) { debug("The requested IP address is statically assigned: %s", inet_ntop(AF_INET, &raddr, ipv4_str, sizeof(ipv4_str))); } else if (!dhcpv4_insert_assignment(&iface->dhcpv4_assignments, a, raddr)) { @@ -413,7 +413,7 @@ static bool dhcpv4_assign(struct interface *iface, struct dhcp_assignment *a, ++i, try = (((try - start) + 1) % count) + start) { uint32_t n_try = htonl(try); - if (config_find_lease_by_ipaddr(n_try)) + if (config_find_lease_cfg_by_ipaddr(n_try)) continue; if (dhcpv4_insert_assignment(&iface->dhcpv4_assignments, a, n_try)) { @@ -447,7 +447,7 @@ dhcpv4_lease(struct interface *iface, enum dhcpv4_msg req_msg, const uint8_t *re uint32_t *fr_serverid) { struct dhcp_assignment *a = find_assignment_by_hwaddr(iface, req_mac); - struct lease *l = config_find_lease_by_mac(req_mac); + struct lease_cfg *lease_cfg = config_find_lease_cfg_by_mac(req_mac); time_t now = odhcpd_time(); /* @@ -455,16 +455,16 @@ dhcpv4_lease(struct interface *iface, enum dhcpv4_msg req_msg, const uint8_t *re * hwaddr, we need to clear out any old assignments given to other * hwaddrs in order to take over the IP address. */ - if (l && !a && (req_msg == DHCPV4_MSG_DISCOVER || req_msg == DHCPV4_MSG_REQUEST)) { + if (lease_cfg && !a && (req_msg == DHCPV4_MSG_DISCOVER || req_msg == DHCPV4_MSG_REQUEST)) { struct dhcp_assignment *c, *tmp; - list_for_each_entry_safe(c, tmp, &l->assignments, lease_list) { + list_for_each_entry_safe(c, tmp, &lease_cfg->assignments, lease_cfg_list) { if (c->flags & OAF_DHCPV4 && c->flags & OAF_STATIC) free_assignment(c); } } - if (l && a && a->lease != l) { + if (lease_cfg && a && a->lease_cfg != lease_cfg) { free_assignment(a); a = NULL; } @@ -492,7 +492,7 @@ dhcpv4_lease(struct interface *iface, enum dhcpv4_msg req_msg, const uint8_t *re a->flags &= ~OAF_BOUND; - if (!(a->flags & OAF_STATIC) || a->lease->ipaddr != a->addr) { + if (!(a->flags & OAF_STATIC) || a->lease_cfg->ipaddr != a->addr) { memset(a->hwaddr, 0, sizeof(a->hwaddr)); a->valid_until = now + 3600; /* Block address for 1h */ } else { @@ -504,7 +504,7 @@ dhcpv4_lease(struct interface *iface, enum dhcpv4_msg req_msg, const uint8_t *re _fallthrough; case DHCPV4_MSG_REQUEST: - if (!a && iface->no_dynamic_dhcp && !l) + if (!a && iface->no_dynamic_dhcp && !lease_cfg) return NULL; /* Old assignment, but with an address that is out-of-scope? */ @@ -535,29 +535,29 @@ dhcpv4_lease(struct interface *iface, enum dhcpv4_msg req_msg, const uint8_t *re a->flags = OAF_DHCPV4; /* static lease => infinite (0), else a placeholder */ - a->valid_until = l ? 0 : now; - a->addr = l ? l->ipaddr : INADDR_ANY; + a->valid_until = lease_cfg ? 0 : now; + a->addr = lease_cfg ? lease_cfg->ipaddr : INADDR_ANY; if (!dhcpv4_assign(iface, a, req_addr)) { free_assignment(a); return NULL; } - if (l) { + if (lease_cfg) { a->flags |= OAF_STATIC; - if (l->hostname) - a->hostname = strdup(l->hostname); + if (lease_cfg->hostname) + a->hostname = strdup(lease_cfg->hostname); - list_add(&a->lease_list, &l->assignments); - a->lease = l; + list_add(&a->lease_cfg_list, &lease_cfg->assignments); + a->lease_cfg = lease_cfg; } } /* See if we need to clamp the requested leasetime */ uint32_t max_leasetime; - if (a->lease && a->lease->leasetime) - max_leasetime = a->lease->leasetime; + if (a->lease_cfg && a->lease_cfg->leasetime) + max_leasetime = a->lease_cfg->leasetime; else max_leasetime = iface->dhcp_leasetime; diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index 3d9ac23..73798c5 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -936,7 +936,7 @@ static bool assign_na(struct interface *iface, struct dhcp_assignment *a) if (is_reserved_ipv6_iid(try)) continue; - if (config_find_lease_by_hostid(try)) + if (config_find_lease_cfg_by_hostid(try)) continue; list_for_each_entry(c, &iface->ia_assignments, head) { @@ -1486,11 +1486,11 @@ ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *ifac size_t ia_response_len = 0; uint8_t reqlen = (is_pd) ? 62 : 128; uint32_t reqhint = 0; - struct lease *l; + struct lease_cfg *lease_cfg; - l = config_find_lease_by_duid_and_iaid(clid_data, clid_len, ntohl(ia->iaid)); - if (!l) - l = config_find_lease_by_mac(mac); + lease_cfg = config_find_lease_cfg_by_duid_and_iaid(clid_data, clid_len, ntohl(ia->iaid)); + if (!lease_cfg) + lease_cfg = config_find_lease_cfg_by_mac(mac); /* Parse request hint for IA-PD */ if (is_pd) { @@ -1572,7 +1572,7 @@ ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *ifac continue; /* Does the existing assignment stem from the same static lease cfg? */ - if (c->lease != l) + if (c->lease_cfg != lease_cfg) continue; /* @@ -1583,14 +1583,14 @@ ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *ifac * on the same client. This is similar to how multiple MAC adresses * are handled for DHCPv4. */ - for (size_t i = 0; i < l->duid_count; i++) { - if (l->duids[i].iaid_set && l->duids[i].iaid != htonl(ia->iaid)) + for (size_t i = 0; i < lease_cfg->duid_count; i++) { + if (lease_cfg->duids[i].iaid_set && lease_cfg->duids[i].iaid != htonl(ia->iaid)) continue; - if (l->duids[i].len != clid_len) + if (lease_cfg->duids[i].len != clid_len) continue; - if (memcmp(l->duids[i].id, clid_data, clid_len)) + if (memcmp(lease_cfg->duids[i].id, clid_data, clid_len)) continue; /* @@ -1615,7 +1615,7 @@ ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *ifac break; } - if (l && a && a->lease != l) { + if (lease_cfg && a && a->lease_cfg != lease_cfg) { free_assignment(a); a = NULL; } @@ -1632,7 +1632,7 @@ proceed: bool assigned = !!a; if (!a) { - if ((!iface->no_dynamic_dhcp || (l && is_na)) && + if ((!iface->no_dynamic_dhcp || (lease_cfg && is_na)) && (iface->dhcpv6_pd || iface->dhcpv6_na)) { /* Create new binding */ a = alloc_assignment(clid_len); @@ -1644,7 +1644,7 @@ proceed: a->length = reqlen; a->peer = *addr; if (is_na) - a->assigned_host_id = l ? l->hostid : 0; + a->assigned_host_id = lease_cfg ? lease_cfg->hostid : 0; else a->assigned_subnet_id = reqhint; a->valid_until = now; @@ -1664,17 +1664,17 @@ proceed: else if (is_na && iface->dhcpv6_na) assigned = assign_na(iface, a); - if (l && assigned) { + if (lease_cfg && assigned) { a->flags |= OAF_STATIC; - if (l->hostname) - a->hostname = strdup(l->hostname); + if (lease_cfg->hostname) + a->hostname = strdup(lease_cfg->hostname); - if (l->leasetime) - a->leasetime = l->leasetime; + if (lease_cfg->leasetime) + a->leasetime = lease_cfg->leasetime; - list_add(&a->lease_list, &l->assignments); - a->lease = l; + list_add(&a->lease_cfg_list, &lease_cfg->assignments); + a->lease_cfg = lease_cfg; } if (a->managed_size && !assigned) @@ -1775,7 +1775,7 @@ proceed: } else if ((a->flags & OAF_DHCPV6_NA) && hdr->msg_type == DHCPV6_MSG_DECLINE) { a->flags &= ~OAF_BOUND; - if (!(a->flags & OAF_STATIC) || a->lease->hostid != a->assigned_host_id) { + if (!(a->flags & OAF_STATIC) || a->lease_cfg->hostid != a->assigned_host_id) { memset(a->clid_data, 0, a->clid_len); a->valid_until = now + 3600; /* Block address for 1h */ } else diff --git a/src/odhcpd.h b/src/odhcpd.h index 3659f08..3d5d707 100644 --- a/src/odhcpd.h +++ b/src/odhcpd.h @@ -71,7 +71,6 @@ struct interface; struct nl_sock; -extern struct vlist_tree leases; extern struct config config; extern struct sys_conf sys_conf; @@ -230,7 +229,8 @@ struct duid { bool iaid_set; }; -struct lease { +/* This corresponds to a UCI host section, i.e. a static lease cfg */ +struct lease_cfg { struct vlist_node node; struct list_head assignments; uint32_t ipaddr; @@ -243,26 +243,16 @@ struct lease { char *hostname; }; -enum { - LEASE_ATTR_IP, - LEASE_ATTR_MAC, - LEASE_ATTR_DUID, - LEASE_ATTR_HOSTID, - LEASE_ATTR_LEASETIME, - LEASE_ATTR_NAME, - LEASE_ATTR_MAX -}; - struct odhcpd_ref_ip; struct dhcp_assignment { struct list_head head; - struct list_head lease_list; + struct list_head lease_cfg_list; void (*dhcp_free_cb)(struct dhcp_assignment *a); struct interface *iface; - struct lease *lease; + struct lease_cfg *lease_cfg; struct sockaddr_in6 peer; time_t valid_until; @@ -469,12 +459,22 @@ struct interface { }; extern struct avl_tree interfaces; -extern const struct blobmsg_policy lease_attrs[LEASE_ATTR_MAX]; + +enum { + LEASE_CFG_ATTR_IP, + LEASE_CFG_ATTR_MAC, + LEASE_CFG_ATTR_DUID, + LEASE_CFG_ATTR_HOSTID, + LEASE_CFG_ATTR_LEASETIME, + LEASE_CFG_ATTR_NAME, + LEASE_CFG_ATTR_MAX +}; +extern const struct blobmsg_policy lease_cfg_attrs[LEASE_CFG_ATTR_MAX]; inline static void free_assignment(struct dhcp_assignment *a) { list_del(&a->head); - list_del(&a->lease_list); + list_del(&a->lease_cfg_list); if (a->dhcp_free_cb) a->dhcp_free_cb(a); @@ -491,7 +491,7 @@ inline static struct dhcp_assignment *alloc_assignment(size_t extra_len) return NULL; INIT_LIST_HEAD(&a->head); - INIT_LIST_HEAD(&a->lease_list); + INIT_LIST_HEAD(&a->lease_cfg_list); return a; } @@ -553,14 +553,15 @@ bool odhcpd_bitlen2netmask(bool v6, unsigned int bits, void *mask); 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_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); +struct lease_cfg *config_find_lease_cfg_by_duid_and_iaid(const uint8_t *duid, + const uint16_t len, + const uint32_t iaid); +struct lease_cfg *config_find_lease_cfg_by_mac(const uint8_t *mac); +struct lease_cfg *config_find_lease_cfg_by_hostid(const uint64_t hostid); +struct lease_cfg *config_find_lease_cfg_by_ipaddr(const uint32_t ipaddr); +int config_set_lease_cfg_from_blobmsg(struct blob_attr *ba); void config_load_ra_pio(struct interface *iface); void config_save_ra_pio(struct interface *iface); -int set_lease_from_blobmsg(struct blob_attr *ba); #ifdef WITH_UBUS int ubus_init(void); diff --git a/src/ubus.c b/src/ubus.c index 1a16726..9cb94a5 100644 --- a/src/ubus.c +++ b/src/ubus.c @@ -225,11 +225,11 @@ static int handle_ra_pio(_unused struct ubus_context *ctx, _unused struct ubus_o return 0; } -static int handle_add_lease(_unused struct ubus_context *ctx, _unused struct ubus_object *obj, - _unused struct ubus_request_data *req, _unused const char *method, - struct blob_attr *msg) +static int handle_add_lease_cfg(_unused struct ubus_context *ctx, _unused struct ubus_object *obj, + _unused struct ubus_request_data *req, _unused const char *method, + struct blob_attr *msg) { - if (!set_lease_from_blobmsg(msg)) + if (!config_set_lease_cfg_from_blobmsg(msg)) return UBUS_STATUS_OK; return UBUS_STATUS_INVALID_ARGUMENT; @@ -241,7 +241,7 @@ static struct ubus_method main_object_methods[] = { #endif /* DHCPV4_SUPPORT */ { .name = "ipv6leases", .handler = handle_dhcpv6_leases }, { .name = "ipv6ra", .handler = handle_ra_pio }, - UBUS_METHOD("add_lease", handle_add_lease, lease_attrs), + UBUS_METHOD("add_lease", handle_add_lease_cfg, lease_cfg_attrs), }; static struct ubus_object_type main_object_type = -- 2.30.2