• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/odhcpd/src/config.c

  1 #include <fcntl.h>
  2 #include <resolv.h>
  3 #include <signal.h>
  4 #include <arpa/inet.h>
  5 #include <unistd.h>
  6 #include <libgen.h>
  7 #include <net/if.h>
  8 #include <string.h>
  9 #include <sys/stat.h>
 10 #include <syslog.h>
 11 
 12 #include <uci.h>
 13 #include <uci_blob.h>
 14 #include <libubox/utils.h>
 15 #include <libubox/avl.h>
 16 #include <libubox/avl-cmp.h>
 17 #include <libubox/list.h>
 18 #include <libubox/vlist.h>
 19 
 20 #include "odhcpd.h"
 21 #include "dhcpv6-pxe.h"
 22 
 23 static struct blob_buf b;
 24 static int reload_pipe[2] = { -1, -1 };
 25 
 26 static int lease_cmp(const void *k1, const void *k2, void *ptr);
 27 static void lease_update(struct vlist_tree *tree, struct vlist_node *node_new,
 28                          struct vlist_node *node_old);
 29 
 30 struct vlist_tree leases = VLIST_TREE_INIT(leases, lease_cmp, lease_update, true, false);
 31 AVL_TREE(interfaces, avl_strcmp, false, NULL);
 32 struct config config = {.legacy = false, .main_dhcpv4 = false,
 33                         .dhcp_cb = NULL, .dhcp_statefile = NULL, .dhcp_hostsfile = NULL,
 34                         .log_level = LOG_WARNING};
 35 
 36 #define START_DEFAULT   100
 37 #define LIMIT_DEFAULT   150
 38 
 39 #define HOSTID_LEN_MIN  12
 40 #define HOSTID_LEN_MAX  64
 41 #define HOSTID_LEN_DEFAULT HOSTID_LEN_MIN
 42 
 43 #define PD_MIN_LEN_MAX (64-2) // must delegate at least 2 bits of prefix
 44 
 45 #define OAF_DHCPV6      (OAF_DHCPV6_NA | OAF_DHCPV6_PD)
 46 
 47 enum {
 48         IPV6_PXE_URL,
 49         IPV6_PXE_ARCH,
 50         IPV6_PXE_MAX
 51 };
 52 
 53 static const struct blobmsg_policy ipv6_pxe_attrs[IPV6_PXE_MAX] = {
 54         [IPV6_PXE_URL] = {.name = "url", .type = BLOBMSG_TYPE_STRING },
 55         [IPV6_PXE_ARCH] = {.name = "arch", .type = BLOBMSG_TYPE_INT32 },
 56 };
 57 
 58 const struct uci_blob_param_list ipv6_pxe_attr_list = {
 59         .n_params = IPV6_PXE_MAX,
 60         .params = ipv6_pxe_attrs,
 61 };
 62 
 63 enum {
 64         IFACE_ATTR_INTERFACE,
 65         IFACE_ATTR_IFNAME,
 66         IFACE_ATTR_NETWORKID,
 67         IFACE_ATTR_DYNAMICDHCP,
 68         IFACE_ATTR_LEASETIME,
 69         IFACE_ATTR_LIMIT,
 70         IFACE_ATTR_START,
 71         IFACE_ATTR_MASTER,
 72         IFACE_ATTR_UPSTREAM,
 73         IFACE_ATTR_RA,
 74         IFACE_ATTR_DHCPV4,
 75         IFACE_ATTR_DHCPV6,
 76         IFACE_ATTR_NDP,
 77         IFACE_ATTR_ROUTER,
 78         IFACE_ATTR_DNS,
 79         IFACE_ATTR_DNR,
 80         IFACE_ATTR_DNS_SERVICE,
 81         IFACE_ATTR_DOMAIN,
 82         IFACE_ATTR_FILTER_CLASS,
 83         IFACE_ATTR_DHCPV4_FORCERECONF,
 84         IFACE_ATTR_DHCPV6_RAW,
 85         IFACE_ATTR_DHCPV6_ASSIGNALL,
 86         IFACE_ATTR_DHCPV6_PD,
 87         IFACE_ATTR_DHCPV6_PD_MIN_LEN,
 88         IFACE_ATTR_DHCPV6_NA,
 89         IFACE_ATTR_DHCPV6_HOSTID_LEN,
 90         IFACE_ATTR_RA_DEFAULT,
 91         IFACE_ATTR_RA_MANAGEMENT,
 92         IFACE_ATTR_RA_FLAGS,
 93         IFACE_ATTR_RA_SLAAC,
 94         IFACE_ATTR_RA_OFFLINK,
 95         IFACE_ATTR_RA_PREFERENCE,
 96         IFACE_ATTR_RA_ADVROUTER,
 97         IFACE_ATTR_RA_MININTERVAL,
 98         IFACE_ATTR_RA_MAXINTERVAL,
 99         IFACE_ATTR_RA_LIFETIME,
100         IFACE_ATTR_RA_REACHABLETIME,
101         IFACE_ATTR_RA_RETRANSTIME,
102         IFACE_ATTR_RA_HOPLIMIT,
103         IFACE_ATTR_RA_MTU,
104         IFACE_ATTR_RA_DNS,
105         IFACE_ATTR_RA_PREF64,
106         IFACE_ATTR_PD_MANAGER,
107         IFACE_ATTR_PD_CER,
108         IFACE_ATTR_NDPROXY_ROUTING,
109         IFACE_ATTR_NDPROXY_SLAVE,
110         IFACE_ATTR_PREFIX_FILTER,
111         IFACE_ATTR_MAX_PREFERRED_LIFETIME,
112         IFACE_ATTR_MAX_VALID_LIFETIME,
113         IFACE_ATTR_NTP,
114         IFACE_ATTR_MAX
115 };
116 
117 static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
118         [IFACE_ATTR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
119         [IFACE_ATTR_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
120         [IFACE_ATTR_NETWORKID] = { .name = "networkid", .type = BLOBMSG_TYPE_STRING },
121         [IFACE_ATTR_DYNAMICDHCP] = { .name = "dynamicdhcp", .type = BLOBMSG_TYPE_BOOL },
122         [IFACE_ATTR_LEASETIME] = { .name = "leasetime", .type = BLOBMSG_TYPE_STRING },
123         [IFACE_ATTR_START] = { .name = "start", .type = BLOBMSG_TYPE_INT32 },
124         [IFACE_ATTR_LIMIT] = { .name = "limit", .type = BLOBMSG_TYPE_INT32 },
125         [IFACE_ATTR_MASTER] = { .name = "master", .type = BLOBMSG_TYPE_BOOL },
126         [IFACE_ATTR_UPSTREAM] = { .name = "upstream", .type = BLOBMSG_TYPE_ARRAY },
127         [IFACE_ATTR_RA] = { .name = "ra", .type = BLOBMSG_TYPE_STRING },
128         [IFACE_ATTR_DHCPV4] = { .name = "dhcpv4", .type = BLOBMSG_TYPE_STRING },
129         [IFACE_ATTR_DHCPV6] = { .name = "dhcpv6", .type = BLOBMSG_TYPE_STRING },
130         [IFACE_ATTR_NDP] = { .name = "ndp", .type = BLOBMSG_TYPE_STRING },
131         [IFACE_ATTR_ROUTER] = { .name = "router", .type = BLOBMSG_TYPE_ARRAY },
132         [IFACE_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY },
133         [IFACE_ATTR_DNR] = { .name = "dnr", .type = BLOBMSG_TYPE_ARRAY },
134         [IFACE_ATTR_DNS_SERVICE] = { .name = "dns_service", .type = BLOBMSG_TYPE_BOOL },
135         [IFACE_ATTR_DOMAIN] = { .name = "domain", .type = BLOBMSG_TYPE_ARRAY },
136         [IFACE_ATTR_FILTER_CLASS] = { .name = "filter_class", .type = BLOBMSG_TYPE_STRING },
137         [IFACE_ATTR_DHCPV4_FORCERECONF] = { .name = "dhcpv4_forcereconf", .type = BLOBMSG_TYPE_BOOL },
138         [IFACE_ATTR_DHCPV6_RAW] = { .name = "dhcpv6_raw", .type = BLOBMSG_TYPE_STRING },
139         [IFACE_ATTR_DHCPV6_ASSIGNALL] = { .name ="dhcpv6_assignall", .type = BLOBMSG_TYPE_BOOL },
140         [IFACE_ATTR_DHCPV6_PD] = { .name = "dhcpv6_pd", .type = BLOBMSG_TYPE_BOOL },
141         [IFACE_ATTR_DHCPV6_PD_MIN_LEN] = { .name = "dhcpv6_pd_min_len", .type = BLOBMSG_TYPE_INT32 },
142         [IFACE_ATTR_DHCPV6_NA] = { .name = "dhcpv6_na", .type = BLOBMSG_TYPE_BOOL },
143         [IFACE_ATTR_DHCPV6_HOSTID_LEN] = { .name = "dhcpv6_hostidlength", .type = BLOBMSG_TYPE_INT32 },
144         [IFACE_ATTR_PD_MANAGER] = { .name = "pd_manager", .type = BLOBMSG_TYPE_STRING },
145         [IFACE_ATTR_PD_CER] = { .name = "pd_cer", .type = BLOBMSG_TYPE_STRING },
146         [IFACE_ATTR_RA_DEFAULT] = { .name = "ra_default", .type = BLOBMSG_TYPE_INT32 },
147         [IFACE_ATTR_RA_MANAGEMENT] = { .name = "ra_management", .type = BLOBMSG_TYPE_INT32 },
148         [IFACE_ATTR_RA_FLAGS] = { .name = "ra_flags", . type = BLOBMSG_TYPE_ARRAY },
149         [IFACE_ATTR_RA_SLAAC] = { .name = "ra_slaac", .type = BLOBMSG_TYPE_BOOL },
150         [IFACE_ATTR_RA_OFFLINK] = { .name = "ra_offlink", .type = BLOBMSG_TYPE_BOOL },
151         [IFACE_ATTR_RA_PREFERENCE] = { .name = "ra_preference", .type = BLOBMSG_TYPE_STRING },
152         [IFACE_ATTR_RA_ADVROUTER] = { .name = "ra_advrouter", .type = BLOBMSG_TYPE_BOOL },
153         [IFACE_ATTR_RA_MININTERVAL] = { .name = "ra_mininterval", .type = BLOBMSG_TYPE_INT32 },
154         [IFACE_ATTR_RA_MAXINTERVAL] = { .name = "ra_maxinterval", .type = BLOBMSG_TYPE_INT32 },
155         [IFACE_ATTR_RA_LIFETIME] = { .name = "ra_lifetime", .type = BLOBMSG_TYPE_INT32 },
156         [IFACE_ATTR_RA_REACHABLETIME] = { .name = "ra_reachabletime", .type = BLOBMSG_TYPE_INT32 },
157         [IFACE_ATTR_RA_RETRANSTIME] = { .name = "ra_retranstime", .type = BLOBMSG_TYPE_INT32 },
158         [IFACE_ATTR_RA_HOPLIMIT] = { .name = "ra_hoplimit", .type = BLOBMSG_TYPE_INT32 },
159         [IFACE_ATTR_RA_MTU] = { .name = "ra_mtu", .type = BLOBMSG_TYPE_INT32 },
160         [IFACE_ATTR_RA_DNS] = { .name = "ra_dns", .type = BLOBMSG_TYPE_BOOL },
161         [IFACE_ATTR_RA_PREF64] = { .name = "ra_pref64", .type = BLOBMSG_TYPE_STRING },
162         [IFACE_ATTR_NDPROXY_ROUTING] = { .name = "ndproxy_routing", .type = BLOBMSG_TYPE_BOOL },
163         [IFACE_ATTR_NDPROXY_SLAVE] = { .name = "ndproxy_slave", .type = BLOBMSG_TYPE_BOOL },
164         [IFACE_ATTR_PREFIX_FILTER] = { .name = "prefix_filter", .type = BLOBMSG_TYPE_STRING },
165         [IFACE_ATTR_MAX_PREFERRED_LIFETIME] = { .name = "max_preferred_lifetime", .type = BLOBMSG_TYPE_STRING },
166         [IFACE_ATTR_MAX_VALID_LIFETIME] = { .name = "max_valid_lifetime", .type = BLOBMSG_TYPE_STRING },
167         [IFACE_ATTR_NTP] = { .name = "ntp", .type = BLOBMSG_TYPE_ARRAY },
168 };
169 
170 static const struct uci_blob_param_info iface_attr_info[IFACE_ATTR_MAX] = {
171         [IFACE_ATTR_UPSTREAM] = { .type = BLOBMSG_TYPE_STRING },
172         [IFACE_ATTR_DNS] = { .type = BLOBMSG_TYPE_STRING },
173         [IFACE_ATTR_DOMAIN] = { .type = BLOBMSG_TYPE_STRING },
174 };
175 
176 const struct uci_blob_param_list interface_attr_list = {
177         .n_params = IFACE_ATTR_MAX,
178         .params = iface_attrs,
179         .info = iface_attr_info,
180 };
181 
182 const struct blobmsg_policy lease_attrs[LEASE_ATTR_MAX] = {
183         [LEASE_ATTR_IP] = { .name = "ip", .type = BLOBMSG_TYPE_STRING },
184         [LEASE_ATTR_MAC] = { .name = "mac", .type = BLOBMSG_TYPE_ARRAY },
185         [LEASE_ATTR_DUID] = { .name = "duid", .type = BLOBMSG_TYPE_STRING },
186         [LEASE_ATTR_HOSTID] = { .name = "hostid", .type = BLOBMSG_TYPE_STRING },
187         [LEASE_ATTR_LEASETIME] = { .name = "leasetime", .type = BLOBMSG_TYPE_STRING },
188         [LEASE_ATTR_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
189 };
190 
191 const struct uci_blob_param_list lease_attr_list = {
192         .n_params = LEASE_ATTR_MAX,
193         .params = lease_attrs,
194 };
195 
196 enum {
197         ODHCPD_ATTR_LEGACY,
198         ODHCPD_ATTR_MAINDHCP,
199         ODHCPD_ATTR_LEASEFILE,
200         ODHCPD_ATTR_LEASETRIGGER,
201         ODHCPD_ATTR_LOGLEVEL,
202         ODHCPD_ATTR_HOSTSFILE,
203         ODHCPD_ATTR_MAX
204 };
205 
206 static const struct blobmsg_policy odhcpd_attrs[ODHCPD_ATTR_MAX] = {
207         [ODHCPD_ATTR_LEGACY] = { .name = "legacy", .type = BLOBMSG_TYPE_BOOL },
208         [ODHCPD_ATTR_MAINDHCP] = { .name = "maindhcp", .type = BLOBMSG_TYPE_BOOL },
209         [ODHCPD_ATTR_LEASEFILE] = { .name = "leasefile", .type = BLOBMSG_TYPE_STRING },
210         [ODHCPD_ATTR_LEASETRIGGER] = { .name = "leasetrigger", .type = BLOBMSG_TYPE_STRING },
211         [ODHCPD_ATTR_LOGLEVEL] = { .name = "loglevel", .type = BLOBMSG_TYPE_INT32 },
212         [ODHCPD_ATTR_HOSTSFILE] = { .name = "hostsfile", .type = BLOBMSG_TYPE_STRING },
213 };
214 
215 const struct uci_blob_param_list odhcpd_attr_list = {
216         .n_params = ODHCPD_ATTR_MAX,
217         .params = odhcpd_attrs,
218 };
219 
220 static const struct { const char *name; uint8_t flag; } ra_flags[] = {
221         { .name = "managed-config", .flag = ND_RA_FLAG_MANAGED },
222         { .name = "other-config", .flag = ND_RA_FLAG_OTHER },
223         { .name = "home-agent", .flag = ND_RA_FLAG_HOME_AGENT },
224         { .name = "none", . flag = 0 },
225         { .name = NULL, },
226 };
227 
228 // https://www.iana.org/assignments/dns-svcb/dns-svcb.xhtml
229 enum svc_param_keys {
230         DNR_SVC_MANDATORY,
231         DNR_SVC_ALPN,
232         DNR_SVC_NO_DEFAULT_ALPN,
233         DNR_SVC_PORT,
234         DNR_SVC_IPV4HINT,
235         DNR_SVC_ECH,
236         DNR_SVC_IPV6HINT,
237         DNR_SVC_DOHPATH,
238         DNR_SVC_OHTTP,
239         DNR_SVC_MAX,
240 };
241 
242 static const char *svc_param_key_names[DNR_SVC_MAX] = {
243         [DNR_SVC_MANDATORY] = "mandatory",
244         [DNR_SVC_ALPN] = "alpn",
245         [DNR_SVC_NO_DEFAULT_ALPN] = "no-default-alpn",
246         [DNR_SVC_PORT] = "port",
247         [DNR_SVC_IPV4HINT] = "ipv4hint",
248         [DNR_SVC_ECH] = "ech",
249         [DNR_SVC_IPV6HINT] = "ipv6hint",
250         [DNR_SVC_DOHPATH] = "dohpath",
251         [DNR_SVC_OHTTP] = "ohttp",
252 };
253 
254 static void set_interface_defaults(struct interface *iface)
255 {
256         iface->ignore = true;
257         iface->dhcpv4 = MODE_DISABLED;
258         iface->dhcpv6 = MODE_DISABLED;
259         iface->ra = MODE_DISABLED;
260         iface->ndp = MODE_DISABLED;
261         iface->learn_routes = 1;
262         iface->dhcp_leasetime = 43200;
263         iface->max_preferred_lifetime = ND_PREFERRED_LIMIT;
264         iface->max_valid_lifetime = ND_VALID_LIMIT;
265         iface->dhcpv4_start.s_addr = htonl(START_DEFAULT);
266         iface->dhcpv4_end.s_addr = htonl(START_DEFAULT + LIMIT_DEFAULT - 1);
267         iface->dhcpv6_assignall = true;
268         iface->dhcpv6_pd = true;
269         iface->dhcpv6_pd_min_len = 0;
270         iface->dhcpv6_na = true;
271         iface->dhcpv6_hostid_len = HOSTID_LEN_DEFAULT;
272         iface->dns_service = true;
273         iface->ra_flags = ND_RA_FLAG_OTHER;
274         iface->ra_slaac = true;
275         iface->ra_maxinterval = 600;
276         iface->ra_mininterval = iface->ra_maxinterval/3;
277         iface->ra_lifetime = -1;
278         iface->ra_dns = true;
279 }
280 
281 static void clean_interface(struct interface *iface)
282 {
283         free(iface->dns);
284         free(iface->search);
285         free(iface->upstream);
286         free(iface->dhcpv4_router);
287         free(iface->dhcpv4_dns);
288         free(iface->dhcpv6_raw);
289         free(iface->filter_class);
290         free(iface->dhcpv4_ntp);
291         free(iface->dhcpv6_ntp);
292         free(iface->dhcpv6_sntp);
293         for (unsigned i = 0; i < iface->dnr_cnt; i++) {
294                 free(iface->dnr[i].adn);
295                 free(iface->dnr[i].addr4);
296                 free(iface->dnr[i].addr6);
297                 free(iface->dnr[i].svc);
298         }
299         free(iface->dnr);
300         memset(&iface->ra, 0, sizeof(*iface) - offsetof(struct interface, ra));
301         set_interface_defaults(iface);
302 }
303 
304 static void close_interface(struct interface *iface)
305 {
306         avl_delete(&interfaces, &iface->avl);
307 
308         router_setup_interface(iface, false);
309         dhcpv6_setup_interface(iface, false);
310         ndp_setup_interface(iface, false);
311 #ifdef DHCPV4_SUPPORT
312         dhcpv4_setup_interface(iface, false);
313 #endif
314 
315         /* make sure timer is not on the timeouts list before freeing */
316         uloop_timeout_cancel(&iface->timer_rs);
317 
318         clean_interface(iface);
319         free(iface->addr4);
320         free(iface->addr6);
321         free(iface->invalid_addr6);
322         free(iface->ifname);
323         free(iface);
324 }
325 
326 static int parse_mode(const char *mode)
327 {
328         if (!strcmp(mode, "disabled"))
329                 return MODE_DISABLED;
330         else if (!strcmp(mode, "server"))
331                 return MODE_SERVER;
332         else if (!strcmp(mode, "relay"))
333                 return MODE_RELAY;
334         else if (!strcmp(mode, "hybrid"))
335                 return MODE_HYBRID;
336         else
337                 return -1;
338 }
339 
340 static int parse_ra_flags(uint8_t *flags, struct blob_attr *attr)
341 {
342         struct blob_attr *cur;
343         unsigned rem;
344 
345         blobmsg_for_each_attr(cur, attr, rem) {
346                 int i;
347 
348                 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
349                         continue;
350 
351                                 if (!blobmsg_check_attr(cur, false))
352                                                 continue;
353 
354                 for (i = 0; ra_flags[i].name; i++) {
355                         if (!strcmp(ra_flags[i].name, blobmsg_get_string(cur))) {
356                                 *flags |= ra_flags[i].flag;
357                                 break;
358                         }
359                 }
360 
361                 if (!ra_flags[i].name)
362                         return -1;
363         }
364 
365         return 0;
366 }
367 
368 static void set_config(struct uci_section *s)
369 {
370         struct blob_attr *tb[ODHCPD_ATTR_MAX], *c;
371 
372         blob_buf_init(&b, 0);
373         uci_to_blob(&b, s, &odhcpd_attr_list);
374         blobmsg_parse(odhcpd_attrs, ODHCPD_ATTR_MAX, tb, blob_data(b.head), blob_len(b.head));
375 
376         if ((c = tb[ODHCPD_ATTR_LEGACY]))
377                 config.legacy = blobmsg_get_bool(c);
378 
379         if ((c = tb[ODHCPD_ATTR_MAINDHCP]))
380                 config.main_dhcpv4 = blobmsg_get_bool(c);
381 
382         if ((c = tb[ODHCPD_ATTR_LEASEFILE])) {
383                 free(config.dhcp_statefile);
384                 config.dhcp_statefile = strdup(blobmsg_get_string(c));
385         }
386 
387         if ((c = tb[ODHCPD_ATTR_HOSTSFILE])) {
388                 free(config.dhcp_hostsfile);
389                 config.dhcp_hostsfile = strdup(blobmsg_get_string(c));
390         }
391 
392         if ((c = tb[ODHCPD_ATTR_LEASETRIGGER])) {
393                 free(config.dhcp_cb);
394                 config.dhcp_cb = strdup(blobmsg_get_string(c));
395         }
396 
397         if ((c = tb[ODHCPD_ATTR_LOGLEVEL])) {
398                 int log_level = (blobmsg_get_u32(c) & LOG_PRIMASK);
399 
400                 if (config.log_level != log_level) {
401                         config.log_level = log_level;
402                         setlogmask(LOG_UPTO(config.log_level));
403                 }
404         }
405 }
406 
407 static double parse_leasetime(struct blob_attr *c) {
408         char *val = blobmsg_get_string(c), *endptr = NULL;
409         double time = strcmp(val, "infinite") ? strtod(val, &endptr) : UINT32_MAX;
410 
411         if (time && endptr && endptr[0]) {
412                 if (endptr[0] == 's')
413                         time *= 1;
414                 else if (endptr[0] == 'm')
415                         time *= 60;
416                 else if (endptr[0] == 'h')
417                         time *= 3600;
418                 else if (endptr[0] == 'd')
419                         time *= 24 * 3600;
420                 else if (endptr[0] == 'w')
421                         time *= 7 * 24 * 3600;
422                 else
423                         goto err;
424         }
425 
426         if (time < 60)
427                 time = 60;
428 
429         return time;
430 
431 err:
432         return -1;
433 }
434 
435 static void free_lease(struct lease *l)
436 {
437         if (!l)
438                 return;
439 
440         free(l->hostname);
441         free(l);
442 }
443 
444 int set_lease_from_blobmsg(struct blob_attr *ba)
445 {
446         struct blob_attr *tb[LEASE_ATTR_MAX], *c;
447         struct lease *l = NULL;
448         int mac_count = 0;
449         struct ether_addr *macs;
450         size_t duidlen = 0;
451         uint8_t *duid;
452 
453         blobmsg_parse(lease_attrs, LEASE_ATTR_MAX, tb, blob_data(ba), blob_len(ba));
454 
455         if ((c = tb[LEASE_ATTR_MAC])) {
456                 mac_count = blobmsg_check_array_len(c, BLOBMSG_TYPE_STRING, blob_raw_len(c));
457                 if (mac_count < 0)
458                         goto err;
459         }
460 
461         if ((c = tb[LEASE_ATTR_DUID]))
462                 duidlen = (blobmsg_data_len(c) - 1) / 2;
463 
464         l = calloc_a(sizeof(*l),
465                      &macs, mac_count * sizeof(*macs),
466                      &duid, duidlen);
467         if (!l)
468                 goto err;
469 
470         if ((c = tb[LEASE_ATTR_MAC])) {
471                 struct blob_attr *cur;
472                 size_t rem;
473                 int i = 0;
474 
475                 l->mac_count = mac_count;
476                 l->macs = macs;
477 
478                 blobmsg_for_each_attr(cur, c, rem)
479                         if (!ether_aton_r(blobmsg_get_string(cur), &l->macs[i++]))
480                                 goto err;
481         }
482 
483         if ((c = tb[LEASE_ATTR_DUID])) {
484                 ssize_t len;
485 
486                 l->duid = duid;
487                 len = odhcpd_unhexlify(l->duid, duidlen, blobmsg_get_string(c));
488 
489                 if (len < 0)
490                         goto err;
491 
492                 l->duid_len = len;
493         }
494 
495         if ((c = tb[LEASE_ATTR_NAME])) {
496                 l->hostname = strdup(blobmsg_get_string(c));
497                 if (!l->hostname || !odhcpd_valid_hostname(l->hostname))
498                         goto err;
499         }
500 
501         if ((c = tb[LEASE_ATTR_IP]))
502                 if (inet_pton(AF_INET, blobmsg_get_string(c), &l->ipaddr) < 0)
503                         goto err;
504 
505         if ((c = tb[LEASE_ATTR_HOSTID])) {
506                 errno = 0;
507                 l->hostid = strtoull(blobmsg_get_string(c), NULL, 16);
508                 if (errno)
509                         goto err;
510         } else {
511                 uint32_t i4a = ntohl(l->ipaddr) & 0xff;
512                 l->hostid = ((i4a / 100) << 8) | (((i4a % 100) / 10) << 4) | (i4a % 10);
513         }
514 
515         if ((c = tb[LEASE_ATTR_LEASETIME])) {
516                 double time = parse_leasetime(c);
517                 if (time < 0)
518                         goto err;
519 
520                 l->leasetime = time;
521         }
522 
523         INIT_LIST_HEAD(&l->assignments);
524         vlist_add(&leases, &l->node, l);
525         return 0;
526 
527 err:
528         free_lease(l);
529         return -1;
530 }
531 
532 static int set_lease_from_uci(struct uci_section *s)
533 {
534         blob_buf_init(&b, 0);
535         uci_to_blob(&b, s, &lease_attr_list);
536 
537         return set_lease_from_blobmsg(b.head);
538 }
539 
540 /* Parse NTP Options for DHCPv6 Address */
541 static int parse_ntp_options(uint16_t *dhcpv6_ntp_len, struct in6_addr addr6, uint8_t **dhcpv6_ntp)
542 {
543         uint16_t sub_opt = 0, sub_len = htons(IPV6_ADDR_LEN);
544         uint16_t ntp_len = IPV6_ADDR_LEN + 4;
545         uint8_t *ntp = *dhcpv6_ntp;
546         size_t pos = *dhcpv6_ntp_len;
547 
548         ntp = realloc(ntp, pos + ntp_len);
549         if (!ntp)
550                 return -1;
551 
552         *dhcpv6_ntp = ntp;
553 
554         if (IN6_IS_ADDR_MULTICAST(&addr6))
555                 sub_opt = htons(NTP_SUBOPTION_MC_ADDR);
556         else
557                 sub_opt = htons(NTP_SUBOPTION_SRV_ADDR);
558 
559         memcpy(ntp + pos, &sub_opt, sizeof(sub_opt));
560         pos += sizeof(sub_opt);
561         memcpy(ntp + pos, &sub_len, sizeof(sub_len));
562         pos += sizeof(sub_len);
563         memcpy(ntp + pos, &addr6, IPV6_ADDR_LEN);
564 
565         *dhcpv6_ntp_len += ntp_len;
566 
567         return 0;
568 }
569 
570 /* Parse NTP Options for FQDN */
571 static int parse_ntp_fqdn(uint16_t *dhcpv6_ntp_len, char *fqdn, uint8_t **dhcpv6_ntp)
572 {
573         size_t fqdn_len = strlen(fqdn);
574         uint16_t sub_opt = 0, sub_len = 0, ntp_len = 0;
575         uint8_t *ntp = *dhcpv6_ntp;
576         size_t pos = *dhcpv6_ntp_len;
577         uint8_t buf[256] = {0};
578 
579         if (fqdn_len > 0 && fqdn[fqdn_len - 1] == '.')
580                 fqdn[fqdn_len - 1] = 0;
581 
582         int len = dn_comp(fqdn, buf, sizeof(buf), NULL, NULL);
583         if (len <= 0)
584                 return -1;
585 
586         ntp_len = len + 4;
587 
588         ntp = realloc(ntp, pos + ntp_len);
589         if (!ntp)
590                 return -1;
591 
592         *dhcpv6_ntp = ntp;
593 
594         sub_opt = htons(NTP_SUBOPTION_SRV_FQDN);
595         sub_len = htons(len);
596 
597         memcpy(ntp + pos, &sub_opt, sizeof(sub_opt));
598         pos += sizeof(sub_opt);
599         memcpy(ntp + pos, &sub_len, sizeof(sub_len));
600         pos += sizeof(sub_len);
601         memcpy(ntp + pos, buf, len);
602 
603         *dhcpv6_ntp_len += ntp_len;
604 
605         return 0;
606 }
607 
608 /* Parse DNR Options */
609 static int parse_dnr_str(char *str, struct interface *iface)
610 {
611         struct dnr_options dnr = {0};
612         size_t adn_len;
613         uint8_t adn_buf[256] = {0};
614         char *saveptr1, *saveptr2;
615 
616         char *priority;
617         priority = strtok_r(str, " \f\n\r\t\v", &saveptr1);
618         if (!priority) {
619                 goto err;
620         } else if (sscanf(priority, "%" SCNu16, &dnr.priority) != 1) {
621                 syslog(LOG_ERR, "Unable to parse priority '%s'", priority);
622                 goto err;
623         } else if (dnr.priority == 0) {
624                 syslog(LOG_ERR, "Invalid priority '%s'", priority);
625                 goto err;
626         }
627 
628         char *adn;
629         adn = strtok_r(NULL, " \f\n\r\t\v", &saveptr1);
630         if (!adn)
631                 goto err;
632 
633         adn_len = strlen(adn);
634         if (adn_len > 0 && adn[adn_len - 1] == '.')
635                 adn[adn_len - 1] = '\0';
636 
637         if (adn_len >= sizeof(adn_buf)) {
638                 syslog(LOG_ERR, "Hostname '%s' too long", adn);
639                 goto err;
640         }
641 
642         adn_len = dn_comp(adn, adn_buf, sizeof(adn_buf), NULL, NULL);
643         if (adn_len <= 0) {
644                 syslog(LOG_ERR, "Unable to parse hostname '%s'", adn);
645                 goto err;
646         }
647 
648         dnr.adn = malloc(adn_len);
649         if (!dnr.adn)
650                 goto err;
651         memcpy(dnr.adn, adn_buf, adn_len);
652         dnr.adn_len = adn_len;
653 
654         char *addrs;
655         addrs = strtok_r(NULL, " \f\n\r\t\v", &saveptr1);
656         if (!addrs)
657                 // ADN-Only mode
658                 goto done;
659 
660         for (char *addr = strtok_r(addrs, ",", &saveptr2); addr; addr = strtok_r(NULL, ",", &saveptr2)) {
661                 struct in6_addr addr6, *tmp6;
662                 struct in_addr addr4, *tmp4;
663                 size_t new_sz;
664 
665                 if (inet_pton(AF_INET6, addr, &addr6) == 1) {
666                         new_sz = (dnr.addr6_cnt + 1) * sizeof(*dnr.addr6);
667                         if (new_sz > UINT16_MAX)
668                                 continue;
669                         tmp6 = realloc(dnr.addr6, new_sz);
670                         if (!tmp6)
671                                 goto err;
672                         dnr.addr6 = tmp6;
673                         memcpy(&dnr.addr6[dnr.addr6_cnt], &addr6, sizeof(*dnr.addr6));
674                         dnr.addr6_cnt++;
675 
676                 } else if (inet_pton(AF_INET, addr, &addr4) == 1) {
677                         new_sz = (dnr.addr4_cnt + 1) * sizeof(*dnr.addr4);
678                         if (new_sz > UINT8_MAX)
679                                 continue;
680                         tmp4 = realloc(dnr.addr4, new_sz);
681                         if (!tmp4)
682                                 goto err;
683                         dnr.addr4 = tmp4;
684                         memcpy(&dnr.addr4[dnr.addr4_cnt], &addr4, sizeof(*dnr.addr4));
685                         dnr.addr4_cnt++;
686 
687                 } else {
688                         syslog(LOG_ERR, "Unable to parse IP address '%s'", addr);
689                         goto err;
690                 }
691         }
692 
693         char *svc_vals[DNR_SVC_MAX] = { NULL, };
694         for (char *svc_tok = strtok_r(NULL, " \f\n\r\t\v", &saveptr1); svc_tok; svc_tok = strtok_r(NULL, " \f\n\r\t\v", &saveptr1)) {
695                 uint16_t svc_id;
696                 char *svc_key, *svc_val;
697 
698                 svc_key = strtok_r(svc_tok, "=", &saveptr2);
699                 svc_val = strtok_r(NULL, "=", &saveptr2);
700 
701                 if (!strcmp(svc_key, "_lifetime")) {
702                         uint32_t lifetime;
703 
704                         if (!svc_val || sscanf(svc_val, "%" SCNu32, &lifetime) != 1) {
705                                 syslog(LOG_ERR, "Invalid value '%s' for _lifetime", svc_val ? svc_val : "");
706                                 goto err;
707                         }
708 
709                         dnr.lifetime = lifetime;
710                         dnr.lifetime_set = true;
711                         continue;
712                 }
713 
714                 for (svc_id = 0; svc_id < DNR_SVC_MAX; svc_id++)
715                         if (!strcmp(svc_key, svc_param_key_names[svc_id]))
716                                 break;
717 
718                 if (svc_id >= DNR_SVC_MAX) {
719                         syslog(LOG_ERR, "Invalid SvcParam '%s'", svc_key);
720                         goto err;
721                 }
722 
723                 svc_vals[svc_id] = svc_val ? svc_val : "";
724         }
725 
726         /* SvcParamKeys must be in increasing order, RFC9460 §2.2 */
727         for (uint16_t svc_key = 0; svc_key < DNR_SVC_MAX; svc_key++) {
728                 uint16_t svc_key_be = ntohs(svc_key);
729                 uint16_t svc_val_len, svc_val_len_be;
730                 char *svc_val_str = svc_vals[svc_key];
731                 uint8_t *tmp;
732 
733                 if (!svc_val_str)
734                         continue;
735 
736                 switch (svc_key) {
737                 case DNR_SVC_MANDATORY:
738                         uint16_t mkeys[DNR_SVC_MAX];
739 
740                         svc_val_len = 0;
741                         for (char *mkey_str = strtok_r(svc_val_str, ",", &saveptr2); mkey_str; mkey_str = strtok_r(NULL, ",", &saveptr2)) {
742                                 uint16_t mkey;
743 
744                                 for (mkey = 0; mkey < DNR_SVC_MAX; mkey++)
745                                         if (!strcmp(mkey_str, svc_param_key_names[mkey]))
746                                                 break;
747 
748                                 if (mkey >= DNR_SVC_MAX || !svc_vals[mkey]) {
749                                         syslog(LOG_ERR, "Invalid value '%s' for SvcParam 'mandatory'", mkey_str);
750                                         goto err;
751                                 }
752 
753                                 mkeys[svc_val_len++] = ntohs(mkey);
754                         }
755 
756                         svc_val_len *= sizeof(uint16_t);
757                         svc_val_len_be = ntohs(svc_val_len);
758 
759                         tmp = realloc(dnr.svc, dnr.svc_len + 4 + svc_val_len);
760                         if (!tmp)
761                                 goto err;
762 
763                         dnr.svc = tmp;
764                         memcpy(dnr.svc + dnr.svc_len, &svc_key_be, sizeof(svc_key_be));
765                         memcpy(dnr.svc + dnr.svc_len + 2, &svc_val_len_be, sizeof(svc_val_len_be));
766                         memcpy(dnr.svc + dnr.svc_len + 4, mkeys, svc_val_len);
767                         dnr.svc_len += 4 + svc_val_len;
768                         break;
769 
770                 case DNR_SVC_ALPN:
771                         size_t len_off;
772 
773                         tmp = realloc(dnr.svc, dnr.svc_len + 4);
774                         if (!tmp)
775                                 goto err;
776 
777                         dnr.svc = tmp;
778                         memcpy(dnr.svc + dnr.svc_len, &svc_key_be, sizeof(svc_key_be));
779                         /* the length is not known yet */
780                         len_off = dnr.svc_len + sizeof(svc_key_be);
781                         dnr.svc_len += 4;
782 
783                         svc_val_len = 0;
784                         for (char *alpn_id_str = strtok_r(svc_val_str, ",", &saveptr2); alpn_id_str; alpn_id_str = strtok_r(NULL, ",", &saveptr2)) {
785                                 size_t alpn_id_len;
786 
787                                 alpn_id_len = strlen(alpn_id_str);
788                                 if (alpn_id_len > UINT8_MAX) {
789                                         syslog(LOG_ERR, "Invalid value '%s' for SvcParam 'alpn'", alpn_id_str);
790                                         goto err;
791                                 }
792 
793                                 tmp = realloc(dnr.svc, dnr.svc_len + 1 + alpn_id_len);
794                                 if (!tmp)
795                                         goto err;
796                                 dnr.svc = tmp;
797 
798                                 dnr.svc[dnr.svc_len] = alpn_id_len;
799                                 memcpy(dnr.svc + dnr.svc_len + 1, alpn_id_str, alpn_id_len);
800                                 dnr.svc_len += 1 + alpn_id_len;
801                                 svc_val_len += 1 + alpn_id_len;
802                         }
803 
804                         svc_val_len_be = ntohs(svc_val_len);
805                         memcpy(dnr.svc + len_off, &svc_val_len_be, sizeof(svc_val_len_be));
806                         break;
807 
808                 case DNR_SVC_PORT:
809                         uint16_t port;
810 
811                         if (sscanf(svc_val_str, "%" SCNu16, &port) != 1) {
812                                 syslog(LOG_ERR, "Invalid value '%s' for SvcParam 'port'", svc_val_str);
813                                 goto err;
814                         }
815 
816                         port = ntohs(port);
817                         svc_val_len_be = ntohs(2);
818 
819                         tmp = realloc(dnr.svc, dnr.svc_len + 6);
820                         if (!tmp)
821                                 goto err;
822 
823                         dnr.svc = tmp;
824                         memcpy(dnr.svc + dnr.svc_len, &svc_key_be, sizeof(svc_key_be));
825                         memcpy(dnr.svc + dnr.svc_len + 2, &svc_val_len_be, sizeof(svc_val_len_be));
826                         memcpy(dnr.svc + dnr.svc_len + 4, &port, sizeof(port));
827                         dnr.svc_len += 6;
828                         break;
829 
830                 case DNR_SVC_NO_DEFAULT_ALPN:
831                         /* fall through */
832 
833                 case DNR_SVC_OHTTP:
834                         if (strlen(svc_val_str) > 0) {
835                                 syslog(LOG_ERR, "Invalid value '%s' for SvcParam 'port'", svc_val_str);
836                                 goto err;
837                         }
838                         /* fall through */
839 
840                 case DNR_SVC_DOHPATH:
841                         /* plain string */
842                         svc_val_len = strlen(svc_val_str);
843                         svc_val_len_be = ntohs(svc_val_len);
844                         tmp = realloc(dnr.svc, dnr.svc_len + 4 + svc_val_len);
845                         if (!tmp)
846                                 goto err;
847 
848                         dnr.svc = tmp;
849                         memcpy(dnr.svc + dnr.svc_len, &svc_key_be, sizeof(svc_key_be));
850                         dnr.svc_len += sizeof(svc_key_be);
851                         memcpy(dnr.svc + dnr.svc_len, &svc_val_len_be, sizeof(svc_val_len_be));
852                         dnr.svc_len += sizeof(svc_val_len_be);
853                         memcpy(dnr.svc + dnr.svc_len, svc_val_str, svc_val_len);
854                         dnr.svc_len += svc_val_len;
855                         break;
856 
857                 case DNR_SVC_ECH:
858                         syslog(LOG_ERR, "SvcParam 'ech' is not implemented");
859                         goto err;
860 
861                 case DNR_SVC_IPV4HINT:
862                         /* fall through */
863 
864                 case DNR_SVC_IPV6HINT:
865                         syslog(LOG_ERR, "SvcParam '%s' is not allowed", svc_param_key_names[svc_key]);
866                         goto err;
867                 }
868         }
869 
870 done:
871         struct dnr_options *tmp;
872         tmp = realloc(iface->dnr, (iface->dnr_cnt + 1) * sizeof(dnr));
873         if (!tmp)
874                 goto err;
875 
876         iface->dnr = tmp;
877         memcpy(iface->dnr + iface->dnr_cnt, &dnr, sizeof(dnr));
878         iface->dnr_cnt++;
879         return 0;
880 
881 err:
882         free(dnr.adn);
883         free(dnr.addr4);
884         free(dnr.addr6);
885         free(dnr.svc);
886         return -1;
887 }
888 
889 int config_parse_interface(void *data, size_t len, const char *name, bool overwrite)
890 {
891         struct odhcpd_ipaddr *addrs = NULL;
892         struct interface *iface;
893         struct blob_attr *tb[IFACE_ATTR_MAX], *c;
894         ssize_t addrs_len;
895         bool get_addrs = false;
896         int mode;
897         const char *ifname = NULL;
898 
899         blobmsg_parse(iface_attrs, IFACE_ATTR_MAX, tb, data, len);
900 
901         if (tb[IFACE_ATTR_INTERFACE])
902                 name = blobmsg_get_string(tb[IFACE_ATTR_INTERFACE]);
903 
904         if (!name)
905                 return -1;
906 
907         iface = avl_find_element(&interfaces, name, iface, avl);
908         if (!iface) {
909                 char *new_name;
910 
911                 iface = calloc_a(sizeof(*iface), &new_name, strlen(name) + 1);
912                 if (!iface)
913                         return -1;
914 
915                 iface->name = strcpy(new_name, name);
916                 iface->avl.key = iface->name;
917                 iface->router_event.uloop.fd = -1;
918                 iface->dhcpv6_event.uloop.fd = -1;
919                 iface->ndp_event.uloop.fd = -1;
920                 iface->ndp_ping_fd = -1;
921                 iface->dhcpv4_event.uloop.fd = -1;
922                 INIT_LIST_HEAD(&iface->ia_assignments);
923                 INIT_LIST_HEAD(&iface->dhcpv4_assignments);
924                 INIT_LIST_HEAD(&iface->dhcpv4_fr_ips);
925 
926                 set_interface_defaults(iface);
927 
928                 avl_insert(&interfaces, &iface->avl);
929                 get_addrs = overwrite = true;
930         }
931 
932         if (overwrite) {
933                 if ((c = tb[IFACE_ATTR_IFNAME]))
934                         ifname = blobmsg_get_string(c);
935                 else if ((c = tb[IFACE_ATTR_NETWORKID]))
936                         ifname = blobmsg_get_string(c);
937         }
938 
939 #ifdef WITH_UBUS
940         if (overwrite || !iface->ifname)
941                 ifname = ubus_get_ifname(name);
942 #endif
943 
944         if (!iface->ifname && !ifname)
945                 goto err;
946 
947         if (ifname) {
948                 free(iface->ifname);
949                 iface->ifname = strdup(ifname);
950 
951                 if (!iface->ifname)
952                         goto err;
953 
954                 if (!iface->ifindex &&
955                         (iface->ifindex = if_nametoindex(iface->ifname)) <= 0)
956                         goto err;
957 
958                 if ((iface->ifflags = odhcpd_get_flags(iface)) < 0)
959                         goto err;
960         }
961 
962         if (get_addrs) {
963                 addrs_len = netlink_get_interface_addrs(iface->ifindex,
964                                                 true, &iface->addr6);
965 
966                 if (addrs_len > 0)
967                         iface->addr6_len = addrs_len;
968 
969                 addrs_len = netlink_get_interface_addrs(iface->ifindex,
970                                                 false, &iface->addr4);
971                 if (addrs_len > 0)
972                         iface->addr4_len = addrs_len;
973         }
974 
975         addrs_len = netlink_get_interface_linklocal(iface->ifindex, &addrs);
976         if (addrs_len > 0) {
977                 for (ssize_t i = 0; i < addrs_len; i++) {
978                         if (!addrs[i].tentative) {
979                                 iface->have_link_local = true;
980                                 break;
981                         }
982                 }
983                 free(addrs);
984         }
985 
986         iface->inuse = true;
987 
988         if ((c = tb[IFACE_ATTR_DYNAMICDHCP]))
989                 iface->no_dynamic_dhcp = !blobmsg_get_bool(c);
990 
991         if ((c = tb[IFACE_ATTR_LEASETIME])) {
992                 double time = parse_leasetime(c);
993 
994                 if (time >= 0)
995                         iface->dhcp_leasetime = time;
996                 else
997                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
998                                         iface_attrs[IFACE_ATTR_LEASETIME].name, iface->name);
999 
1000         }
1001 
1002         if ((c = tb[IFACE_ATTR_MAX_PREFERRED_LIFETIME])) {
1003                 double time = parse_leasetime(c);
1004 
1005                 if (time >= 0) {
1006                         iface->max_preferred_lifetime = time;
1007                 } else {
1008                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1009                                iface_attrs[IFACE_ATTR_MAX_PREFERRED_LIFETIME].name, iface->name);
1010                 }
1011         }
1012 
1013         if ((c = tb[IFACE_ATTR_MAX_VALID_LIFETIME])) {
1014                 double time = parse_leasetime(c);
1015 
1016                 if (time >= 0) {
1017                         iface->max_valid_lifetime = time;
1018                 } else {
1019                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1020                                iface_attrs[IFACE_ATTR_MAX_VALID_LIFETIME].name, iface->name);
1021                 }
1022         }
1023 
1024         if ((c = tb[IFACE_ATTR_START])) {
1025                 iface->dhcpv4_start.s_addr = htonl(blobmsg_get_u32(c));
1026                 iface->dhcpv4_end.s_addr = htonl(ntohl(iface->dhcpv4_start.s_addr) +
1027                                                         LIMIT_DEFAULT - 1);
1028 
1029                 if (config.main_dhcpv4 && config.legacy)
1030                         iface->dhcpv4 = MODE_SERVER;
1031         }
1032 
1033         if ((c = tb[IFACE_ATTR_LIMIT]))
1034                 iface->dhcpv4_end.s_addr = htonl(ntohl(iface->dhcpv4_start.s_addr) +
1035                                                         blobmsg_get_u32(c) - 1);
1036 
1037         if ((c = tb[IFACE_ATTR_MASTER]))
1038                 iface->master = blobmsg_get_bool(c);
1039 
1040         if (overwrite && (c = tb[IFACE_ATTR_UPSTREAM])) {
1041                 struct blob_attr *cur;
1042                 unsigned rem;
1043 
1044                 blobmsg_for_each_attr(cur, c, rem) {
1045                         if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false))
1046                                 continue;
1047 
1048                         iface->upstream = realloc(iface->upstream,
1049                                         iface->upstream_len + blobmsg_data_len(cur));
1050                         if (!iface->upstream)
1051                                 goto err;
1052 
1053                         memcpy(iface->upstream + iface->upstream_len, blobmsg_get_string(cur), blobmsg_data_len(cur));
1054                         iface->upstream_len += blobmsg_data_len(cur);
1055                 }
1056         }
1057 
1058         if ((c = tb[IFACE_ATTR_RA])) {
1059                 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) {
1060                         iface->ra = mode;
1061 
1062                         if (iface->ra != MODE_DISABLED)
1063                                 iface->ignore = false;
1064                 } else
1065                         syslog(LOG_ERR, "Invalid %s mode configured for interface '%s'",
1066                                         iface_attrs[IFACE_ATTR_RA].name, iface->name);
1067         }
1068 
1069         if ((c = tb[IFACE_ATTR_DHCPV4])) {
1070                 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) {
1071                         if (config.main_dhcpv4) {
1072                                 iface->dhcpv4 = mode;
1073 
1074                                 if (iface->dhcpv4 != MODE_DISABLED)
1075                                         iface->ignore = false;
1076                         }
1077                 } else
1078                         syslog(LOG_ERR, "Invalid %s mode configured for interface %s",
1079                                         iface_attrs[IFACE_ATTR_DHCPV4].name, iface->name);
1080         }
1081 
1082         if ((c = tb[IFACE_ATTR_DHCPV6])) {
1083                 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) {
1084                         iface->dhcpv6 = mode;
1085 
1086                         if (iface->dhcpv6 != MODE_DISABLED)
1087                                 iface->ignore = false;
1088                 } else
1089                         syslog(LOG_ERR, "Invalid %s mode configured for interface '%s'",
1090                                         iface_attrs[IFACE_ATTR_DHCPV6].name, iface->name);
1091         }
1092 
1093         if ((c = tb[IFACE_ATTR_NDP])) {
1094                 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) {
1095                         iface->ndp = mode;
1096 
1097                         if (iface->ndp != MODE_DISABLED)
1098                                 iface->ignore = false;
1099                 } else
1100                         syslog(LOG_ERR, "Invalid %s mode configured for interface '%s'",
1101                                         iface_attrs[IFACE_ATTR_NDP].name, iface->name);
1102         }
1103 
1104         if ((c = tb[IFACE_ATTR_ROUTER])) {
1105                 struct blob_attr *cur;
1106                 unsigned rem;
1107 
1108                 blobmsg_for_each_attr(cur, c, rem) {
1109                         struct in_addr addr4;
1110 
1111                         if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false))
1112                                 continue;
1113 
1114                         if (inet_pton(AF_INET, blobmsg_get_string(cur), &addr4) == 1) {
1115                                 iface->dhcpv4_router = realloc(iface->dhcpv4_router,
1116                                                 (++iface->dhcpv4_router_cnt) * sizeof(*iface->dhcpv4_router));
1117                                 if (!iface->dhcpv4_router)
1118                                         goto err;
1119 
1120                                 iface->dhcpv4_router[iface->dhcpv4_router_cnt - 1] = addr4;
1121                         } else
1122                                 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1123                                                 iface_attrs[IFACE_ATTR_ROUTER].name, iface->name);
1124                 }
1125         }
1126 
1127         if ((c = tb[IFACE_ATTR_DNS])) {
1128                 struct blob_attr *cur;
1129                 unsigned rem;
1130 
1131                 iface->always_rewrite_dns = true;
1132                 blobmsg_for_each_attr(cur, c, rem) {
1133                         struct in_addr addr4;
1134                         struct in6_addr addr6;
1135 
1136                         if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false))
1137                                 continue;
1138 
1139                         if (inet_pton(AF_INET, blobmsg_get_string(cur), &addr4) == 1) {
1140                                 if (addr4.s_addr == INADDR_ANY) {
1141                                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1142                                                         iface_attrs[IFACE_ATTR_DNS].name, iface->name);
1143 
1144                                         continue;
1145                                 }
1146 
1147                                 iface->dhcpv4_dns = realloc(iface->dhcpv4_dns,
1148                                                 (++iface->dhcpv4_dns_cnt) * sizeof(*iface->dhcpv4_dns));
1149                                 if (!iface->dhcpv4_dns)
1150                                         goto err;
1151 
1152                                 iface->dhcpv4_dns[iface->dhcpv4_dns_cnt - 1] = addr4;
1153                         } else if (inet_pton(AF_INET6, blobmsg_get_string(cur), &addr6) == 1) {
1154                                 if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) {
1155                                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1156                                                         iface_attrs[IFACE_ATTR_DNS].name, iface->name);
1157 
1158                                         continue;
1159                                 }
1160 
1161                                 iface->dns = realloc(iface->dns,
1162                                                 (++iface->dns_cnt) * sizeof(*iface->dns));
1163                                 if (!iface->dns)
1164                                         goto err;
1165 
1166                                 iface->dns[iface->dns_cnt - 1] = addr6;
1167                         } else
1168                                 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1169                                                 iface_attrs[IFACE_ATTR_DNS].name, iface->name);
1170                 }
1171         }
1172 
1173         if ((c = tb[IFACE_ATTR_DNS_SERVICE]))
1174                 iface->dns_service = blobmsg_get_bool(c);
1175 
1176         if ((c = tb[IFACE_ATTR_DOMAIN])) {
1177                 struct blob_attr *cur;
1178                 unsigned rem;
1179 
1180                 blobmsg_for_each_attr(cur, c, rem) {
1181                         uint8_t buf[256];
1182                         char *domain = blobmsg_get_string(cur);
1183                         size_t domainlen = strlen(domain);
1184                         int len;
1185 
1186                         if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false))
1187                                 continue;
1188 
1189                         domain = blobmsg_get_string(cur);
1190                         domainlen = strlen(domain);
1191 
1192                         if (domainlen > 0 && domain[domainlen - 1] == '.')
1193                                 domain[domainlen - 1] = 0;
1194 
1195                         len = dn_comp(domain, buf, sizeof(buf), NULL, NULL);
1196                         if (len <= 0) {
1197                                 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1198                                                 iface_attrs[IFACE_ATTR_DOMAIN].name, iface->name);
1199 
1200                                 continue;
1201                         }
1202 
1203                         iface->search = realloc(iface->search, iface->search_len + len);
1204                         if (!iface->search)
1205                                 goto err;
1206 
1207                         memcpy(&iface->search[iface->search_len], buf, len);
1208                         iface->search_len += len;
1209                 }
1210         }
1211 
1212         if ((c = tb[IFACE_ATTR_FILTER_CLASS])) {
1213                 iface->filter_class = realloc(iface->filter_class, blobmsg_data_len(c) + 1);
1214                 memcpy(iface->filter_class, blobmsg_get_string(c), blobmsg_data_len(c) + 1);
1215         }
1216 
1217         if ((c = tb[IFACE_ATTR_DHCPV4_FORCERECONF]))
1218                 iface->dhcpv4_forcereconf = blobmsg_get_bool(c);
1219 
1220         if ((c = tb[IFACE_ATTR_DHCPV6_RAW])) {
1221                 iface->dhcpv6_raw_len = blobmsg_data_len(c) / 2;
1222                 iface->dhcpv6_raw = realloc(iface->dhcpv6_raw, iface->dhcpv6_raw_len);
1223                 odhcpd_unhexlify(iface->dhcpv6_raw, iface->dhcpv6_raw_len, blobmsg_get_string(c));
1224         }
1225 
1226         if ((c = tb[IFACE_ATTR_DHCPV6_ASSIGNALL]))
1227                 iface->dhcpv6_assignall = blobmsg_get_bool(c);
1228 
1229         if ((c = tb[IFACE_ATTR_DHCPV6_PD]))
1230                 iface->dhcpv6_pd = blobmsg_get_bool(c);
1231 
1232         if ((c = tb[IFACE_ATTR_DHCPV6_PD_MIN_LEN])) {
1233                 uint32_t pd_min_len = blobmsg_get_u32(c);
1234                 if (pd_min_len != 0 && pd_min_len <= PD_MIN_LEN_MAX)
1235                         iface->dhcpv6_pd_min_len = pd_min_len;
1236                 else
1237                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1238                                         iface_attrs[IFACE_ATTR_DHCPV6_PD_MIN_LEN].name, iface->name);
1239         }
1240 
1241         if ((c = tb[IFACE_ATTR_DHCPV6_NA]))
1242                 iface->dhcpv6_na = blobmsg_get_bool(c);
1243 
1244         if ((c = tb[IFACE_ATTR_DHCPV6_HOSTID_LEN])) {
1245                 uint32_t hostid_len = blobmsg_get_u32(c);
1246 
1247                 if (hostid_len >= HOSTID_LEN_MIN && hostid_len <= HOSTID_LEN_MAX)
1248                         iface->dhcpv6_hostid_len = hostid_len;
1249                 else
1250                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1251                                 iface_attrs[IFACE_ATTR_DHCPV6_HOSTID_LEN].name, iface->name);
1252 
1253         }
1254 
1255         if ((c = tb[IFACE_ATTR_RA_DEFAULT]))
1256                 iface->default_router = blobmsg_get_u32(c);
1257 
1258         /* IFACE_ATTR_RA_MANAGEMENT aka ra_management is deprecated since 2019 */
1259         if (!tb[IFACE_ATTR_RA_FLAGS] && !tb[IFACE_ATTR_RA_SLAAC] &&
1260                 (c = tb[IFACE_ATTR_RA_MANAGEMENT])) {
1261                 switch (blobmsg_get_u32(c)) {
1262                 case 0:
1263                         iface->ra_flags = ND_RA_FLAG_OTHER;
1264                         iface->ra_slaac = true;
1265                         break;
1266                 case 1:
1267                         iface->ra_flags = ND_RA_FLAG_OTHER|ND_RA_FLAG_MANAGED;
1268                         iface->ra_slaac = true;
1269                         break;
1270                 case 2:
1271                         iface->ra_flags = ND_RA_FLAG_OTHER|ND_RA_FLAG_MANAGED;
1272                         iface->ra_slaac = false;
1273                         break;
1274                 default:
1275                         break;
1276                 }
1277         }
1278 
1279         if ((c = tb[IFACE_ATTR_RA_FLAGS])) {
1280                 iface->ra_flags = 0;
1281 
1282                 if (parse_ra_flags(&iface->ra_flags, c) < 0)
1283                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1284                                         iface_attrs[IFACE_ATTR_RA_FLAGS].name, iface->name);
1285         }
1286 
1287         if ((c = tb[IFACE_ATTR_RA_REACHABLETIME])) {
1288                 uint32_t ra_reachabletime = blobmsg_get_u32(c);
1289 
1290                 if (ra_reachabletime <= 3600000)
1291                         iface->ra_reachabletime = ra_reachabletime;
1292                 else
1293                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1294                                         iface_attrs[IFACE_ATTR_RA_REACHABLETIME].name, iface->name);
1295         }
1296 
1297         if ((c = tb[IFACE_ATTR_RA_RETRANSTIME])) {
1298                 uint32_t ra_retranstime = blobmsg_get_u32(c);
1299 
1300                 if (ra_retranstime <= 60000)
1301                         iface->ra_retranstime = ra_retranstime;
1302                 else
1303                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1304                                         iface_attrs[IFACE_ATTR_RA_RETRANSTIME].name, iface->name);
1305         }
1306 
1307         if ((c = tb[IFACE_ATTR_RA_HOPLIMIT])) {
1308                 uint32_t ra_hoplimit = blobmsg_get_u32(c);
1309 
1310                 if (ra_hoplimit <= 255)
1311                         iface->ra_hoplimit = ra_hoplimit;
1312                 else
1313                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1314                                         iface_attrs[IFACE_ATTR_RA_HOPLIMIT].name, iface->name);
1315         }
1316 
1317         if ((c = tb[IFACE_ATTR_RA_MTU])) {
1318                 uint32_t ra_mtu = blobmsg_get_u32(c);
1319 
1320                 if (ra_mtu >= 1280 || ra_mtu <= 65535)
1321                         iface->ra_mtu = ra_mtu;
1322                 else
1323                         syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1324                                         iface_attrs[IFACE_ATTR_RA_MTU].name, iface->name);
1325         }
1326 
1327         if ((c = tb[IFACE_ATTR_RA_SLAAC]))
1328                 iface->ra_slaac = blobmsg_get_bool(c);
1329 
1330         if ((c = tb[IFACE_ATTR_RA_OFFLINK]))
1331                 iface->ra_not_onlink = blobmsg_get_bool(c);
1332 
1333         if ((c = tb[IFACE_ATTR_RA_ADVROUTER]))
1334                 iface->ra_advrouter = blobmsg_get_bool(c);
1335 
1336         if ((c = tb[IFACE_ATTR_RA_MININTERVAL]))
1337                 iface->ra_mininterval =  blobmsg_get_u32(c);
1338 
1339         if ((c = tb[IFACE_ATTR_RA_MAXINTERVAL]))
1340                 iface->ra_maxinterval = blobmsg_get_u32(c);
1341 
1342         if ((c = tb[IFACE_ATTR_RA_LIFETIME]))
1343                 iface->ra_lifetime = blobmsg_get_u32(c);
1344 
1345         if ((c = tb[IFACE_ATTR_RA_DNS]))
1346                 iface->ra_dns = blobmsg_get_bool(c);
1347 
1348         if ((c = tb[IFACE_ATTR_DNR])) {
1349                 struct blob_attr *cur;
1350                 unsigned rem;
1351 
1352                 blobmsg_for_each_attr(cur, c, rem) {
1353                         if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false))
1354                                 continue;
1355 
1356                         if (parse_dnr_str(blobmsg_get_string(cur), iface))
1357                                 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1358                                        iface_attrs[IFACE_ATTR_DNR].name, iface->name);
1359                 }
1360         }
1361 
1362         if ((c = tb[IFACE_ATTR_RA_PREF64])) {
1363                 struct in6_addr addr;
1364 
1365                 odhcpd_parse_addr6_prefix(blobmsg_get_string(c),
1366                                           &addr, &iface->pref64_length);
1367 
1368                 iface->pref64_prefix[0] = addr.s6_addr32[0];
1369                 switch (iface->pref64_length) {
1370                 case 96:
1371                         iface->pref64_plc = 0;
1372                         iface->pref64_prefix[1] = addr.s6_addr32[1];
1373                         iface->pref64_prefix[2] = addr.s6_addr32[2];
1374                         break;
1375                 case 64:
1376                         iface->pref64_plc = 1;
1377                         iface->pref64_prefix[1] = addr.s6_addr32[1];
1378                         iface->pref64_prefix[2] = 0;
1379                         break;
1380                 case 56:
1381                         iface->pref64_plc = 2;
1382                         iface->pref64_prefix[1] = addr.s6_addr32[1] & htonl(0xffffff00);
1383                         iface->pref64_prefix[2] = 0;
1384                         break;
1385                 case 48:
1386                         iface->pref64_plc = 3;
1387                         iface->pref64_prefix[1] = addr.s6_addr32[1] & htonl(0xffff0000);
1388                         iface->pref64_prefix[2] = 0;
1389                         break;
1390                 case 40:
1391                         iface->pref64_plc = 4;
1392                         iface->pref64_prefix[1] = addr.s6_addr32[1] & htonl(0xff000000);
1393                         iface->pref64_prefix[2] = 0;
1394                         break;
1395                 case 32:
1396                         iface->pref64_plc = 5;
1397                         iface->pref64_prefix[1] = 0;
1398                         iface->pref64_prefix[2] = 0;
1399                         break;
1400                 default:
1401                         syslog(LOG_WARNING, "Invalid PREF64 prefix size (%d), "
1402                                "ignoring ra_pref64 option!", iface->pref64_length);
1403                         iface->pref64_length = 0;
1404                 }
1405         }
1406 
1407         if ((c = tb[IFACE_ATTR_RA_PREFERENCE])) {
1408                 const char *prio = blobmsg_get_string(c);
1409 
1410                 if (!strcmp(prio, "high"))
1411                         iface->route_preference = 1;
1412                 else if (!strcmp(prio, "low"))
1413                         iface->route_preference = -1;
1414                 else if (!strcmp(prio, "medium") || !strcmp(prio, "default"))
1415                         iface->route_preference = 0;
1416                 else
1417                         syslog(LOG_ERR, "Invalid %s mode configured for interface '%s'",
1418                                         iface_attrs[IFACE_ATTR_RA_PREFERENCE].name, iface->name);
1419         }
1420 
1421         if ((c = tb[IFACE_ATTR_PD_MANAGER]))
1422                 strncpy(iface->dhcpv6_pd_manager, blobmsg_get_string(c),
1423                                 sizeof(iface->dhcpv6_pd_manager) - 1);
1424 
1425         if ((c = tb[IFACE_ATTR_PD_CER]) &&
1426                         inet_pton(AF_INET6, blobmsg_get_string(c), &iface->dhcpv6_pd_cer) < 1)
1427                 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'",
1428                                 iface_attrs[IFACE_ATTR_PD_CER].name, iface->name);
1429 
1430         if ((c = tb[IFACE_ATTR_NDPROXY_ROUTING]))
1431                 iface->learn_routes = blobmsg_get_bool(c);
1432 
1433         if ((c = tb[IFACE_ATTR_NDPROXY_SLAVE]))
1434                 iface->external = blobmsg_get_bool(c);
1435 
1436         if ((c = tb[IFACE_ATTR_PREFIX_FILTER]))
1437                 odhcpd_parse_addr6_prefix(blobmsg_get_string(c),
1438                                           &iface->pio_filter_addr,
1439                                           &iface->pio_filter_length);
1440 
1441         if (overwrite && (c = tb[IFACE_ATTR_NTP])) {
1442                 struct blob_attr *cur;
1443                 unsigned rem;
1444 
1445                 blobmsg_for_each_attr(cur, c, rem) {
1446                         if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false))
1447                                 continue;
1448 
1449                         char *str = blobmsg_get_string(cur);
1450                         struct in_addr addr4;
1451                         struct in6_addr addr6;
1452 
1453                         if (inet_pton(AF_INET, str, &addr4) == 1) {
1454                                 if (addr4.s_addr == INADDR_ANY)
1455                                         goto err;
1456 
1457                                 iface->dhcpv4_ntp = realloc(iface->dhcpv4_ntp,
1458                                                 (++iface->dhcpv4_ntp_cnt) * sizeof(*iface->dhcpv4_ntp));
1459                                 if (!iface->dhcpv4_ntp)
1460                                         goto err;
1461 
1462                                 iface->dhcpv4_ntp[iface->dhcpv4_ntp_cnt - 1] = addr4;
1463                         } else if (inet_pton(AF_INET6, str, &addr6) == 1) {
1464                                 if (IN6_IS_ADDR_UNSPECIFIED(&addr6))
1465                                         goto err;
1466 
1467                                 iface->dhcpv6_sntp = realloc(iface->dhcpv6_sntp,
1468                                                 (++iface->dhcpv6_sntp_cnt) * sizeof(*iface->dhcpv6_sntp));
1469                                 if (!iface->dhcpv6_sntp)
1470                                         goto err;
1471 
1472                                 iface->dhcpv6_sntp[iface->dhcpv6_sntp_cnt - 1] = addr6;
1473 
1474                                 if (!parse_ntp_options(&iface->dhcpv6_ntp_len, addr6, &iface->dhcpv6_ntp))
1475                                         iface->dhcpv6_ntp_cnt++;
1476                         } else {
1477                                 if (!parse_ntp_fqdn(&iface->dhcpv6_ntp_len, str, &iface->dhcpv6_ntp))
1478                                         iface->dhcpv6_ntp_cnt++;
1479                         }
1480                 }
1481         }
1482 
1483         return 0;
1484 
1485 err:
1486         close_interface(iface);
1487         return -1;
1488 }
1489 
1490 static int set_interface(struct uci_section *s)
1491 {
1492         blob_buf_init(&b, 0);
1493         uci_to_blob(&b, s, &interface_attr_list);
1494 
1495         return config_parse_interface(blob_data(b.head), blob_len(b.head), s->e.name, true);
1496 }
1497 
1498 static void lease_delete_assignments(struct lease *l, bool v6)
1499 {
1500         struct dhcp_assignment *a, *tmp;
1501         unsigned int flag = v6 ? OAF_DHCPV6 : OAF_DHCPV4;
1502 
1503         list_for_each_entry_safe(a, tmp, &l->assignments, lease_list) {
1504                 if (a->flags & flag)
1505                         free_assignment(a);
1506         }
1507 }
1508 
1509 static void lease_update_assignments(struct lease *l)
1510 {
1511         struct dhcp_assignment *a;
1512 
1513         list_for_each_entry(a, &l->assignments, lease_list) {
1514                 if (a->hostname)
1515                         free(a->hostname);
1516                 a->hostname = NULL;
1517 
1518                 if (l->hostname)
1519                         a->hostname = strdup(l->hostname);
1520 
1521                 a->leasetime = l->leasetime;
1522         }
1523 }
1524 
1525 static int lease_cmp(const void *k1, const void *k2, _unused void *ptr)
1526 {
1527         const struct lease *l1 = k1, *l2 = k2;
1528         int cmp = 0;
1529 
1530         if (l1->duid_len != l2->duid_len)
1531                 return l1->duid_len - l2->duid_len;
1532 
1533         if (l1->duid_len && l2->duid_len)
1534                 cmp = memcmp(l1->duid, l2->duid, l1->duid_len);
1535 
1536         if (cmp)
1537                 return cmp;
1538 
1539         if (l1->mac_count != l2->mac_count)
1540                 return l1->mac_count - l2->mac_count;
1541 
1542         for (size_t i = 0; i < l1->mac_count; i++) {
1543                 cmp = memcmp(l1->macs[i].ether_addr_octet,
1544                              l2->macs[i].ether_addr_octet,
1545                              sizeof(l1->macs[i].ether_addr_octet));
1546                 if (cmp)
1547                         return cmp;
1548         }
1549 
1550         return 0;
1551 }
1552 
1553 static void lease_change_config(struct lease *l_old, struct lease *l_new)
1554 {
1555         bool update = false;
1556 
1557         if ((!!l_new->hostname != !!l_old->hostname) ||
1558                 (l_new->hostname && strcmp(l_new->hostname, l_old->hostname))) {
1559                 free(l_old->hostname);
1560                 l_old->hostname = NULL;
1561 
1562                 if (l_new->hostname)
1563                         l_old->hostname = strdup(l_new->hostname);
1564 
1565                 update = true;
1566         }
1567 
1568         if (l_old->leasetime != l_new->leasetime) {
1569                 l_old->leasetime = l_new->leasetime;
1570                 update = true;
1571         }
1572 
1573         if (l_old->ipaddr != l_new->ipaddr) {
1574                 l_old->ipaddr = l_new->ipaddr;
1575                 lease_delete_assignments(l_old, false);
1576         }
1577 
1578         if (l_old->hostid != l_new->hostid) {
1579                 l_old->hostid = l_new->hostid;
1580                 lease_delete_assignments(l_old, true);
1581         }
1582 
1583         if (update)
1584                 lease_update_assignments(l_old);
1585 
1586         free_lease(l_new);
1587 }
1588 
1589 static void lease_delete(struct lease *l)
1590 {
1591         struct dhcp_assignment *a, *tmp;
1592 
1593         list_for_each_entry_safe(a, tmp, &l->assignments, lease_list)
1594                 free_assignment(a);
1595 
1596         free_lease(l);
1597 }
1598 
1599 static void lease_update(_unused struct vlist_tree *tree, struct vlist_node *node_new,
1600                          struct vlist_node *node_old)
1601 {
1602         struct lease *lease_new = container_of(node_new, struct lease, node);
1603         struct lease *lease_old = container_of(node_old, struct lease, node);
1604 
1605         if (node_old && node_new)
1606                 lease_change_config(lease_old, lease_new);
1607         else if (node_old)
1608                 lease_delete(lease_old);
1609 }
1610 
1611 struct lease *config_find_lease_by_duid(const uint8_t *duid, const uint16_t len)
1612 {
1613         struct lease *l;
1614 
1615         vlist_for_each_element(&leases, l, node) {
1616                 if (l->duid_len == len && !memcmp(l->duid, duid, len))
1617                         return l;
1618         }
1619 
1620         return NULL;
1621 }
1622 
1623 struct lease *config_find_lease_by_mac(const uint8_t *mac)
1624 {
1625         struct lease *l;
1626 
1627         vlist_for_each_element(&leases, l, node) {
1628                 for (size_t i = 0; i < l->mac_count; i++) {
1629                         if (!memcmp(l->macs[i].ether_addr_octet, mac,
1630                                     sizeof(l->macs[i].ether_addr_octet)))
1631                                 return l;
1632                 }
1633         }
1634 
1635         return NULL;
1636 }
1637 
1638 struct lease *config_find_lease_by_hostid(const uint64_t hostid)
1639 {
1640         struct lease *l;
1641 
1642         vlist_for_each_element(&leases, l, node) {
1643                 if (l->hostid == hostid)
1644                         return l;
1645         }
1646 
1647         return NULL;
1648 }
1649 
1650 struct lease *config_find_lease_by_ipaddr(const uint32_t ipaddr)
1651 {
1652         struct lease *l;
1653 
1654         vlist_for_each_element(&leases, l, node) {
1655                 if (l->ipaddr == ipaddr)
1656                         return l;
1657         }
1658 
1659         return NULL;
1660 }
1661 
1662 void reload_services(struct interface *iface)
1663 {
1664         if (iface->ifflags & IFF_RUNNING) {
1665                 syslog(LOG_DEBUG, "Enabling services with %s running", iface->ifname);
1666                 router_setup_interface(iface, iface->ra != MODE_DISABLED);
1667                 dhcpv6_setup_interface(iface, iface->dhcpv6 != MODE_DISABLED);
1668                 ndp_setup_interface(iface, iface->ndp != MODE_DISABLED);
1669 #ifdef DHCPV4_SUPPORT
1670                 dhcpv4_setup_interface(iface, iface->dhcpv4 != MODE_DISABLED);
1671 #endif
1672         } else {
1673                 syslog(LOG_DEBUG, "Disabling services with %s not running", iface->ifname);
1674                 router_setup_interface(iface, false);
1675                 dhcpv6_setup_interface(iface, false);
1676                 ndp_setup_interface(iface, false);
1677 #ifdef DHCPV4_SUPPORT
1678                 dhcpv4_setup_interface(iface, false);
1679 #endif
1680         }
1681 }
1682 
1683 static int ipv6_pxe_from_uci(struct uci_section* s)
1684 {
1685         blob_buf_init(&b, 0);
1686         uci_to_blob(&b, s, &ipv6_pxe_attr_list);
1687 
1688         void* data = blob_data(b.head);
1689         size_t len = blob_len(b.head);
1690 
1691         struct blob_attr* tb[IFACE_ATTR_MAX];
1692         blobmsg_parse(ipv6_pxe_attrs, IPV6_PXE_MAX, tb, data, len);
1693 
1694         if (!tb[IPV6_PXE_URL])
1695                 return -1;
1696 
1697         const char* url = blobmsg_get_string(tb[IPV6_PXE_URL]);
1698 
1699         uint32_t arch = 0xFFFFFFFF;
1700         if (tb[IPV6_PXE_ARCH])
1701                 arch = blobmsg_get_u32(tb[IPV6_PXE_ARCH]);
1702 
1703         return ipv6_pxe_entry_new(arch, url) ? -1 : 0;
1704 }
1705 
1706 void odhcpd_reload(void)
1707 {
1708         struct uci_context *uci = uci_alloc_context();
1709         struct interface *master = NULL, *i, *tmp;
1710 
1711         if (!uci)
1712                 return;
1713 
1714         vlist_update(&leases);
1715         avl_for_each_element(&interfaces, i, avl)
1716                 clean_interface(i);
1717 
1718         struct uci_package *dhcp = NULL;
1719         if (!uci_load(uci, "dhcp", &dhcp)) {
1720                 struct uci_element *e;
1721 
1722                 /* 1. Global settings */
1723                 uci_foreach_element(&dhcp->sections, e) {
1724                         struct uci_section *s = uci_to_section(e);
1725                         if (!strcmp(s->type, "odhcpd"))
1726                                 set_config(s);
1727                 }
1728 
1729                 /* 2. DHCP pools */
1730                 uci_foreach_element(&dhcp->sections, e) {
1731                         struct uci_section *s = uci_to_section(e);
1732                         if (!strcmp(s->type, "dhcp"))
1733                                 set_interface(s);
1734                 }
1735 
1736                 /* 3. Static leases */
1737                 uci_foreach_element(&dhcp->sections, e) {
1738                         struct uci_section* s = uci_to_section(e);
1739                         if (!strcmp(s->type, "host"))
1740                                 set_lease_from_uci(s);
1741                 }
1742 
1743                 /* 4. IPv6 PxE */
1744                 ipv6_pxe_clear();
1745                 uci_foreach_element(&dhcp->sections, e) {
1746                         struct uci_section* s = uci_to_section(e);
1747                         if (!strcmp(s->type, "boot6"))
1748                                 ipv6_pxe_from_uci(s);
1749                 }
1750                 ipv6_pxe_dump();
1751         }
1752 
1753         if (config.dhcp_statefile) {
1754                 char *path = strdup(config.dhcp_statefile);
1755 
1756                 mkdir_p(dirname(path), 0755);
1757                 free(path);
1758         }
1759 
1760         vlist_flush(&leases);
1761 
1762 #ifdef WITH_UBUS
1763         ubus_apply_network();
1764 #endif
1765 
1766         bool any_dhcpv6_slave = false, any_ra_slave = false, any_ndp_slave = false;
1767 
1768         /* Test for */
1769         avl_for_each_element(&interfaces, i, avl) {
1770                 if (i->master)
1771                         continue;
1772 
1773                 if (i->dhcpv6 == MODE_HYBRID || i->dhcpv6 == MODE_RELAY)
1774                         any_dhcpv6_slave = true;
1775 
1776                 if (i->ra == MODE_HYBRID || i->ra == MODE_RELAY)
1777                         any_ra_slave = true;
1778 
1779                 if (i->ndp == MODE_HYBRID || i->ndp == MODE_RELAY)
1780                         any_ndp_slave = true;
1781         }
1782 
1783         /* Evaluate hybrid mode for master */
1784         avl_for_each_element(&interfaces, i, avl) {
1785                 if (!i->master)
1786                         continue;
1787 
1788                 enum odhcpd_mode hybrid_mode = MODE_DISABLED;
1789 #ifdef WITH_UBUS
1790                 if (!ubus_has_prefix(i->name, i->ifname))
1791                         hybrid_mode = MODE_RELAY;
1792 #endif
1793 
1794                 if (i->dhcpv6 == MODE_HYBRID)
1795                         i->dhcpv6 = hybrid_mode;
1796 
1797                 if (i->dhcpv6 == MODE_RELAY && !any_dhcpv6_slave)
1798                         i->dhcpv6 = MODE_DISABLED;
1799 
1800                 if (i->ra == MODE_HYBRID)
1801                         i->ra = hybrid_mode;
1802 
1803                 if (i->ra == MODE_RELAY && !any_ra_slave)
1804                         i->ra = MODE_DISABLED;
1805 
1806                 if (i->ndp == MODE_HYBRID)
1807                         i->ndp = hybrid_mode;
1808 
1809                 if (i->ndp == MODE_RELAY && !any_ndp_slave)
1810                         i->ndp = MODE_DISABLED;
1811 
1812                 if (i->dhcpv6 == MODE_RELAY || i->ra == MODE_RELAY || i->ndp == MODE_RELAY)
1813                         master = i;
1814         }
1815 
1816 
1817         avl_for_each_element_safe(&interfaces, i, avl, tmp) {
1818                 if (i->inuse && i->ifflags & IFF_RUNNING) {
1819                         /* Resolve hybrid mode */
1820                         if (i->dhcpv6 == MODE_HYBRID)
1821                                 i->dhcpv6 = (master && master->dhcpv6 == MODE_RELAY) ?
1822                                                 MODE_RELAY : MODE_SERVER;
1823 
1824                         if (i->ra == MODE_HYBRID)
1825                                 i->ra = (master && master->ra == MODE_RELAY) ?
1826                                                 MODE_RELAY : MODE_SERVER;
1827 
1828                         if (i->ndp == MODE_HYBRID)
1829                                 i->ndp = (master && master->ndp == MODE_RELAY) ?
1830                                                 MODE_RELAY : MODE_DISABLED;
1831 
1832                         reload_services(i);
1833                 } else
1834                         close_interface(i);
1835         }
1836 
1837         uci_unload(uci, dhcp);
1838         uci_free_context(uci);
1839 }
1840 
1841 static void handle_signal(int signal)
1842 {
1843         char b[1] = {0};
1844 
1845         if (signal == SIGHUP) {
1846                 if (write(reload_pipe[1], b, sizeof(b)) < 0) {}
1847         } else
1848                 uloop_end();
1849 }
1850 
1851 static void reload_cb(struct uloop_fd *u, _unused unsigned int events)
1852 {
1853         char b[512];
1854         if (read(u->fd, b, sizeof(b)) < 0) {}
1855 
1856         odhcpd_reload();
1857 }
1858 
1859 static struct uloop_fd reload_fd = { .fd = -1, .cb = reload_cb };
1860 
1861 void odhcpd_run(void)
1862 {
1863         if (pipe2(reload_pipe, O_NONBLOCK | O_CLOEXEC) < 0) {}
1864 
1865         reload_fd.fd = reload_pipe[0];
1866         uloop_fd_add(&reload_fd, ULOOP_READ);
1867 
1868         signal(SIGTERM, handle_signal);
1869         signal(SIGINT, handle_signal);
1870         signal(SIGHUP, handle_signal);
1871 
1872 #ifdef WITH_UBUS
1873         while (ubus_init())
1874                 sleep(1);
1875 #endif
1876 
1877         odhcpd_reload();
1878         uloop_run();
1879 }
1880 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt