+ 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 (l_new->hostname)
+ l_old->hostname = strdup(l_new->hostname);
+
+ update = true;
+ }
+
+ if (l_old->leasetime != l_new->leasetime) {
+ l_old->leasetime = l_new->leasetime;
+ update = true;
+ }
+
+ if (l_old->ipaddr != l_new->ipaddr) {
+ l_old->ipaddr = l_new->ipaddr;
+ lease_delete_assignments(l_old, false);
+ }
+
+ if (l_old->hostid != l_new->hostid) {
+ l_old->hostid = l_new->hostid;
+ lease_delete_assignments(l_old, true);
+ }
+
+ if (update)
+ lease_update_assignments(l_old);
+
+ free_lease(l_new);
+}
+
+static void lease_delete(struct lease *l)
+{
+ struct dhcp_assignment *a, *tmp;
+
+ list_for_each_entry_safe(a, tmp, &l->assignments, lease_list)
+ free_assignment(a);
+
+ free_lease(l);
+}
+
+static void lease_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);
+
+ if (node_old && node_new)
+ lease_change_config(lease_old, lease_new);
+ else if (node_old)
+ lease_delete(lease_old);
+}
+
+struct lease *config_find_lease_by_duid(const uint8_t *duid, const uint16_t len)
+{
+ struct lease *l;
+
+ vlist_for_each_element(&leases, l, node) {
+ if (l->duid_len == len && !memcmp(l->duid, duid, len))
+ return l;
+ }
+
+ return NULL;
+}
+
+struct lease *config_find_lease_by_mac(const uint8_t *mac)
+{
+ struct lease *l;
+
+ vlist_for_each_element(&leases, l, node) {
+ if (!memcmp(l->mac.ether_addr_octet, mac,
+ sizeof(l->mac.ether_addr_octet)))
+ return l;
+ }
+
+ return NULL;
+}
+
+struct lease *config_find_lease_by_hostid(const uint32_t hostid)
+{
+ struct lease *l;
+
+ vlist_for_each_element(&leases, l, node) {
+ if (l->hostid == hostid)
+ return l;
+ }
+
+ return NULL;
+}
+
+struct lease *config_find_lease_by_ipaddr(const uint32_t ipaddr)
+{
+ struct lease *l;
+
+ vlist_for_each_element(&leases, l, node) {
+ if (l->ipaddr == ipaddr)
+ return l;
+ }
+
+ return NULL;
+}
+
+void odhcpd_reload(void)
+{
+ struct uci_context *uci = uci_alloc_context();
+ struct interface *master = NULL, *i, *tmp;