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