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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt