1 #include <errno.h> 2 #include <fcntl.h> 3 #include <resolv.h> 4 #include <signal.h> 5 #include <arpa/inet.h> 6 #include <unistd.h> 7 #include <libgen.h> 8 #include <net/if.h> 9 #include <string.h> 10 #include <sys/stat.h> 11 #include <ctype.h> 12 13 #include <uci.h> 14 #include <uci_blob.h> 15 #include <json-c/json.h> 16 #include <libubox/utils.h> 17 #include <libubox/avl.h> 18 #include <libubox/avl-cmp.h> 19 #include <libubox/list.h> 20 #include <libubox/vlist.h> 21 22 #include "odhcpd.h" 23 #include "router.h" 24 #include "dhcpv6-pxe.h" 25 26 static struct blob_buf b; 27 static int reload_pipe[2] = { -1, -1 }; 28 29 static int lease_cfg_cmp(const void *k1, const void *k2, void *ptr); 30 static void lease_cfg_update(struct vlist_tree *tree, struct vlist_node *node_new, 31 struct vlist_node *node_old); 32 33 struct vlist_tree lease_cfgs = VLIST_TREE_INIT(lease_cfgs, lease_cfg_cmp, 34 lease_cfg_update, true, false); 35 36 AVL_TREE(interfaces, avl_strcmp, false, NULL); 37 struct config config = { 38 .enable_tz = true, 39 .main_dhcpv4 = false, 40 .dhcp_cb = NULL, 41 .dhcp_statefile = NULL, 42 .dhcp_hostsfile = NULL, 43 .ra_piofolder = NULL, 44 .ra_piofolder_fd = -1, 45 .uci_cfgdir = NULL, 46 .log_level = LOG_WARNING, 47 .log_level_cmdline = false, 48 .log_syslog = true, 49 .default_duid = { 0 }, 50 .default_duid_len = 0, 51 }; 52 53 struct sys_conf sys_conf = { 54 .posix_tz = NULL, // "timezone" 55 .posix_tz_len = 0, 56 .tzdb_tz = NULL, // "zonename" 57 .tzdb_tz_len = 0, 58 }; 59 60 #define START_DEFAULT 100 61 #define LIMIT_DEFAULT 150 62 63 #define HOSTID_LEN_MIN 12 64 #define HOSTID_LEN_MAX 64 65 #define HOSTID_LEN_DEFAULT HOSTID_LEN_MIN 66 67 #define PD_MIN_LEN_MAX (64-2) // must delegate at least 2 bits of prefix 68 69 #define OAF_DHCPV6 (OAF_DHCPV6_NA | OAF_DHCPV6_PD) 70 71 enum { 72 IPV6_PXE_URL, 73 IPV6_PXE_ARCH, 74 IPV6_PXE_MAX 75 }; 76 77 static const struct blobmsg_policy ipv6_pxe_attrs[IPV6_PXE_MAX] = { 78 [IPV6_PXE_URL] = {.name = "url", .type = BLOBMSG_TYPE_STRING }, 79 [IPV6_PXE_ARCH] = {.name = "arch", .type = BLOBMSG_TYPE_INT32 }, 80 }; 81 82 const struct uci_blob_param_list ipv6_pxe_attr_list = { 83 .n_params = IPV6_PXE_MAX, 84 .params = ipv6_pxe_attrs, 85 }; 86 87 enum { 88 IFACE_ATTR_INTERFACE, 89 IFACE_ATTR_IFNAME, 90 IFACE_ATTR_NETWORKID, 91 IFACE_ATTR_DYNAMICDHCP, 92 IFACE_ATTR_LEASETIME, 93 IFACE_ATTR_LIMIT, 94 IFACE_ATTR_START, 95 IFACE_ATTR_MASTER, 96 IFACE_ATTR_UPSTREAM, 97 IFACE_ATTR_RA, 98 IFACE_ATTR_DHCPV4, 99 IFACE_ATTR_DHCPV6, 100 IFACE_ATTR_NDP, 101 IFACE_ATTR_ROUTER, 102 IFACE_ATTR_DNS, 103 IFACE_ATTR_DNR, 104 IFACE_ATTR_DNS_SERVICE, 105 IFACE_ATTR_DOMAIN, 106 IFACE_ATTR_DHCPV4_FORCERECONF, 107 IFACE_ATTR_DHCPV6_RAW, 108 IFACE_ATTR_DHCPV6_ASSIGNALL, 109 IFACE_ATTR_DHCPV6_PD, 110 IFACE_ATTR_DHCPV6_PD_MIN_LEN, 111 IFACE_ATTR_DHCPV6_NA, 112 IFACE_ATTR_DHCPV6_HOSTID_LEN, 113 IFACE_ATTR_RA_DEFAULT, 114 IFACE_ATTR_RA_FLAGS, 115 IFACE_ATTR_RA_SLAAC, 116 IFACE_ATTR_RA_OFFLINK, 117 IFACE_ATTR_RA_PREFERENCE, 118 IFACE_ATTR_RA_ADVROUTER, 119 IFACE_ATTR_RA_MININTERVAL, 120 IFACE_ATTR_RA_MAXINTERVAL, 121 IFACE_ATTR_RA_LIFETIME, 122 IFACE_ATTR_RA_REACHABLETIME, 123 IFACE_ATTR_RA_RETRANSTIME, 124 IFACE_ATTR_RA_HOPLIMIT, 125 IFACE_ATTR_RA_MTU, 126 IFACE_ATTR_RA_DNS, 127 IFACE_ATTR_RA_PREF64, 128 IFACE_ATTR_NDPROXY_ROUTING, 129 IFACE_ATTR_NDPROXY_SLAVE, 130 IFACE_ATTR_NDP_FROM_LINK_LOCAL, 131 IFACE_ATTR_PREFIX_FILTER, 132 IFACE_ATTR_MAX_PREFERRED_LIFETIME, 133 IFACE_ATTR_MAX_VALID_LIFETIME, 134 IFACE_ATTR_NTP, 135 IFACE_ATTR_MAX 136 }; 137 138 static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = { 139 [IFACE_ATTR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING }, 140 [IFACE_ATTR_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, 141 [IFACE_ATTR_NETWORKID] = { .name = "networkid", .type = BLOBMSG_TYPE_STRING }, 142 [IFACE_ATTR_DYNAMICDHCP] = { .name = "dynamicdhcp", .type = BLOBMSG_TYPE_BOOL }, 143 [IFACE_ATTR_LEASETIME] = { .name = "leasetime", .type = BLOBMSG_TYPE_STRING }, 144 [IFACE_ATTR_START] = { .name = "start", .type = BLOBMSG_TYPE_INT32 }, 145 [IFACE_ATTR_LIMIT] = { .name = "limit", .type = BLOBMSG_TYPE_INT32 }, 146 [IFACE_ATTR_MASTER] = { .name = "master", .type = BLOBMSG_TYPE_BOOL }, 147 [IFACE_ATTR_UPSTREAM] = { .name = "upstream", .type = BLOBMSG_TYPE_ARRAY }, 148 [IFACE_ATTR_RA] = { .name = "ra", .type = BLOBMSG_TYPE_STRING }, 149 [IFACE_ATTR_DHCPV4] = { .name = "dhcpv4", .type = BLOBMSG_TYPE_STRING }, 150 [IFACE_ATTR_DHCPV6] = { .name = "dhcpv6", .type = BLOBMSG_TYPE_STRING }, 151 [IFACE_ATTR_NDP] = { .name = "ndp", .type = BLOBMSG_TYPE_STRING }, 152 [IFACE_ATTR_ROUTER] = { .name = "router", .type = BLOBMSG_TYPE_ARRAY }, 153 [IFACE_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY }, 154 [IFACE_ATTR_DNR] = { .name = "dnr", .type = BLOBMSG_TYPE_ARRAY }, 155 [IFACE_ATTR_DNS_SERVICE] = { .name = "dns_service", .type = BLOBMSG_TYPE_BOOL }, 156 [IFACE_ATTR_DOMAIN] = { .name = "domain", .type = BLOBMSG_TYPE_ARRAY }, 157 [IFACE_ATTR_DHCPV4_FORCERECONF] = { .name = "dhcpv4_forcereconf", .type = BLOBMSG_TYPE_BOOL }, 158 [IFACE_ATTR_DHCPV6_RAW] = { .name = "dhcpv6_raw", .type = BLOBMSG_TYPE_STRING }, 159 [IFACE_ATTR_DHCPV6_ASSIGNALL] = { .name ="dhcpv6_assignall", .type = BLOBMSG_TYPE_BOOL }, 160 [IFACE_ATTR_DHCPV6_PD] = { .name = "dhcpv6_pd", .type = BLOBMSG_TYPE_BOOL }, 161 [IFACE_ATTR_DHCPV6_PD_MIN_LEN] = { .name = "dhcpv6_pd_min_len", .type = BLOBMSG_TYPE_INT32 }, 162 [IFACE_ATTR_DHCPV6_NA] = { .name = "dhcpv6_na", .type = BLOBMSG_TYPE_BOOL }, 163 [IFACE_ATTR_DHCPV6_HOSTID_LEN] = { .name = "dhcpv6_hostidlength", .type = BLOBMSG_TYPE_INT32 }, 164 [IFACE_ATTR_RA_DEFAULT] = { .name = "ra_default", .type = BLOBMSG_TYPE_INT32 }, 165 [IFACE_ATTR_RA_FLAGS] = { .name = "ra_flags", . type = BLOBMSG_TYPE_ARRAY }, 166 [IFACE_ATTR_RA_SLAAC] = { .name = "ra_slaac", .type = BLOBMSG_TYPE_BOOL }, 167 [IFACE_ATTR_RA_OFFLINK] = { .name = "ra_offlink", .type = BLOBMSG_TYPE_BOOL }, 168 [IFACE_ATTR_RA_PREFERENCE] = { .name = "ra_preference", .type = BLOBMSG_TYPE_STRING }, 169 [IFACE_ATTR_RA_ADVROUTER] = { .name = "ra_advrouter", .type = BLOBMSG_TYPE_BOOL }, 170 [IFACE_ATTR_RA_MININTERVAL] = { .name = "ra_mininterval", .type = BLOBMSG_TYPE_INT32 }, 171 [IFACE_ATTR_RA_MAXINTERVAL] = { .name = "ra_maxinterval", .type = BLOBMSG_TYPE_INT32 }, 172 [IFACE_ATTR_RA_LIFETIME] = { .name = "ra_lifetime", .type = BLOBMSG_TYPE_INT32 }, 173 [IFACE_ATTR_RA_REACHABLETIME] = { .name = "ra_reachabletime", .type = BLOBMSG_TYPE_INT32 }, 174 [IFACE_ATTR_RA_RETRANSTIME] = { .name = "ra_retranstime", .type = BLOBMSG_TYPE_INT32 }, 175 [IFACE_ATTR_RA_HOPLIMIT] = { .name = "ra_hoplimit", .type = BLOBMSG_TYPE_INT32 }, 176 [IFACE_ATTR_RA_MTU] = { .name = "ra_mtu", .type = BLOBMSG_TYPE_INT32 }, 177 [IFACE_ATTR_RA_DNS] = { .name = "ra_dns", .type = BLOBMSG_TYPE_BOOL }, 178 [IFACE_ATTR_RA_PREF64] = { .name = "ra_pref64", .type = BLOBMSG_TYPE_STRING }, 179 [IFACE_ATTR_NDPROXY_ROUTING] = { .name = "ndproxy_routing", .type = BLOBMSG_TYPE_BOOL }, 180 [IFACE_ATTR_NDPROXY_SLAVE] = { .name = "ndproxy_slave", .type = BLOBMSG_TYPE_BOOL }, 181 [IFACE_ATTR_NDP_FROM_LINK_LOCAL] = { .name = "ndp_from_link_local", .type = BLOBMSG_TYPE_BOOL }, 182 [IFACE_ATTR_PREFIX_FILTER] = { .name = "prefix_filter", .type = BLOBMSG_TYPE_STRING }, 183 [IFACE_ATTR_MAX_PREFERRED_LIFETIME] = { .name = "max_preferred_lifetime", .type = BLOBMSG_TYPE_STRING }, 184 [IFACE_ATTR_MAX_VALID_LIFETIME] = { .name = "max_valid_lifetime", .type = BLOBMSG_TYPE_STRING }, 185 [IFACE_ATTR_NTP] = { .name = "ntp", .type = BLOBMSG_TYPE_ARRAY }, 186 }; 187 188 const struct uci_blob_param_list interface_attr_list = { 189 .n_params = IFACE_ATTR_MAX, 190 .params = iface_attrs, 191 }; 192 193 const struct blobmsg_policy lease_cfg_attrs[LEASE_CFG_ATTR_MAX] = { 194 [LEASE_CFG_ATTR_IP] = { .name = "ip", .type = BLOBMSG_TYPE_STRING }, 195 [LEASE_CFG_ATTR_MAC] = { .name = "mac", .type = BLOBMSG_TYPE_ARRAY }, 196 [LEASE_CFG_ATTR_DUID] = { .name = "duid", .type = BLOBMSG_TYPE_ARRAY }, 197 [LEASE_CFG_ATTR_HOSTID] = { .name = "hostid", .type = BLOBMSG_TYPE_STRING }, 198 [LEASE_CFG_ATTR_LEASETIME] = { .name = "leasetime", .type = BLOBMSG_TYPE_STRING }, 199 [LEASE_CFG_ATTR_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING }, 200 }; 201 202 const struct uci_blob_param_list lease_cfg_attr_list = { 203 .n_params = LEASE_CFG_ATTR_MAX, 204 .params = lease_cfg_attrs, 205 }; 206 207 enum { 208 ODHCPD_ATTR_MAINDHCP, 209 ODHCPD_ATTR_LEASEFILE, 210 ODHCPD_ATTR_LEASETRIGGER, 211 ODHCPD_ATTR_LOGLEVEL, 212 ODHCPD_ATTR_HOSTSFILE, 213 ODHCPD_ATTR_PIOFOLDER, 214 ODHCPD_ATTR_ENABLE_TZ, 215 ODHCPD_ATTR_MAX 216 }; 217 218 static const struct blobmsg_policy odhcpd_attrs[ODHCPD_ATTR_MAX] = { 219 [ODHCPD_ATTR_MAINDHCP] = { .name = "maindhcp", .type = BLOBMSG_TYPE_BOOL }, 220 [ODHCPD_ATTR_LEASEFILE] = { .name = "leasefile", .type = BLOBMSG_TYPE_STRING }, 221 [ODHCPD_ATTR_LEASETRIGGER] = { .name = "leasetrigger", .type = BLOBMSG_TYPE_STRING }, 222 [ODHCPD_ATTR_LOGLEVEL] = { .name = "loglevel", .type = BLOBMSG_TYPE_INT32 }, 223 [ODHCPD_ATTR_HOSTSFILE] = { .name = "hostsfile", .type = BLOBMSG_TYPE_STRING }, 224 [ODHCPD_ATTR_PIOFOLDER] = { .name = "piofolder", .type = BLOBMSG_TYPE_STRING }, 225 [ODHCPD_ATTR_ENABLE_TZ] = { .name = "enable_tz", .type = BLOBMSG_TYPE_BOOL }, 226 }; 227 228 const struct uci_blob_param_list odhcpd_attr_list = { 229 .n_params = ODHCPD_ATTR_MAX, 230 .params = odhcpd_attrs, 231 }; 232 233 enum { 234 SYSTEM_ATTR_TIMEZONE, 235 SYSTEM_ATTR_ZONENAME, 236 SYSTEM_ATTR_MAX 237 }; 238 239 static const struct blobmsg_policy system_attrs[SYSTEM_ATTR_MAX] = { 240 [SYSTEM_ATTR_TIMEZONE] = { .name = "timezone", .type = BLOBMSG_TYPE_STRING }, 241 [SYSTEM_ATTR_ZONENAME] = { .name = "zonename", .type = BLOBMSG_TYPE_STRING }, 242 }; 243 244 const struct uci_blob_param_list system_attr_list = { 245 .n_params = SYSTEM_ATTR_MAX, 246 .params = system_attrs, 247 }; 248 249 enum { 250 GLOBAL_ATTR_DUID, 251 GLOBAL_ATTR_MAX 252 }; 253 254 static const struct blobmsg_policy global_attrs[GLOBAL_ATTR_MAX] = { 255 [GLOBAL_ATTR_DUID] = { .name = "dhcp_default_duid", .type = BLOBMSG_TYPE_STRING }, 256 }; 257 258 const struct uci_blob_param_list global_attr_list = { 259 .n_params = GLOBAL_ATTR_MAX, 260 .params = global_attrs, 261 }; 262 263 static const struct { const char *name; uint8_t flag; } ra_flags[] = { 264 { .name = "managed-config", .flag = ND_RA_FLAG_MANAGED }, 265 { .name = "other-config", .flag = ND_RA_FLAG_OTHER }, 266 { .name = "home-agent", .flag = ND_RA_FLAG_HOME_AGENT }, 267 { .name = "none", . flag = 0 }, 268 { .name = NULL, }, 269 }; 270 271 // https://www.iana.org/assignments/dns-svcb/dns-svcb.xhtml 272 enum svc_param_keys { 273 DNR_SVC_MANDATORY, 274 DNR_SVC_ALPN, 275 DNR_SVC_NO_DEFAULT_ALPN, 276 DNR_SVC_PORT, 277 DNR_SVC_IPV4HINT, 278 DNR_SVC_ECH, 279 DNR_SVC_IPV6HINT, 280 DNR_SVC_DOHPATH, 281 DNR_SVC_OHTTP, 282 DNR_SVC_MAX, 283 }; 284 285 static const char *svc_param_key_names[DNR_SVC_MAX] = { 286 [DNR_SVC_MANDATORY] = "mandatory", 287 [DNR_SVC_ALPN] = "alpn", 288 [DNR_SVC_NO_DEFAULT_ALPN] = "no-default-alpn", 289 [DNR_SVC_PORT] = "port", 290 [DNR_SVC_IPV4HINT] = "ipv4hint", 291 [DNR_SVC_ECH] = "ech", 292 [DNR_SVC_IPV6HINT] = "ipv6hint", 293 [DNR_SVC_DOHPATH] = "dohpath", 294 [DNR_SVC_OHTTP] = "ohttp", 295 }; 296 297 static void set_interface_defaults(struct interface *iface) 298 { 299 iface->ignore = true; 300 iface->dhcpv4 = MODE_DISABLED; 301 iface->dhcpv6 = MODE_DISABLED; 302 iface->ra = MODE_DISABLED; 303 iface->ndp = MODE_DISABLED; 304 iface->learn_routes = 1; 305 iface->ndp_from_link_local = true; 306 iface->cached_linklocal_valid = false; 307 iface->dhcp_leasetime = 43200; 308 iface->max_preferred_lifetime = ND_PREFERRED_LIMIT; 309 iface->max_valid_lifetime = ND_VALID_LIMIT; 310 iface->dhcpv4_start.s_addr = htonl(START_DEFAULT); 311 iface->dhcpv4_end.s_addr = htonl(START_DEFAULT + LIMIT_DEFAULT - 1); 312 iface->dhcpv6_assignall = true; 313 iface->dhcpv6_pd = true; 314 iface->dhcpv6_pd_min_len = 0; 315 iface->dhcpv6_na = true; 316 iface->dhcpv6_hostid_len = HOSTID_LEN_DEFAULT; 317 iface->dns_service = true; 318 iface->ra_flags = ND_RA_FLAG_OTHER; 319 iface->ra_slaac = true; 320 iface->ra_maxinterval = 600; 321 /* 322 * RFC4861: MinRtrAdvInterval: Default: 0.33 * MaxRtrAdvInterval If 323 * MaxRtrAdvInterval >= 9 seconds; otherwise, the Default is MaxRtrAdvInterval. 324 */ 325 iface->ra_mininterval = iface->ra_maxinterval/3; 326 iface->ra_lifetime = 3 * iface->ra_maxinterval; /* RFC4861: AdvDefaultLifetime: Default: 3 * MaxRtrAdvInterval */ 327 iface->ra_dns = true; 328 iface->pio_update = false; 329 iface->update_statefile = true; 330 } 331 332 static void clean_interface(struct interface *iface) 333 { 334 free(iface->dns); 335 free(iface->search); 336 free(iface->upstream); 337 free(iface->dhcpv4_router); 338 free(iface->dhcpv4_dns); 339 free(iface->dhcpv6_raw); 340 free(iface->dhcpv4_ntp); 341 free(iface->dhcpv6_ntp); 342 free(iface->dhcpv6_sntp); 343 for (unsigned i = 0; i < iface->dnr_cnt; i++) { 344 free(iface->dnr[i].adn); 345 free(iface->dnr[i].addr4); 346 free(iface->dnr[i].addr6); 347 free(iface->dnr[i].svc); 348 } 349 free(iface->dnr); 350 memset(&iface->ra, 0, sizeof(*iface) - offsetof(struct interface, ra)); 351 set_interface_defaults(iface); 352 } 353 354 static void close_interface(struct interface *iface) 355 { 356 avl_delete(&interfaces, &iface->avl); 357 358 router_setup_interface(iface, false); 359 dhcpv6_setup_interface(iface, false); 360 ndp_setup_interface(iface, false); 361 #ifdef DHCPV4_SUPPORT 362 dhcpv4_setup_interface(iface, false); 363 #endif 364 365 /* make sure timer is not on the timeouts list before freeing */ 366 uloop_timeout_cancel(&iface->timer_rs); 367 368 clean_interface(iface); 369 free(iface->addr4); 370 free(iface->addr6); 371 free(iface->pios); 372 free(iface->ifname); 373 free(iface); 374 } 375 376 static int parse_mode(const char *mode) 377 { 378 if (!strcmp(mode, "disabled")) 379 return MODE_DISABLED; 380 else if (!strcmp(mode, "server")) 381 return MODE_SERVER; 382 else if (!strcmp(mode, "relay")) 383 return MODE_RELAY; 384 else if (!strcmp(mode, "hybrid")) 385 return MODE_HYBRID; 386 else 387 return -1; 388 } 389 390 static int parse_ra_flags(uint8_t *flags, struct blob_attr *attr) 391 { 392 struct blob_attr *cur; 393 unsigned rem; 394 395 blobmsg_for_each_attr(cur, attr, rem) { 396 int i; 397 398 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) 399 continue; 400 401 if (!blobmsg_check_attr(cur, false)) 402 continue; 403 404 for (i = 0; ra_flags[i].name; i++) { 405 if (!strcmp(ra_flags[i].name, blobmsg_get_string(cur))) { 406 *flags |= ra_flags[i].flag; 407 break; 408 } 409 } 410 411 if (!ra_flags[i].name) 412 return -1; 413 } 414 415 return 0; 416 } 417 418 static void set_global_config(struct uci_section *s) 419 { 420 struct blob_attr *tb[GLOBAL_ATTR_MAX], *c; 421 422 blob_buf_init(&b, 0); 423 uci_to_blob(&b, s, &global_attr_list); 424 blobmsg_parse(global_attrs, GLOBAL_ATTR_MAX, tb, blob_data(b.head), blob_len(b.head)); 425 426 if ((c = tb[GLOBAL_ATTR_DUID])) { 427 size_t len = blobmsg_data_len(c) / 2; 428 429 config.default_duid_len = 0; 430 if (len >= DUID_MIN_LEN && len <= DUID_MAX_LEN) { 431 ssize_t r = odhcpd_unhexlify(config.default_duid, len, blobmsg_get_string(c)); 432 if (r >= DUID_MIN_LEN) 433 config.default_duid_len = r; 434 } 435 } 436 } 437 438 static void set_config(struct uci_section *s) 439 { 440 struct blob_attr *tb[ODHCPD_ATTR_MAX], *c; 441 442 blob_buf_init(&b, 0); 443 uci_to_blob(&b, s, &odhcpd_attr_list); 444 blobmsg_parse(odhcpd_attrs, ODHCPD_ATTR_MAX, tb, blob_data(b.head), blob_len(b.head)); 445 446 if ((c = tb[ODHCPD_ATTR_MAINDHCP])) 447 config.main_dhcpv4 = blobmsg_get_bool(c); 448 449 if ((c = tb[ODHCPD_ATTR_LEASEFILE])) { 450 free(config.dhcp_statefile); 451 config.dhcp_statefile = strdup(blobmsg_get_string(c)); 452 } 453 454 if ((c = tb[ODHCPD_ATTR_HOSTSFILE])) { 455 free(config.dhcp_hostsfile); 456 config.dhcp_hostsfile = strdup(blobmsg_get_string(c)); 457 } 458 459 if ((c = tb[ODHCPD_ATTR_PIOFOLDER])) { 460 free(config.ra_piofolder); 461 config.ra_piofolder = strdup(blobmsg_get_string(c)); 462 } 463 464 if ((c = tb[ODHCPD_ATTR_LEASETRIGGER])) { 465 free(config.dhcp_cb); 466 config.dhcp_cb = strdup(blobmsg_get_string(c)); 467 } 468 469 if ((c = tb[ODHCPD_ATTR_LOGLEVEL])) { 470 int log_level = (blobmsg_get_u32(c) & LOG_PRIMASK); 471 472 if (config.log_level != log_level && !config.log_level_cmdline) { 473 config.log_level = log_level; 474 if (config.log_syslog) 475 setlogmask(LOG_UPTO(config.log_level)); 476 notice("Log level set to %d\n", config.log_level); 477 } 478 } 479 480 if ((c = tb[ODHCPD_ATTR_ENABLE_TZ])) 481 config.enable_tz = blobmsg_get_bool(c); 482 483 } 484 485 static void sanitize_tz_string(const char *src, uint8_t **dst, size_t *dst_len) 486 { 487 /* replace any spaces with '_' in tz strings. luci, where these strings 488 are normally set, (had a bug that) replaced underscores for spaces in the 489 names. */ 490 491 if (!dst || !dst_len) 492 return; 493 494 free(*dst); 495 *dst = NULL; 496 *dst_len = 0; 497 498 if (!src || !*src) 499 return; 500 501 char *copy = strdup(src); 502 if (!copy) 503 return; 504 505 for (char *p = copy; *p; p++) { 506 if (isspace((unsigned char)*p)) 507 *p = '_'; 508 } 509 510 *dst = (uint8_t *)copy; 511 *dst_len = strlen(copy); 512 } 513 514 static void set_timezone_info_from_uci(struct uci_section *s) 515 { 516 struct blob_attr *tb[SYSTEM_ATTR_MAX], *c; 517 518 blob_buf_init(&b, 0); 519 uci_to_blob(&b, s, &system_attr_list); 520 blobmsg_parse(system_attrs, SYSTEM_ATTR_MAX, tb, blob_data(b.head), blob_len(b.head)); 521 522 if ((c = tb[SYSTEM_ATTR_TIMEZONE])) 523 sanitize_tz_string(blobmsg_get_string(c), &sys_conf.posix_tz, &sys_conf.posix_tz_len); 524 525 if ((c = tb[SYSTEM_ATTR_ZONENAME])) 526 sanitize_tz_string(blobmsg_get_string(c), &sys_conf.tzdb_tz, &sys_conf.tzdb_tz_len); 527 } 528 529 static uint32_t parse_leasetime(struct blob_attr *c) { 530 char *val = blobmsg_get_string(c), *endptr = NULL; 531 uint32_t time = strcmp(val, "infinite") ? (uint32_t)strtod(val, &endptr) : UINT32_MAX; 532 533 if (time && endptr && endptr[0]) { 534 switch(endptr[0]) { 535 case 's': break; /* seconds */ 536 case 'm': time *= 60; break; /* minutes */ 537 case 'h': time *= 3600; break; /* hours */ 538 case 'd': time *= 24 * 3600; break; /* days */ 539 case 'w': time *= 7 * 24 * 3600; break; /* weeks */ 540 default: goto err; 541 } 542 } 543 544 if (time < 60) 545 time = 60; 546 547 return time; 548 549 err: 550 return 0; 551 } 552 553 static void free_lease_cfg(struct lease_cfg *lease_cfg) 554 { 555 if (!lease_cfg) 556 return; 557 558 free(lease_cfg->hostname); 559 free(lease_cfg); 560 } 561 562 static bool parse_duid(struct duid *duid, struct blob_attr *c) 563 { 564 const char *duid_str = blobmsg_get_string(c); 565 size_t duid_str_len = blobmsg_data_len(c) - 1; 566 ssize_t duid_len; 567 const char *iaid_str; 568 569 /* We support a hex string with either "<DUID>", or "<DUID>%<IAID>" */ 570 iaid_str = strrchr(duid_str, '%'); 571 if (iaid_str) { 572 size_t iaid_str_len = strlen(++iaid_str); 573 char *end; 574 575 /* IAID = uint32, RFC8415, §21.4, §21.5, §21.21 */ 576 if (iaid_str_len < 1 || iaid_str_len > 2 * sizeof(uint32_t)) { 577 error("Invalid IAID length '%s'", iaid_str); 578 return false; 579 } 580 581 errno = 0; 582 duid->iaid = strtoul(iaid_str, &end, 16); 583 if (errno || *end != '\0') { 584 error("Invalid IAID '%s'", iaid_str); 585 return false; 586 } 587 588 duid->iaid_set = true; 589 duid_str_len -= (iaid_str_len + 1); 590 } 591 592 if (duid_str_len < 2 || duid_str_len > DUID_MAX_LEN * 2 || duid_str_len % 2) { 593 error("Invalid DUID length '%.*s'", (int)duid_str_len, duid_str); 594 return false; 595 } 596 597 duid_len = odhcpd_unhexlify(duid->id, duid_str_len / 2, duid_str); 598 if (duid_len < 0) { 599 error("Invalid DUID '%.*s'", (int)duid_str_len, duid_str); 600 return false; 601 } 602 603 duid->len = duid_len; 604 return true; 605 } 606 607 int config_set_lease_cfg_from_blobmsg(struct blob_attr *ba) 608 { 609 struct blob_attr *tb[LEASE_CFG_ATTR_MAX], *c; 610 struct lease_cfg *lease_cfg = NULL; 611 int mac_count = 0; 612 struct ether_addr *macs; 613 int duid_count = 0; 614 struct duid *duids; 615 616 blobmsg_parse(lease_cfg_attrs, LEASE_CFG_ATTR_MAX, tb, blob_data(ba), blob_len(ba)); 617 618 if ((c = tb[LEASE_CFG_ATTR_MAC])) { 619 mac_count = blobmsg_check_array_len(c, BLOBMSG_TYPE_STRING, blob_raw_len(c)); 620 if (mac_count < 0) 621 goto err; 622 } 623 624 if ((c = tb[LEASE_CFG_ATTR_DUID])) { 625 duid_count = blobmsg_check_array_len(c, BLOBMSG_TYPE_STRING, blob_raw_len(c)); 626 if (duid_count < 0) 627 goto err; 628 } 629 630 lease_cfg = calloc_a(sizeof(*lease_cfg), 631 &macs, mac_count * sizeof(*macs), 632 &duids, duid_count * sizeof(*duids)); 633 if (!lease_cfg) 634 goto err; 635 636 if ((c = tb[LEASE_CFG_ATTR_MAC])) { 637 struct blob_attr *cur; 638 size_t rem; 639 int i = 0; 640 641 lease_cfg->mac_count = mac_count; 642 lease_cfg->macs = macs; 643 644 blobmsg_for_each_attr(cur, c, rem) 645 if (!ether_aton_r(blobmsg_get_string(cur), &lease_cfg->macs[i++])) 646 goto err; 647 } 648 649 if ((c = tb[LEASE_CFG_ATTR_DUID])) { 650 struct blob_attr *cur; 651 size_t rem; 652 unsigned i = 0; 653 654 lease_cfg->duid_count = duid_count; 655 lease_cfg->duids = duids; 656 657 blobmsg_for_each_attr(cur, c, rem) 658 if (!parse_duid(&duids[i++], cur)) 659 goto err; 660 } 661 662 if ((c = tb[LEASE_CFG_ATTR_NAME])) { 663 lease_cfg->hostname = strdup(blobmsg_get_string(c)); 664 if (!lease_cfg->hostname || !odhcpd_valid_hostname(lease_cfg->hostname)) 665 goto err; 666 } 667 668 if ((c = tb[LEASE_CFG_ATTR_IP])) 669 if (inet_pton(AF_INET, blobmsg_get_string(c), &lease_cfg->ipaddr) < 0) 670 goto err; 671 672 if ((c = tb[LEASE_CFG_ATTR_HOSTID])) { 673 errno = 0; 674 lease_cfg->hostid = strtoull(blobmsg_get_string(c), NULL, 16); 675 if (errno) 676 goto err; 677 } else { 678 uint32_t i4a = ntohl(lease_cfg->ipaddr) & 0xff; 679 lease_cfg->hostid = ((i4a / 100) << 8) | (((i4a % 100) / 10) << 4) | (i4a % 10); 680 } 681 682 if ((c = tb[LEASE_CFG_ATTR_LEASETIME])) { 683 uint32_t time = parse_leasetime(c); 684 if (time == 0) 685 goto err; 686 687 lease_cfg->leasetime = time; 688 } 689 690 INIT_LIST_HEAD(&lease_cfg->dhcpv6_leases); 691 vlist_add(&lease_cfgs, &lease_cfg->node, lease_cfg); 692 return 0; 693 694 err: 695 free_lease_cfg(lease_cfg); 696 return -1; 697 } 698 699 static int set_lease_cfg_from_uci(struct uci_section *s) 700 { 701 blob_buf_init(&b, 0); 702 uci_to_blob(&b, s, &lease_cfg_attr_list); 703 704 return config_set_lease_cfg_from_blobmsg(b.head); 705 } 706 707 /* Parse NTP Options for DHCPv6 Address */ 708 static int parse_ntp_options(uint16_t *dhcpv6_ntp_len, struct in6_addr addr6, uint8_t **dhcpv6_ntp) 709 { 710 uint16_t sub_opt = 0, sub_len = htons(IPV6_ADDR_LEN); 711 uint16_t ntp_len = IPV6_ADDR_LEN + 4; 712 uint8_t *ntp = *dhcpv6_ntp; 713 size_t pos = *dhcpv6_ntp_len; 714 715 ntp = realloc(ntp, pos + ntp_len); 716 if (!ntp) 717 return -1; 718 719 *dhcpv6_ntp = ntp; 720 721 if (IN6_IS_ADDR_MULTICAST(&addr6)) 722 sub_opt = htons(NTP_SUBOPTION_MC_ADDR); 723 else 724 sub_opt = htons(NTP_SUBOPTION_SRV_ADDR); 725 726 memcpy(ntp + pos, &sub_opt, sizeof(sub_opt)); 727 pos += sizeof(sub_opt); 728 memcpy(ntp + pos, &sub_len, sizeof(sub_len)); 729 pos += sizeof(sub_len); 730 memcpy(ntp + pos, &addr6, IPV6_ADDR_LEN); 731 732 *dhcpv6_ntp_len += ntp_len; 733 734 return 0; 735 } 736 737 /* Parse NTP Options for FQDN */ 738 static int parse_ntp_fqdn(uint16_t *dhcpv6_ntp_len, char *fqdn, uint8_t **dhcpv6_ntp) 739 { 740 size_t fqdn_len = strlen(fqdn); 741 uint16_t sub_opt = 0, sub_len = 0, ntp_len = 0; 742 uint8_t *ntp = *dhcpv6_ntp; 743 size_t pos = *dhcpv6_ntp_len; 744 uint8_t buf[256] = {0}; 745 746 if (fqdn_len > 0 && fqdn[fqdn_len - 1] == '.') 747 fqdn[fqdn_len - 1] = 0; 748 749 int len = dn_comp(fqdn, buf, sizeof(buf), NULL, NULL); 750 if (len <= 0) 751 return -1; 752 753 ntp_len = len + 4; 754 755 ntp = realloc(ntp, pos + ntp_len); 756 if (!ntp) 757 return -1; 758 759 *dhcpv6_ntp = ntp; 760 761 sub_opt = htons(NTP_SUBOPTION_SRV_FQDN); 762 sub_len = htons(len); 763 764 memcpy(ntp + pos, &sub_opt, sizeof(sub_opt)); 765 pos += sizeof(sub_opt); 766 memcpy(ntp + pos, &sub_len, sizeof(sub_len)); 767 pos += sizeof(sub_len); 768 memcpy(ntp + pos, buf, len); 769 770 *dhcpv6_ntp_len += ntp_len; 771 772 return 0; 773 } 774 775 /* Parse DNR Options */ 776 static int parse_dnr_str(char *str, struct interface *iface) 777 { 778 struct dnr_options dnr = {0}; 779 size_t adn_len; 780 uint8_t adn_buf[256] = {0}; 781 char *saveptr1, *saveptr2; 782 783 char *priority; 784 priority = strtok_r(str, " \f\n\r\t\v", &saveptr1); 785 if (!priority) { 786 goto err; 787 } else if (sscanf(priority, "%" SCNu16, &dnr.priority) != 1) { 788 error("Unable to parse priority '%s'", priority); 789 goto err; 790 } else if (dnr.priority == 0) { 791 error("Invalid priority '%s'", priority); 792 goto err; 793 } 794 795 char *adn; 796 adn = strtok_r(NULL, " \f\n\r\t\v", &saveptr1); 797 if (!adn) 798 goto err; 799 800 adn_len = strlen(adn); 801 if (adn_len > 0 && adn[adn_len - 1] == '.') 802 adn[adn_len - 1] = '\0'; 803 804 if (adn_len >= sizeof(adn_buf)) { 805 error("Hostname '%s' too long", adn); 806 goto err; 807 } 808 809 adn_len = dn_comp(adn, adn_buf, sizeof(adn_buf), NULL, NULL); 810 if (adn_len <= 0) { 811 error("Unable to parse hostname '%s'", adn); 812 goto err; 813 } 814 815 dnr.adn = malloc(adn_len); 816 if (!dnr.adn) 817 goto err; 818 memcpy(dnr.adn, adn_buf, adn_len); 819 dnr.adn_len = adn_len; 820 821 char *addrs; 822 addrs = strtok_r(NULL, " \f\n\r\t\v", &saveptr1); 823 if (!addrs) 824 // ADN-Only mode 825 goto done; 826 827 for (char *addr = strtok_r(addrs, ",", &saveptr2); addr; addr = strtok_r(NULL, ",", &saveptr2)) { 828 struct in6_addr addr6, *tmp6; 829 struct in_addr addr4, *tmp4; 830 size_t new_sz; 831 832 if (inet_pton(AF_INET6, addr, &addr6) == 1) { 833 new_sz = (dnr.addr6_cnt + 1) * sizeof(*dnr.addr6); 834 if (new_sz > UINT16_MAX) 835 continue; 836 tmp6 = realloc(dnr.addr6, new_sz); 837 if (!tmp6) 838 goto err; 839 dnr.addr6 = tmp6; 840 memcpy(&dnr.addr6[dnr.addr6_cnt], &addr6, sizeof(*dnr.addr6)); 841 dnr.addr6_cnt++; 842 843 } else if (inet_pton(AF_INET, addr, &addr4) == 1) { 844 new_sz = (dnr.addr4_cnt + 1) * sizeof(*dnr.addr4); 845 if (new_sz > UINT8_MAX) 846 continue; 847 tmp4 = realloc(dnr.addr4, new_sz); 848 if (!tmp4) 849 goto err; 850 dnr.addr4 = tmp4; 851 memcpy(&dnr.addr4[dnr.addr4_cnt], &addr4, sizeof(*dnr.addr4)); 852 dnr.addr4_cnt++; 853 854 } else { 855 error("Unable to parse IP address '%s'", addr); 856 goto err; 857 } 858 } 859 860 char *svc_vals[DNR_SVC_MAX] = { NULL, }; 861 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)) { 862 uint16_t svc_id; 863 char *svc_key, *svc_val; 864 865 svc_key = strtok_r(svc_tok, "=", &saveptr2); 866 svc_val = strtok_r(NULL, "=", &saveptr2); 867 868 if (!strcmp(svc_key, "_lifetime")) { 869 uint32_t lifetime; 870 871 if (!svc_val || sscanf(svc_val, "%" SCNu32, &lifetime) != 1) { 872 error("Invalid value '%s' for _lifetime", svc_val ? svc_val : ""); 873 goto err; 874 } 875 876 dnr.lifetime = lifetime; 877 dnr.lifetime_set = true; 878 continue; 879 } 880 881 for (svc_id = 0; svc_id < DNR_SVC_MAX; svc_id++) 882 if (!strcmp(svc_key, svc_param_key_names[svc_id])) 883 break; 884 885 if (svc_id >= DNR_SVC_MAX) { 886 error("Invalid SvcParam '%s'", svc_key); 887 goto err; 888 } 889 890 svc_vals[svc_id] = svc_val ? svc_val : ""; 891 } 892 893 /* SvcParamKeys must be in increasing order, RFC9460 §2.2 */ 894 for (uint16_t svc_key = 0; svc_key < DNR_SVC_MAX; svc_key++) { 895 uint16_t svc_key_be = ntohs(svc_key); 896 uint16_t svc_val_len, svc_val_len_be; 897 char *svc_val_str = svc_vals[svc_key]; 898 uint8_t *tmp; 899 900 if (!svc_val_str) 901 continue; 902 903 switch (svc_key) { 904 case DNR_SVC_MANDATORY: 905 uint16_t mkeys[DNR_SVC_MAX]; 906 907 svc_val_len = 0; 908 for (char *mkey_str = strtok_r(svc_val_str, ",", &saveptr2); mkey_str; mkey_str = strtok_r(NULL, ",", &saveptr2)) { 909 uint16_t mkey; 910 911 for (mkey = 0; mkey < DNR_SVC_MAX; mkey++) 912 if (!strcmp(mkey_str, svc_param_key_names[mkey])) 913 break; 914 915 if (mkey >= DNR_SVC_MAX || !svc_vals[mkey]) { 916 error("Invalid value '%s' for SvcParam 'mandatory'", mkey_str); 917 goto err; 918 } 919 920 mkeys[svc_val_len++] = ntohs(mkey); 921 } 922 923 svc_val_len *= sizeof(uint16_t); 924 svc_val_len_be = ntohs(svc_val_len); 925 926 tmp = realloc(dnr.svc, dnr.svc_len + 4 + svc_val_len); 927 if (!tmp) 928 goto err; 929 930 dnr.svc = tmp; 931 memcpy(dnr.svc + dnr.svc_len, &svc_key_be, sizeof(svc_key_be)); 932 memcpy(dnr.svc + dnr.svc_len + 2, &svc_val_len_be, sizeof(svc_val_len_be)); 933 memcpy(dnr.svc + dnr.svc_len + 4, mkeys, svc_val_len); 934 dnr.svc_len += 4 + svc_val_len; 935 break; 936 937 case DNR_SVC_ALPN: 938 size_t len_off; 939 940 tmp = realloc(dnr.svc, dnr.svc_len + 4); 941 if (!tmp) 942 goto err; 943 944 dnr.svc = tmp; 945 memcpy(dnr.svc + dnr.svc_len, &svc_key_be, sizeof(svc_key_be)); 946 /* the length is not known yet */ 947 len_off = dnr.svc_len + sizeof(svc_key_be); 948 dnr.svc_len += 4; 949 950 svc_val_len = 0; 951 for (char *alpn_id_str = strtok_r(svc_val_str, ",", &saveptr2); alpn_id_str; alpn_id_str = strtok_r(NULL, ",", &saveptr2)) { 952 size_t alpn_id_len; 953 954 alpn_id_len = strlen(alpn_id_str); 955 if (alpn_id_len > UINT8_MAX) { 956 error("Invalid value '%s' for SvcParam 'alpn'", alpn_id_str); 957 goto err; 958 } 959 960 tmp = realloc(dnr.svc, dnr.svc_len + 1 + alpn_id_len); 961 if (!tmp) 962 goto err; 963 dnr.svc = tmp; 964 965 dnr.svc[dnr.svc_len] = alpn_id_len; 966 memcpy(dnr.svc + dnr.svc_len + 1, alpn_id_str, alpn_id_len); 967 dnr.svc_len += 1 + alpn_id_len; 968 svc_val_len += 1 + alpn_id_len; 969 } 970 971 svc_val_len_be = ntohs(svc_val_len); 972 memcpy(dnr.svc + len_off, &svc_val_len_be, sizeof(svc_val_len_be)); 973 break; 974 975 case DNR_SVC_PORT: 976 uint16_t port; 977 978 if (sscanf(svc_val_str, "%" SCNu16, &port) != 1) { 979 error("Invalid value '%s' for SvcParam 'port'", svc_val_str); 980 goto err; 981 } 982 983 port = ntohs(port); 984 svc_val_len_be = ntohs(2); 985 986 tmp = realloc(dnr.svc, dnr.svc_len + 6); 987 if (!tmp) 988 goto err; 989 990 dnr.svc = tmp; 991 memcpy(dnr.svc + dnr.svc_len, &svc_key_be, sizeof(svc_key_be)); 992 memcpy(dnr.svc + dnr.svc_len + 2, &svc_val_len_be, sizeof(svc_val_len_be)); 993 memcpy(dnr.svc + dnr.svc_len + 4, &port, sizeof(port)); 994 dnr.svc_len += 6; 995 break; 996 997 case DNR_SVC_NO_DEFAULT_ALPN: 998 /* fall through */ 999 1000 case DNR_SVC_OHTTP: 1001 if (strlen(svc_val_str) > 0) { 1002 error("Invalid value '%s' for SvcParam 'port'", svc_val_str); 1003 goto err; 1004 } 1005 /* fall through */ 1006 1007 case DNR_SVC_DOHPATH: 1008 /* plain string */ 1009 svc_val_len = strlen(svc_val_str); 1010 svc_val_len_be = ntohs(svc_val_len); 1011 tmp = realloc(dnr.svc, dnr.svc_len + 4 + svc_val_len); 1012 if (!tmp) 1013 goto err; 1014 1015 dnr.svc = tmp; 1016 memcpy(dnr.svc + dnr.svc_len, &svc_key_be, sizeof(svc_key_be)); 1017 dnr.svc_len += sizeof(svc_key_be); 1018 memcpy(dnr.svc + dnr.svc_len, &svc_val_len_be, sizeof(svc_val_len_be)); 1019 dnr.svc_len += sizeof(svc_val_len_be); 1020 memcpy(dnr.svc + dnr.svc_len, svc_val_str, svc_val_len); 1021 dnr.svc_len += svc_val_len; 1022 break; 1023 1024 case DNR_SVC_ECH: 1025 error("SvcParam 'ech' is not implemented"); 1026 goto err; 1027 1028 case DNR_SVC_IPV4HINT: 1029 /* fall through */ 1030 1031 case DNR_SVC_IPV6HINT: 1032 error("SvcParam '%s' is not allowed", svc_param_key_names[svc_key]); 1033 goto err; 1034 } 1035 } 1036 1037 done: 1038 struct dnr_options *tmp; 1039 tmp = realloc(iface->dnr, (iface->dnr_cnt + 1) * sizeof(dnr)); 1040 if (!tmp) 1041 goto err; 1042 1043 iface->dnr = tmp; 1044 memcpy(iface->dnr + iface->dnr_cnt, &dnr, sizeof(dnr)); 1045 iface->dnr_cnt++; 1046 return 0; 1047 1048 err: 1049 free(dnr.adn); 1050 free(dnr.addr4); 1051 free(dnr.addr6); 1052 free(dnr.svc); 1053 return -1; 1054 } 1055 1056 int config_parse_interface(void *data, size_t len, const char *name, bool overwrite) 1057 { 1058 struct odhcpd_ipaddr *addrs = NULL; 1059 struct interface *iface; 1060 struct blob_attr *tb[IFACE_ATTR_MAX], *c; 1061 ssize_t addrs_len; 1062 bool get_addrs = false; 1063 int mode; 1064 const char *ifname = NULL; 1065 1066 blobmsg_parse(iface_attrs, IFACE_ATTR_MAX, tb, data, len); 1067 1068 if (tb[IFACE_ATTR_INTERFACE]) 1069 name = blobmsg_get_string(tb[IFACE_ATTR_INTERFACE]); 1070 1071 if (!name) 1072 return -1; 1073 1074 iface = avl_find_element(&interfaces, name, iface, avl); 1075 if (!iface) { 1076 char *new_name; 1077 1078 iface = calloc_a(sizeof(*iface), &new_name, strlen(name) + 1); 1079 if (!iface) 1080 return -1; 1081 1082 iface->name = strcpy(new_name, name); 1083 iface->avl.key = iface->name; 1084 iface->router_event.uloop.fd = -1; 1085 iface->dhcpv6_event.uloop.fd = -1; 1086 iface->ndp_event.uloop.fd = -1; 1087 iface->ndp_ping_fd = -1; 1088 iface->dhcpv4_event.uloop.fd = -1; 1089 INIT_LIST_HEAD(&iface->ia_assignments); 1090 INIT_LIST_HEAD(&iface->dhcpv4_leases); 1091 INIT_LIST_HEAD(&iface->dhcpv4_fr_ips); 1092 1093 set_interface_defaults(iface); 1094 1095 avl_insert(&interfaces, &iface->avl); 1096 get_addrs = overwrite = true; 1097 } 1098 1099 if (overwrite) { 1100 if ((c = tb[IFACE_ATTR_IFNAME])) 1101 ifname = blobmsg_get_string(c); 1102 else if ((c = tb[IFACE_ATTR_NETWORKID])) 1103 ifname = blobmsg_get_string(c); 1104 } 1105 1106 #ifdef WITH_UBUS 1107 if (overwrite || !iface->ifname) 1108 ifname = ubus_get_ifname(name); 1109 #endif 1110 1111 if (!iface->ifname && !ifname) 1112 goto err; 1113 1114 if (ifname) { 1115 free(iface->ifname); 1116 iface->ifname = strdup(ifname); 1117 1118 if (!iface->ifname) 1119 goto err; 1120 1121 if (!iface->ifindex && 1122 (iface->ifindex = if_nametoindex(iface->ifname)) <= 0) 1123 goto err; 1124 1125 if ((iface->ifflags = odhcpd_get_flags(iface)) < 0) 1126 goto err; 1127 } 1128 1129 if (get_addrs) { 1130 addrs_len = netlink_get_interface_addrs(iface->ifindex, 1131 true, &iface->addr6); 1132 1133 if (addrs_len > 0) 1134 iface->addr6_len = addrs_len; 1135 1136 addrs_len = netlink_get_interface_addrs(iface->ifindex, 1137 false, &iface->addr4); 1138 if (addrs_len > 0) 1139 iface->addr4_len = addrs_len; 1140 } 1141 1142 addrs_len = netlink_get_interface_linklocal(iface->ifindex, &addrs); 1143 if (addrs_len > 0) { 1144 for (ssize_t i = 0; i < addrs_len; i++) { 1145 if (!addrs[i].tentative) { 1146 iface->have_link_local = true; 1147 break; 1148 } 1149 } 1150 free(addrs); 1151 } 1152 1153 iface->inuse = true; 1154 1155 if ((c = tb[IFACE_ATTR_DYNAMICDHCP])) 1156 iface->no_dynamic_dhcp = !blobmsg_get_bool(c); 1157 1158 if ((c = tb[IFACE_ATTR_LEASETIME])) { 1159 uint32_t time = parse_leasetime(c); 1160 1161 if (time > 0) 1162 iface->dhcp_leasetime = time; 1163 else 1164 error("Invalid %s value configured for interface '%s'", 1165 iface_attrs[IFACE_ATTR_LEASETIME].name, iface->name); 1166 1167 } 1168 1169 if ((c = tb[IFACE_ATTR_MAX_PREFERRED_LIFETIME])) { 1170 uint32_t time = parse_leasetime(c); 1171 1172 if (time > 0) 1173 iface->max_preferred_lifetime = time; 1174 else 1175 error("Invalid %s value configured for interface '%s'", 1176 iface_attrs[IFACE_ATTR_MAX_PREFERRED_LIFETIME].name, iface->name); 1177 } 1178 1179 if ((c = tb[IFACE_ATTR_MAX_VALID_LIFETIME])) { 1180 uint32_t time = parse_leasetime(c); 1181 1182 if (time > 0) 1183 iface->max_valid_lifetime = time; 1184 else 1185 error("Invalid %s value configured for interface '%s'", 1186 iface_attrs[IFACE_ATTR_MAX_VALID_LIFETIME].name, iface->name); 1187 } 1188 1189 if ((c = tb[IFACE_ATTR_START])) { 1190 iface->dhcpv4_start.s_addr = htonl(blobmsg_get_u32(c)); 1191 iface->dhcpv4_end.s_addr = htonl(ntohl(iface->dhcpv4_start.s_addr) + 1192 LIMIT_DEFAULT - 1); 1193 } 1194 1195 if ((c = tb[IFACE_ATTR_LIMIT])) 1196 iface->dhcpv4_end.s_addr = htonl(ntohl(iface->dhcpv4_start.s_addr) + 1197 blobmsg_get_u32(c) - 1); 1198 1199 if ((c = tb[IFACE_ATTR_MASTER])) 1200 iface->master = blobmsg_get_bool(c); 1201 1202 if (overwrite && (c = tb[IFACE_ATTR_UPSTREAM])) { 1203 struct blob_attr *cur; 1204 unsigned rem; 1205 1206 blobmsg_for_each_attr(cur, c, rem) { 1207 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 1208 continue; 1209 1210 iface->upstream = realloc(iface->upstream, 1211 iface->upstream_len + blobmsg_data_len(cur)); 1212 if (!iface->upstream) 1213 goto err; 1214 1215 memcpy(iface->upstream + iface->upstream_len, blobmsg_get_string(cur), blobmsg_data_len(cur)); 1216 iface->upstream_len += blobmsg_data_len(cur); 1217 } 1218 } 1219 1220 if ((c = tb[IFACE_ATTR_RA])) { 1221 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) { 1222 iface->ra = mode; 1223 1224 if (iface->ra != MODE_DISABLED) 1225 iface->ignore = false; 1226 } else 1227 error("Invalid %s mode configured for interface '%s'", 1228 iface_attrs[IFACE_ATTR_RA].name, iface->name); 1229 } 1230 1231 if ((c = tb[IFACE_ATTR_DHCPV4])) { 1232 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) { 1233 iface->dhcpv4 = config.main_dhcpv4 ? mode : MODE_DISABLED; 1234 1235 if (iface->dhcpv4 != MODE_DISABLED) 1236 iface->ignore = false; 1237 } else 1238 error("Invalid %s mode configured for interface %s", 1239 iface_attrs[IFACE_ATTR_DHCPV4].name, iface->name); 1240 } 1241 1242 if ((c = tb[IFACE_ATTR_DHCPV6])) { 1243 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) { 1244 iface->dhcpv6 = mode; 1245 1246 if (iface->dhcpv6 != MODE_DISABLED) 1247 iface->ignore = false; 1248 } else 1249 error("Invalid %s mode configured for interface '%s'", 1250 iface_attrs[IFACE_ATTR_DHCPV6].name, iface->name); 1251 } 1252 1253 if ((c = tb[IFACE_ATTR_NDP])) { 1254 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) { 1255 iface->ndp = mode; 1256 1257 if (iface->ndp != MODE_DISABLED) 1258 iface->ignore = false; 1259 } else 1260 error("Invalid %s mode configured for interface '%s'", 1261 iface_attrs[IFACE_ATTR_NDP].name, iface->name); 1262 } 1263 1264 if ((c = tb[IFACE_ATTR_ROUTER])) { 1265 struct blob_attr *cur; 1266 unsigned rem; 1267 1268 blobmsg_for_each_attr(cur, c, rem) { 1269 struct in_addr addr4; 1270 1271 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 1272 continue; 1273 1274 if (inet_pton(AF_INET, blobmsg_get_string(cur), &addr4) == 1) { 1275 iface->dhcpv4_router = realloc(iface->dhcpv4_router, 1276 (++iface->dhcpv4_router_cnt) * sizeof(*iface->dhcpv4_router)); 1277 if (!iface->dhcpv4_router) 1278 goto err; 1279 1280 iface->dhcpv4_router[iface->dhcpv4_router_cnt - 1] = addr4; 1281 } else 1282 error("Invalid %s value configured for interface '%s'", 1283 iface_attrs[IFACE_ATTR_ROUTER].name, iface->name); 1284 } 1285 } 1286 1287 if ((c = tb[IFACE_ATTR_DNS])) { 1288 struct blob_attr *cur; 1289 unsigned rem; 1290 1291 iface->always_rewrite_dns = true; 1292 blobmsg_for_each_attr(cur, c, rem) { 1293 struct in_addr addr4; 1294 struct in6_addr addr6; 1295 1296 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 1297 continue; 1298 1299 if (inet_pton(AF_INET, blobmsg_get_string(cur), &addr4) == 1) { 1300 if (addr4.s_addr == INADDR_ANY) { 1301 error("Invalid %s value configured for interface '%s'", 1302 iface_attrs[IFACE_ATTR_DNS].name, iface->name); 1303 continue; 1304 } 1305 1306 iface->dhcpv4_dns = realloc(iface->dhcpv4_dns, 1307 (++iface->dhcpv4_dns_cnt) * sizeof(*iface->dhcpv4_dns)); 1308 if (!iface->dhcpv4_dns) 1309 goto err; 1310 1311 iface->dhcpv4_dns[iface->dhcpv4_dns_cnt - 1] = addr4; 1312 } else if (inet_pton(AF_INET6, blobmsg_get_string(cur), &addr6) == 1) { 1313 if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) { 1314 error("Invalid %s value configured for interface '%s'", 1315 iface_attrs[IFACE_ATTR_DNS].name, iface->name); 1316 continue; 1317 } 1318 1319 iface->dns = realloc(iface->dns, 1320 (++iface->dns_cnt) * sizeof(*iface->dns)); 1321 if (!iface->dns) 1322 goto err; 1323 1324 iface->dns[iface->dns_cnt - 1] = addr6; 1325 } else 1326 error("Invalid %s value configured for interface '%s'", 1327 iface_attrs[IFACE_ATTR_DNS].name, iface->name); 1328 } 1329 } 1330 1331 if ((c = tb[IFACE_ATTR_DNS_SERVICE])) 1332 iface->dns_service = blobmsg_get_bool(c); 1333 1334 if ((c = tb[IFACE_ATTR_DOMAIN])) { 1335 struct blob_attr *cur; 1336 unsigned rem; 1337 1338 blobmsg_for_each_attr(cur, c, rem) { 1339 uint8_t buf[256]; 1340 char *domain = blobmsg_get_string(cur); 1341 size_t domainlen = strlen(domain); 1342 int len; 1343 1344 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 1345 continue; 1346 1347 domain = blobmsg_get_string(cur); 1348 domainlen = strlen(domain); 1349 1350 if (domainlen > 0 && domain[domainlen - 1] == '.') 1351 domain[domainlen - 1] = 0; 1352 1353 len = dn_comp(domain, buf, sizeof(buf), NULL, NULL); 1354 if (len <= 0) { 1355 error("Invalid %s value configured for interface '%s'", 1356 iface_attrs[IFACE_ATTR_DOMAIN].name, iface->name); 1357 continue; 1358 } 1359 1360 iface->search = realloc(iface->search, iface->search_len + len); 1361 if (!iface->search) 1362 goto err; 1363 1364 memcpy(&iface->search[iface->search_len], buf, len); 1365 iface->search_len += len; 1366 } 1367 } 1368 1369 if ((c = tb[IFACE_ATTR_DHCPV4_FORCERECONF])) 1370 iface->dhcpv4_forcereconf = blobmsg_get_bool(c); 1371 1372 if ((c = tb[IFACE_ATTR_DHCPV6_RAW])) { 1373 iface->dhcpv6_raw_len = blobmsg_data_len(c) / 2; 1374 iface->dhcpv6_raw = realloc(iface->dhcpv6_raw, iface->dhcpv6_raw_len); 1375 odhcpd_unhexlify(iface->dhcpv6_raw, iface->dhcpv6_raw_len, blobmsg_get_string(c)); 1376 } 1377 1378 if ((c = tb[IFACE_ATTR_DHCPV6_ASSIGNALL])) 1379 iface->dhcpv6_assignall = blobmsg_get_bool(c); 1380 1381 if ((c = tb[IFACE_ATTR_DHCPV6_PD])) 1382 iface->dhcpv6_pd = blobmsg_get_bool(c); 1383 1384 if ((c = tb[IFACE_ATTR_DHCPV6_PD_MIN_LEN])) { 1385 uint32_t pd_min_len = blobmsg_get_u32(c); 1386 if (pd_min_len > PD_MIN_LEN_MAX) 1387 iface->dhcpv6_pd_min_len = PD_MIN_LEN_MAX; 1388 iface->dhcpv6_pd_min_len = pd_min_len; 1389 if (pd_min_len > PD_MIN_LEN_MAX) 1390 warn("Clamped invalid %s value configured for interface '%s' to %d", 1391 iface_attrs[IFACE_ATTR_DHCPV6_PD_MIN_LEN].name, iface->name, iface->dhcpv6_pd_min_len); 1392 } 1393 1394 if ((c = tb[IFACE_ATTR_DHCPV6_NA])) 1395 iface->dhcpv6_na = blobmsg_get_bool(c); 1396 1397 if ((c = tb[IFACE_ATTR_DHCPV6_HOSTID_LEN])) { 1398 uint32_t original_hostid_len, hostid_len; 1399 original_hostid_len = hostid_len = blobmsg_get_u32(c); 1400 1401 if (hostid_len < HOSTID_LEN_MIN) 1402 hostid_len = HOSTID_LEN_MIN; 1403 else if (hostid_len > HOSTID_LEN_MAX) 1404 hostid_len = HOSTID_LEN_MAX; 1405 1406 iface->dhcpv6_hostid_len = hostid_len; 1407 1408 if (original_hostid_len != hostid_len) { 1409 warn("Clamped invalid %s value configured for interface '%s' to %d", 1410 iface_attrs[IFACE_ATTR_DHCPV6_HOSTID_LEN].name, iface->name, iface->dhcpv6_hostid_len); 1411 } 1412 } 1413 1414 if ((c = tb[IFACE_ATTR_RA_DEFAULT])) 1415 iface->default_router = blobmsg_get_u32(c); 1416 1417 if ((c = tb[IFACE_ATTR_RA_FLAGS])) { 1418 iface->ra_flags = 0; 1419 1420 if (parse_ra_flags(&iface->ra_flags, c) < 0) 1421 error("Invalid %s value configured for interface '%s'", 1422 iface_attrs[IFACE_ATTR_RA_FLAGS].name, iface->name); 1423 } 1424 1425 if ((c = tb[IFACE_ATTR_RA_REACHABLETIME])) { 1426 uint32_t ra_reachabletime = blobmsg_get_u32(c); 1427 1428 /* RFC4861 §6.2.1 : AdvReachableTime : 1429 * MUST be no greater than 3,600,000 msec 1430 */ 1431 iface->ra_reachabletime = ra_reachabletime <= AdvReachableTime ? ra_reachabletime : AdvReachableTime; 1432 if(ra_reachabletime > AdvReachableTime) 1433 warn("Clamped invalid %s value configured for interface '%s' to %d", 1434 iface_attrs[IFACE_ATTR_RA_REACHABLETIME].name, iface->name, iface->ra_reachabletime); 1435 } 1436 1437 if ((c = tb[IFACE_ATTR_RA_RETRANSTIME])) { 1438 uint32_t ra_retranstime = blobmsg_get_u32(c); 1439 1440 iface->ra_retranstime = ra_retranstime <= RETRANS_TIMER_MAX ? ra_retranstime : RETRANS_TIMER_MAX; 1441 if (ra_retranstime > RETRANS_TIMER_MAX) 1442 warn("Clamped invalid %s value configured for interface '%s' to %d", 1443 iface_attrs[IFACE_ATTR_RA_RETRANSTIME].name, iface->name, iface->ra_retranstime); 1444 } 1445 1446 if ((c = tb[IFACE_ATTR_RA_HOPLIMIT])) { 1447 uint32_t ra_hoplimit = blobmsg_get_u32(c); 1448 1449 /* RFC4861 §6.2.1 : AdvCurHopLimit */ 1450 iface->ra_hoplimit = ra_hoplimit <= AdvCurHopLimit ? ra_hoplimit : AdvCurHopLimit; 1451 if(ra_hoplimit > AdvCurHopLimit) 1452 warn("Clamped invalid %s value configured for interface '%s' to %d", 1453 iface_attrs[IFACE_ATTR_RA_HOPLIMIT].name, iface->name, iface->ra_hoplimit); 1454 1455 } 1456 1457 iface->if_mtu = odhcpd_get_interface_config(iface->ifname, "mtu"); 1458 if ((c = tb[IFACE_ATTR_RA_MTU])) { 1459 uint32_t original_ra_mtu, ra_mtu; 1460 original_ra_mtu = ra_mtu = blobmsg_get_u32(c); 1461 if (ra_mtu < RA_MTU_MIN) 1462 ra_mtu = RA_MTU_MIN; 1463 else if (ra_mtu > RA_MTU_MAX) 1464 ra_mtu = RA_MTU_MAX; 1465 if (iface->if_mtu && ra_mtu > iface->if_mtu) 1466 ra_mtu = iface->if_mtu; 1467 1468 iface->ra_mtu = ra_mtu; 1469 1470 if (original_ra_mtu != ra_mtu) { 1471 warn("Clamped invalid %s value configured for interface '%s' to %d", 1472 iface_attrs[IFACE_ATTR_RA_MTU].name, iface->name, iface->ra_mtu); 1473 } 1474 } 1475 1476 /* Default RA MTU to the interface MTU if no value is assigned */ 1477 if (!iface->ra_mtu && iface->if_mtu) { 1478 iface->ra_mtu = iface->if_mtu; 1479 info("Defaulted %s value for interface '%s' to %d", 1480 iface_attrs[IFACE_ATTR_RA_MTU].name, iface->name, iface->ra_mtu); 1481 } 1482 1483 if ((c = tb[IFACE_ATTR_RA_SLAAC])) 1484 iface->ra_slaac = blobmsg_get_bool(c); 1485 1486 if ((c = tb[IFACE_ATTR_RA_OFFLINK])) 1487 iface->ra_not_onlink = blobmsg_get_bool(c); 1488 1489 if ((c = tb[IFACE_ATTR_RA_ADVROUTER])) 1490 iface->ra_advrouter = blobmsg_get_bool(c); 1491 1492 /* 1493 * RFC4861: MaxRtrAdvInterval: MUST be no less than 4 seconds and no greater than 1800 seconds. 1494 * RFC8319: MaxRtrAdvInterval: MUST be no less than 4 seconds and no greater than 65535 seconds. 1495 * Default: 600 seconds 1496 */ 1497 if ((c = tb[IFACE_ATTR_RA_MAXINTERVAL])){ 1498 uint32_t ra_maxinterval = blobmsg_get_u32(c); 1499 if (ra_maxinterval < 4) 1500 ra_maxinterval = 4; 1501 else if (ra_maxinterval > MaxRtrAdvInterval) 1502 ra_maxinterval = MaxRtrAdvInterval; 1503 iface->ra_maxinterval = ra_maxinterval; 1504 } 1505 1506 /* 1507 * RFC4861: MinRtrAdvInterval: MUST be no less than 3 seconds and no greater than .75 * MaxRtrAdvInterval. 1508 * Default: 0.33 * MaxRtrAdvInterval If MaxRtrAdvInterval >= 9 seconds; otherwise, the 1509 * Default is MaxRtrAdvInterval. 1510 */ 1511 if ((c = tb[IFACE_ATTR_RA_MININTERVAL])){ 1512 uint32_t ra_mininterval = blobmsg_get_u32(c); 1513 if (ra_mininterval < MinRtrAdvInterval) 1514 ra_mininterval = MinRtrAdvInterval; // clamp min 1515 else if (ra_mininterval > (0.75 * iface->ra_maxinterval)) 1516 ra_mininterval = 0.75 * iface->ra_maxinterval; // clamp max 1517 iface->ra_mininterval = ra_mininterval; 1518 } 1519 1520 /* 1521 * RFC4861: AdvDefaultLifetime: MUST be either zero or between MaxRtrAdvInterval and 9000 seconds. 1522 * RFC8319: AdvDefaultLifetime: MUST be either zero or between MaxRtrAdvInterval and 65535 seconds. 1523 * Default: 3 * MaxRtrAdvInterval 1524 * i.e. 3 * 65535 => 65535 seconds. 1525 */ 1526 if ((c = tb[IFACE_ATTR_RA_LIFETIME])){ 1527 uint32_t ra_lifetime = blobmsg_get_u32(c); 1528 if (ra_lifetime != 0){ 1529 if (ra_lifetime < iface->ra_maxinterval) 1530 ra_lifetime = iface->ra_maxinterval; // clamp min 1531 else if (ra_lifetime > AdvDefaultLifetime) 1532 ra_lifetime = AdvDefaultLifetime; // clamp max 1533 } 1534 iface->ra_lifetime = ra_lifetime; 1535 } 1536 1537 if ((c = tb[IFACE_ATTR_RA_DNS])) 1538 iface->ra_dns = blobmsg_get_bool(c); 1539 1540 if ((c = tb[IFACE_ATTR_DNR])) { 1541 struct blob_attr *cur; 1542 unsigned rem; 1543 1544 blobmsg_for_each_attr(cur, c, rem) { 1545 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 1546 continue; 1547 1548 if (parse_dnr_str(blobmsg_get_string(cur), iface)) 1549 error("Invalid %s value configured for interface '%s'", 1550 iface_attrs[IFACE_ATTR_DNR].name, iface->name); 1551 } 1552 } 1553 1554 if ((c = tb[IFACE_ATTR_RA_PREF64])) { 1555 struct in6_addr addr; 1556 1557 odhcpd_parse_addr6_prefix(blobmsg_get_string(c), 1558 &addr, &iface->pref64_length); 1559 1560 iface->pref64_prefix[0] = addr.s6_addr32[0]; 1561 switch (iface->pref64_length) { 1562 case 96: 1563 iface->pref64_plc = 0; 1564 iface->pref64_prefix[1] = addr.s6_addr32[1]; 1565 iface->pref64_prefix[2] = addr.s6_addr32[2]; 1566 break; 1567 case 64: 1568 iface->pref64_plc = 1; 1569 iface->pref64_prefix[1] = addr.s6_addr32[1]; 1570 iface->pref64_prefix[2] = 0; 1571 break; 1572 case 56: 1573 iface->pref64_plc = 2; 1574 iface->pref64_prefix[1] = addr.s6_addr32[1] & htonl(0xffffff00); 1575 iface->pref64_prefix[2] = 0; 1576 break; 1577 case 48: 1578 iface->pref64_plc = 3; 1579 iface->pref64_prefix[1] = addr.s6_addr32[1] & htonl(0xffff0000); 1580 iface->pref64_prefix[2] = 0; 1581 break; 1582 case 40: 1583 iface->pref64_plc = 4; 1584 iface->pref64_prefix[1] = addr.s6_addr32[1] & htonl(0xff000000); 1585 iface->pref64_prefix[2] = 0; 1586 break; 1587 case 32: 1588 iface->pref64_plc = 5; 1589 iface->pref64_prefix[1] = 0; 1590 iface->pref64_prefix[2] = 0; 1591 break; 1592 default: 1593 warn("Invalid PREF64 prefix size (%d), ignoring ra_pref64 option!", 1594 iface->pref64_length); 1595 iface->pref64_length = 0; 1596 } 1597 } 1598 1599 if ((c = tb[IFACE_ATTR_RA_PREFERENCE])) { 1600 const char *prio = blobmsg_get_string(c); 1601 1602 if (!strcmp(prio, "high")) 1603 iface->route_preference = 1; 1604 else if (!strcmp(prio, "low")) 1605 iface->route_preference = -1; 1606 else if (!strcmp(prio, "medium") || !strcmp(prio, "default")) 1607 iface->route_preference = 0; 1608 else 1609 error("Invalid %s mode configured for interface '%s'", 1610 iface_attrs[IFACE_ATTR_RA_PREFERENCE].name, iface->name); 1611 } 1612 1613 if ((c = tb[IFACE_ATTR_NDPROXY_ROUTING])) 1614 iface->learn_routes = blobmsg_get_bool(c); 1615 1616 if ((c = tb[IFACE_ATTR_NDPROXY_SLAVE])) 1617 iface->external = blobmsg_get_bool(c); 1618 1619 if ((c = tb[IFACE_ATTR_NDP_FROM_LINK_LOCAL])) 1620 iface->ndp_from_link_local = blobmsg_get_bool(c); 1621 1622 if ((c = tb[IFACE_ATTR_PREFIX_FILTER])) 1623 odhcpd_parse_addr6_prefix(blobmsg_get_string(c), 1624 &iface->pio_filter_addr, 1625 &iface->pio_filter_length); 1626 1627 if (overwrite && (c = tb[IFACE_ATTR_NTP])) { 1628 struct blob_attr *cur; 1629 unsigned rem; 1630 1631 blobmsg_for_each_attr(cur, c, rem) { 1632 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 1633 continue; 1634 1635 char *str = blobmsg_get_string(cur); 1636 struct in_addr addr4; 1637 struct in6_addr addr6; 1638 1639 if (inet_pton(AF_INET, str, &addr4) == 1) { 1640 if (addr4.s_addr == INADDR_ANY) 1641 goto err; 1642 1643 iface->dhcpv4_ntp = realloc(iface->dhcpv4_ntp, 1644 (++iface->dhcpv4_ntp_cnt) * sizeof(*iface->dhcpv4_ntp)); 1645 if (!iface->dhcpv4_ntp) 1646 goto err; 1647 1648 iface->dhcpv4_ntp[iface->dhcpv4_ntp_cnt - 1] = addr4; 1649 } else if (inet_pton(AF_INET6, str, &addr6) == 1) { 1650 if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) 1651 goto err; 1652 1653 iface->dhcpv6_sntp = realloc(iface->dhcpv6_sntp, 1654 (++iface->dhcpv6_sntp_cnt) * sizeof(*iface->dhcpv6_sntp)); 1655 if (!iface->dhcpv6_sntp) 1656 goto err; 1657 1658 iface->dhcpv6_sntp[iface->dhcpv6_sntp_cnt - 1] = addr6; 1659 1660 if (!parse_ntp_options(&iface->dhcpv6_ntp_len, addr6, &iface->dhcpv6_ntp)) 1661 iface->dhcpv6_ntp_cnt++; 1662 } else { 1663 if (!parse_ntp_fqdn(&iface->dhcpv6_ntp_len, str, &iface->dhcpv6_ntp)) 1664 iface->dhcpv6_ntp_cnt++; 1665 } 1666 } 1667 } 1668 1669 config_load_ra_pio(iface); 1670 1671 return 0; 1672 1673 err: 1674 close_interface(iface); 1675 return -1; 1676 } 1677 1678 static int set_interface(struct uci_section *s) 1679 { 1680 blob_buf_init(&b, 0); 1681 uci_to_blob(&b, s, &interface_attr_list); 1682 1683 return config_parse_interface(blob_data(b.head), blob_len(b.head), s->e.name, true); 1684 } 1685 1686 static void lease_cfg_delete_dhcpv6_leases(struct lease_cfg *lease_cfg) 1687 { 1688 struct dhcpv6_lease *lease, *tmp; 1689 1690 list_for_each_entry_safe(lease, tmp, &lease_cfg->dhcpv6_leases, lease_cfg_list) 1691 dhcpv6_free_lease(lease); 1692 } 1693 1694 static void lease_cfg_update_leases(struct lease_cfg *lease_cfg) 1695 { 1696 struct dhcpv4_lease *a4 = lease_cfg->dhcpv4_lease; 1697 struct dhcpv6_lease *lease6; 1698 1699 if (a4) { 1700 free(a4->hostname); 1701 a4->hostname = NULL; 1702 1703 if (lease_cfg->hostname) 1704 a4->hostname = strdup(lease_cfg->hostname); 1705 } 1706 1707 list_for_each_entry(lease6, &lease_cfg->dhcpv6_leases, lease_cfg_list) { 1708 free(lease6->hostname); 1709 lease6->hostname = NULL; 1710 1711 if (lease_cfg->hostname) 1712 lease6->hostname = strdup(lease_cfg->hostname); 1713 1714 lease6->leasetime = lease_cfg->leasetime; 1715 } 1716 } 1717 1718 static int lease_cfg_cmp(const void *k1, const void *k2, _unused void *ptr) 1719 { 1720 const struct lease_cfg *lease_cfg1 = k1, *lease_cfg2 = k2; 1721 int cmp = 0; 1722 1723 if (lease_cfg1->duid_count != lease_cfg2->duid_count) 1724 return lease_cfg1->duid_count - lease_cfg2->duid_count; 1725 1726 for (size_t i = 0; i < lease_cfg1->duid_count; i++) { 1727 if (lease_cfg1->duids[i].len != lease_cfg2->duids[i].len) 1728 return lease_cfg1->duids[i].len - lease_cfg2->duids[i].len; 1729 1730 if (lease_cfg1->duids[i].len && lease_cfg2->duids[i].len) { 1731 cmp = memcmp(lease_cfg1->duids[i].id, lease_cfg2->duids[i].id, 1732 lease_cfg1->duids[i].len); 1733 if (cmp) 1734 return cmp; 1735 } 1736 } 1737 1738 if (lease_cfg1->mac_count != lease_cfg2->mac_count) 1739 return lease_cfg1->mac_count - lease_cfg2->mac_count; 1740 1741 for (size_t i = 0; i < lease_cfg1->mac_count; i++) { 1742 cmp = memcmp(lease_cfg1->macs[i].ether_addr_octet, 1743 lease_cfg2->macs[i].ether_addr_octet, 1744 sizeof(lease_cfg1->macs[i].ether_addr_octet)); 1745 if (cmp) 1746 return cmp; 1747 } 1748 1749 return 0; 1750 } 1751 1752 static void lease_cfg_change(struct lease_cfg *lease_cfg_old, struct lease_cfg *lease_cfg_new) 1753 { 1754 bool update = false; 1755 1756 if ((!!lease_cfg_new->hostname != !!lease_cfg_old->hostname) || 1757 (lease_cfg_new->hostname && strcmp(lease_cfg_new->hostname, lease_cfg_old->hostname))) { 1758 free(lease_cfg_old->hostname); 1759 lease_cfg_old->hostname = NULL; 1760 1761 if (lease_cfg_new->hostname) 1762 lease_cfg_old->hostname = strdup(lease_cfg_new->hostname); 1763 1764 update = true; 1765 } 1766 1767 if (lease_cfg_old->leasetime != lease_cfg_new->leasetime) { 1768 lease_cfg_old->leasetime = lease_cfg_new->leasetime; 1769 update = true; 1770 } 1771 1772 if (lease_cfg_old->ipaddr != lease_cfg_new->ipaddr) { 1773 lease_cfg_old->ipaddr = lease_cfg_new->ipaddr; 1774 dhcpv4_free_lease(lease_cfg_old->dhcpv4_lease); 1775 } 1776 1777 if (lease_cfg_old->hostid != lease_cfg_new->hostid) { 1778 lease_cfg_old->hostid = lease_cfg_new->hostid; 1779 lease_cfg_delete_dhcpv6_leases(lease_cfg_old); 1780 } 1781 1782 if (update) 1783 lease_cfg_update_leases(lease_cfg_old); 1784 1785 free_lease_cfg(lease_cfg_new); 1786 } 1787 1788 static void lease_cfg_delete(struct lease_cfg *lease_cfg) 1789 { 1790 dhcpv4_free_lease(lease_cfg->dhcpv4_lease); 1791 lease_cfg_delete_dhcpv6_leases(lease_cfg); 1792 free_lease_cfg(lease_cfg); 1793 } 1794 1795 static void lease_cfg_update(_unused struct vlist_tree *tree, struct vlist_node *node_new, 1796 struct vlist_node *node_old) 1797 { 1798 struct lease_cfg *lease_cfg_new = container_of(node_new, struct lease_cfg, node); 1799 struct lease_cfg *lease_cfg_old = container_of(node_old, struct lease_cfg, node); 1800 1801 if (node_old && node_new) 1802 lease_cfg_change(lease_cfg_old, lease_cfg_new); 1803 else if (node_old) 1804 lease_cfg_delete(lease_cfg_old); 1805 } 1806 1807 /* 1808 * Either find: 1809 * a) a lease cfg with an exact DUID/IAID match; or 1810 * b) a lease cfg with a matching DUID and no IAID set 1811 */ 1812 struct lease_cfg * 1813 config_find_lease_cfg_by_duid_and_iaid(const uint8_t *duid, const uint16_t len, const uint32_t iaid) 1814 { 1815 struct lease_cfg *lease_cfg, *candidate = NULL; 1816 1817 vlist_for_each_element(&lease_cfgs, lease_cfg, node) { 1818 for (size_t i = 0; i < lease_cfg->duid_count; i++) { 1819 if (lease_cfg->duids[i].len != len) 1820 continue; 1821 1822 if (memcmp(lease_cfg->duids[i].id, duid, len)) 1823 continue; 1824 1825 if (!lease_cfg->duids[i].iaid_set) { 1826 candidate = lease_cfg; 1827 continue; 1828 } 1829 1830 if (lease_cfg->duids[i].iaid == iaid) 1831 return lease_cfg; 1832 } 1833 } 1834 1835 return candidate; 1836 } 1837 1838 struct lease_cfg *config_find_lease_cfg_by_mac(const uint8_t *mac) 1839 { 1840 struct lease_cfg *lease_cfg; 1841 1842 vlist_for_each_element(&lease_cfgs, lease_cfg, node) { 1843 for (size_t i = 0; i < lease_cfg->mac_count; i++) { 1844 if (!memcmp(lease_cfg->macs[i].ether_addr_octet, mac, 1845 sizeof(lease_cfg->macs[i].ether_addr_octet))) 1846 return lease_cfg; 1847 } 1848 } 1849 1850 return NULL; 1851 } 1852 1853 struct lease_cfg *config_find_lease_cfg_by_hostid(const uint64_t hostid) 1854 { 1855 struct lease_cfg *lease_cfg; 1856 1857 vlist_for_each_element(&lease_cfgs, lease_cfg, node) { 1858 if (lease_cfg->hostid == hostid) 1859 return lease_cfg; 1860 } 1861 1862 return NULL; 1863 } 1864 1865 struct lease_cfg *config_find_lease_cfg_by_ipaddr(const uint32_t ipaddr) 1866 { 1867 struct lease_cfg *lease_cfg; 1868 1869 vlist_for_each_element(&lease_cfgs, lease_cfg, node) { 1870 if (lease_cfg->ipaddr == ipaddr) 1871 return lease_cfg; 1872 } 1873 1874 return NULL; 1875 } 1876 1877 void reload_services(struct interface *iface) 1878 { 1879 if (iface->ifflags & IFF_RUNNING) { 1880 debug("Enabling services with %s running", iface->ifname); 1881 router_setup_interface(iface, iface->ra != MODE_DISABLED); 1882 dhcpv6_setup_interface(iface, iface->dhcpv6 != MODE_DISABLED); 1883 ndp_setup_interface(iface, iface->ndp != MODE_DISABLED); 1884 #ifdef DHCPV4_SUPPORT 1885 dhcpv4_setup_interface(iface, iface->dhcpv4 != MODE_DISABLED); 1886 #endif 1887 } else { 1888 debug("Disabling services with %s not running", iface->ifname); 1889 router_setup_interface(iface, false); 1890 dhcpv6_setup_interface(iface, false); 1891 ndp_setup_interface(iface, false); 1892 #ifdef DHCPV4_SUPPORT 1893 dhcpv4_setup_interface(iface, false); 1894 #endif 1895 } 1896 } 1897 1898 static int ipv6_pxe_from_uci(struct uci_section* s) 1899 { 1900 blob_buf_init(&b, 0); 1901 uci_to_blob(&b, s, &ipv6_pxe_attr_list); 1902 1903 void* data = blob_data(b.head); 1904 size_t len = blob_len(b.head); 1905 1906 struct blob_attr* tb[IFACE_ATTR_MAX]; 1907 blobmsg_parse(ipv6_pxe_attrs, IPV6_PXE_MAX, tb, data, len); 1908 1909 if (!tb[IPV6_PXE_URL]) 1910 return -1; 1911 1912 const char* url = blobmsg_get_string(tb[IPV6_PXE_URL]); 1913 1914 uint32_t arch = 0xFFFFFFFF; 1915 if (tb[IPV6_PXE_ARCH]) 1916 arch = blobmsg_get_u32(tb[IPV6_PXE_ARCH]); 1917 1918 return ipv6_pxe_entry_new(arch, url) ? -1 : 0; 1919 } 1920 1921 #define JSON_LENGTH "length" 1922 #define JSON_PREFIX "prefix" 1923 #define JSON_SLAAC "slaac" 1924 #define JSON_TIME "time" 1925 1926 static inline time_t config_time_from_json(time_t json_time) 1927 { 1928 time_t ref, now; 1929 1930 ref = time(NULL); 1931 now = odhcpd_time(); 1932 1933 if (now > json_time || ref > json_time) 1934 return 0; 1935 1936 return json_time + (now - ref); 1937 } 1938 1939 static inline time_t config_time_to_json(time_t config_time) 1940 { 1941 time_t ref, now; 1942 1943 ref = time(NULL); 1944 now = odhcpd_time(); 1945 1946 return config_time + (ref - now); 1947 } 1948 1949 static inline bool config_ra_pio_enabled(struct interface *iface) 1950 { 1951 return config.ra_piofolder_fd >= 0 && iface->ra == MODE_SERVER && !iface->master; 1952 } 1953 1954 static bool config_ra_pio_time(json_object *slaac_json, time_t *slaac_time) 1955 { 1956 time_t pio_json_time, pio_time; 1957 json_object *time_json; 1958 1959 time_json = json_object_object_get(slaac_json, JSON_TIME); 1960 if (!time_json) 1961 return true; 1962 1963 pio_json_time = (time_t) json_object_get_int64(time_json); 1964 if (!pio_json_time) 1965 return true; 1966 1967 pio_time = config_time_from_json(pio_json_time); 1968 if (!pio_time) 1969 return false; 1970 1971 *slaac_time = pio_time; 1972 1973 return true; 1974 } 1975 1976 static json_object *config_load_ra_pio_json(struct interface *iface) 1977 { 1978 json_object *json; 1979 int fd; 1980 1981 fd = openat(config.ra_piofolder_fd, iface->ifname, O_RDONLY | O_CLOEXEC); 1982 if (fd < 0) 1983 return NULL; 1984 1985 json = json_object_from_fd(fd); 1986 1987 close(fd); 1988 1989 if (!json) 1990 error("rfc9096: %s: json read error %s", 1991 iface->ifname, 1992 json_util_get_last_err()); 1993 1994 return json; 1995 } 1996 1997 void config_load_ra_pio(struct interface *iface) 1998 { 1999 json_object *json, *slaac_json; 2000 size_t pio_cnt; 2001 time_t now; 2002 2003 if (!config_ra_pio_enabled(iface)) 2004 return; 2005 2006 json = config_load_ra_pio_json(iface); 2007 if (!json) 2008 return; 2009 2010 slaac_json = json_object_object_get(json, JSON_SLAAC); 2011 if (!slaac_json) { 2012 json_object_put(json); 2013 return; 2014 } 2015 2016 now = odhcpd_time(); 2017 2018 pio_cnt = json_object_array_length(slaac_json); 2019 iface->pios = malloc(sizeof(struct ra_pio) * pio_cnt); 2020 if (!iface->pios) { 2021 json_object_put(json); 2022 return; 2023 } 2024 2025 iface->pio_cnt = 0; 2026 for (size_t i = 0; i < pio_cnt; i++) { 2027 json_object *cur_pio_json, *length_json, *prefix_json; 2028 const char *pio_str; 2029 time_t pio_lt = 0; 2030 struct ra_pio *pio; 2031 uint8_t pio_len; 2032 2033 cur_pio_json = json_object_array_get_idx(slaac_json, i); 2034 if (!cur_pio_json) 2035 continue; 2036 2037 if (!config_ra_pio_time(cur_pio_json, &pio_lt)) 2038 continue; 2039 2040 length_json = json_object_object_get(cur_pio_json, JSON_LENGTH); 2041 if (!length_json) 2042 continue; 2043 2044 prefix_json = json_object_object_get(cur_pio_json, JSON_PREFIX); 2045 if (!prefix_json) 2046 continue; 2047 2048 pio_len = (uint8_t) json_object_get_uint64(length_json); 2049 pio_str = json_object_get_string(prefix_json); 2050 pio = &iface->pios[iface->pio_cnt]; 2051 2052 inet_pton(AF_INET6, pio_str, &pio->prefix); 2053 pio->length = pio_len; 2054 pio->lifetime = pio_lt; 2055 info("rfc9096: %s: load %s/%u (%u)", 2056 iface->ifname, 2057 pio_str, 2058 pio_len, 2059 ra_pio_lifetime(pio, now)); 2060 2061 iface->pio_cnt++; 2062 } 2063 2064 json_object_put(json); 2065 2066 if (!iface->pio_cnt) { 2067 free(iface->pios); 2068 iface->pios = NULL; 2069 } else if (iface->pio_cnt != pio_cnt) { 2070 iface->pios = realloc(iface->pios, sizeof(struct ra_pio) * iface->pio_cnt); 2071 } 2072 } 2073 2074 static void config_save_ra_pio_json(struct interface *iface, struct json_object *json) 2075 { 2076 size_t tmp_piofile_strlen; 2077 char *tmp_piofile; 2078 int fd, ret; 2079 2080 tmp_piofile_strlen = strlen(iface->ifname) + 2; 2081 tmp_piofile = alloca(tmp_piofile_strlen); 2082 snprintf(tmp_piofile, tmp_piofile_strlen, ".%s", iface->ifname); 2083 2084 fd = openat(config.ra_piofolder_fd, 2085 tmp_piofile, 2086 O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 2087 0644); 2088 if (fd < 0) { 2089 error("rfc9096: %s: error %m creating temporary json file", 2090 iface->ifname); 2091 return; 2092 } 2093 2094 ret = json_object_to_fd(fd, json, JSON_C_TO_STRING_PLAIN); 2095 if (ret) { 2096 error("rfc9096: %s: json write error %s", 2097 iface->ifname, 2098 json_util_get_last_err()); 2099 close(fd); 2100 unlinkat(config.ra_piofolder_fd, tmp_piofile, 0); 2101 return; 2102 } 2103 2104 ret = fsync(fd); 2105 if (ret) { 2106 error("rfc9096: %s: error %m syncing %s", 2107 iface->ifname, 2108 tmp_piofile); 2109 close(fd); 2110 unlinkat(config.ra_piofolder_fd, tmp_piofile, 0); 2111 return; 2112 } 2113 2114 ret = close(fd); 2115 if (ret) { 2116 error("rfc9096: %s: error %m closing %s", 2117 iface->ifname, 2118 tmp_piofile); 2119 unlinkat(config.ra_piofolder_fd, tmp_piofile, 0); 2120 return; 2121 } 2122 2123 ret = renameat(config.ra_piofolder_fd, 2124 tmp_piofile, 2125 config.ra_piofolder_fd, 2126 iface->ifname); 2127 if (ret) { 2128 error("rfc9096: %s: error %m renaming piofile: %s -> %s", 2129 iface->ifname, 2130 tmp_piofile, 2131 iface->ifname); 2132 close(fd); 2133 unlinkat(config.ra_piofolder_fd, tmp_piofile, 0); 2134 return; 2135 } 2136 2137 iface->pio_update = false; 2138 warn("rfc9096: %s: piofile updated", iface->ifname); 2139 } 2140 2141 void config_save_ra_pio(struct interface *iface) 2142 { 2143 struct json_object *json, *slaac_json; 2144 char ipv6_str[INET6_ADDRSTRLEN]; 2145 time_t now; 2146 2147 if (!config_ra_pio_enabled(iface)) 2148 return; 2149 2150 if (!iface->pio_update) 2151 return; 2152 2153 now = odhcpd_time(); 2154 2155 json = json_object_new_object(); 2156 if (!json) 2157 return; 2158 2159 slaac_json = json_object_new_array_ext(iface->pio_cnt); 2160 if (!slaac_json) { 2161 json_object_put(slaac_json); 2162 return; 2163 } 2164 2165 json_object_object_add(json, JSON_SLAAC, slaac_json); 2166 2167 for (size_t i = 0; i < iface->pio_cnt; i++) { 2168 struct json_object *cur_pio_json, *len_json, *pfx_json; 2169 const struct ra_pio *cur_pio = &iface->pios[i]; 2170 2171 if (ra_pio_expired(cur_pio, now)) 2172 continue; 2173 2174 cur_pio_json = json_object_new_object(); 2175 if (!cur_pio_json) 2176 continue; 2177 2178 inet_ntop(AF_INET6, &cur_pio->prefix, ipv6_str, sizeof(ipv6_str)); 2179 2180 pfx_json = json_object_new_string(ipv6_str); 2181 if (!pfx_json) { 2182 json_object_put(cur_pio_json); 2183 continue; 2184 } 2185 2186 len_json = json_object_new_uint64(cur_pio->length); 2187 if (!len_json) { 2188 json_object_put(cur_pio_json); 2189 json_object_put(pfx_json); 2190 continue; 2191 } 2192 2193 json_object_object_add(cur_pio_json, JSON_PREFIX, pfx_json); 2194 json_object_object_add(cur_pio_json, JSON_LENGTH, len_json); 2195 2196 if (cur_pio->lifetime) { 2197 struct json_object *time_json; 2198 time_t pio_lt; 2199 2200 pio_lt = config_time_to_json(cur_pio->lifetime); 2201 2202 time_json = json_object_new_int64(pio_lt); 2203 if (time_json) 2204 json_object_object_add(cur_pio_json, JSON_TIME, time_json); 2205 } 2206 2207 json_object_array_add(slaac_json, cur_pio_json); 2208 } 2209 2210 config_save_ra_pio_json(iface, json); 2211 2212 json_object_put(json); 2213 } 2214 2215 void odhcpd_reload(void) 2216 { 2217 struct uci_context *uci = uci_alloc_context(); 2218 struct interface *master = NULL, *i, *tmp; 2219 char *uci_dhcp_path = "dhcp"; 2220 char *uci_system_path = "system"; 2221 char *uci_network_path = "network"; 2222 2223 if (!uci) 2224 return; 2225 2226 if (config.uci_cfgdir) { 2227 size_t dlen = strlen(config.uci_cfgdir); 2228 2229 uci_dhcp_path = alloca(dlen + sizeof("/dhcp")); 2230 sprintf(uci_dhcp_path, "%s/dhcp", config.uci_cfgdir); 2231 uci_system_path = alloca(dlen + sizeof("/system")); 2232 sprintf(uci_system_path, "%s/system", config.uci_cfgdir); 2233 uci_network_path = alloca(dlen + sizeof("/network")); 2234 sprintf(uci_network_path, "%s/network", config.uci_cfgdir); 2235 } 2236 2237 vlist_update(&lease_cfgs); 2238 avl_for_each_element(&interfaces, i, avl) 2239 clean_interface(i); 2240 2241 struct uci_package *network = NULL; 2242 if (!uci_load(uci, uci_network_path, &network)) { 2243 struct uci_element *e; 2244 2245 /* 0. Global settings */ 2246 uci_foreach_element(&network->sections, e) { 2247 struct uci_section *s = uci_to_section(e); 2248 if (!strcmp(s->type, "globals")) 2249 set_global_config(s); 2250 } 2251 } 2252 uci_unload(uci, network); 2253 2254 struct uci_package *dhcp = NULL; 2255 if (!uci_load(uci, uci_dhcp_path, &dhcp)) { 2256 struct uci_element *e; 2257 2258 /* 1. General odhcpd settings */ 2259 uci_foreach_element(&dhcp->sections, e) { 2260 struct uci_section *s = uci_to_section(e); 2261 if (!strcmp(s->type, "odhcpd")) 2262 set_config(s); 2263 } 2264 2265 /* 2. DHCP pools */ 2266 uci_foreach_element(&dhcp->sections, e) { 2267 struct uci_section *s = uci_to_section(e); 2268 if (!strcmp(s->type, "dhcp")) 2269 set_interface(s); 2270 } 2271 2272 /* 3. Static lease cfgs */ 2273 uci_foreach_element(&dhcp->sections, e) { 2274 struct uci_section* s = uci_to_section(e); 2275 if (!strcmp(s->type, "host")) 2276 set_lease_cfg_from_uci(s); 2277 } 2278 2279 /* 4. IPv6 PxE */ 2280 ipv6_pxe_clear(); 2281 uci_foreach_element(&dhcp->sections, e) { 2282 struct uci_section* s = uci_to_section(e); 2283 if (!strcmp(s->type, "boot6")) 2284 ipv6_pxe_from_uci(s); 2285 } 2286 ipv6_pxe_dump(); 2287 } 2288 uci_unload(uci, dhcp); 2289 2290 struct uci_package *system = NULL; 2291 if (config.enable_tz && !uci_load(uci, uci_system_path, &system)) { 2292 struct uci_element *e; 2293 2294 /* 5. System settings */ 2295 uci_foreach_element(&system->sections, e) { 2296 struct uci_section *s = uci_to_section(e); 2297 if (!strcmp(s->type, "system")) 2298 set_timezone_info_from_uci(s); 2299 } 2300 } 2301 uci_unload(uci, system); 2302 2303 if (config.dhcp_statefile) { 2304 char *path = strdupa(config.dhcp_statefile); 2305 2306 mkdir_p(dirname(path), 0755); 2307 } 2308 2309 if (config.ra_piofolder) { 2310 char *path = strdupa(config.ra_piofolder); 2311 2312 mkdir_p(path, 0755); 2313 2314 close(config.ra_piofolder_fd); 2315 config.ra_piofolder_fd = open(path, O_PATH | O_DIRECTORY | O_CLOEXEC); 2316 if (config.ra_piofolder_fd < 0) 2317 error("Unable to open piofolder '%s': %m", path); 2318 } 2319 2320 vlist_flush(&lease_cfgs); 2321 2322 ubus_apply_network(); 2323 2324 bool any_dhcpv6_slave = false, any_ra_slave = false, any_ndp_slave = false; 2325 2326 /* Test for */ 2327 avl_for_each_element(&interfaces, i, avl) { 2328 if (i->master) 2329 continue; 2330 2331 if (i->dhcpv6 == MODE_HYBRID || i->dhcpv6 == MODE_RELAY) 2332 any_dhcpv6_slave = true; 2333 2334 if (i->ra == MODE_HYBRID || i->ra == MODE_RELAY) 2335 any_ra_slave = true; 2336 2337 if (i->ndp == MODE_HYBRID || i->ndp == MODE_RELAY) 2338 any_ndp_slave = true; 2339 } 2340 2341 /* Evaluate hybrid mode for master */ 2342 avl_for_each_element(&interfaces, i, avl) { 2343 if (!i->master) 2344 continue; 2345 2346 enum odhcpd_mode hybrid_mode = MODE_DISABLED; 2347 #ifdef WITH_UBUS 2348 if (!ubus_has_prefix(i->name, i->ifname)) 2349 hybrid_mode = MODE_RELAY; 2350 #endif 2351 2352 if (i->dhcpv6 == MODE_HYBRID) 2353 i->dhcpv6 = hybrid_mode; 2354 2355 if (i->dhcpv6 == MODE_RELAY && !any_dhcpv6_slave) 2356 i->dhcpv6 = MODE_DISABLED; 2357 2358 if (i->ra == MODE_HYBRID) 2359 i->ra = hybrid_mode; 2360 2361 if (i->ra == MODE_RELAY && !any_ra_slave) 2362 i->ra = MODE_DISABLED; 2363 2364 if (i->ndp == MODE_HYBRID) 2365 i->ndp = hybrid_mode; 2366 2367 if (i->ndp == MODE_RELAY && !any_ndp_slave) 2368 i->ndp = MODE_DISABLED; 2369 2370 if (i->dhcpv6 == MODE_RELAY || i->ra == MODE_RELAY || i->ndp == MODE_RELAY) 2371 master = i; 2372 } 2373 2374 2375 avl_for_each_element_safe(&interfaces, i, avl, tmp) { 2376 if (i->inuse && i->ifflags & IFF_RUNNING) { 2377 /* Resolve hybrid mode */ 2378 if (i->dhcpv6 == MODE_HYBRID) 2379 i->dhcpv6 = (master && master->dhcpv6 == MODE_RELAY) ? 2380 MODE_RELAY : MODE_SERVER; 2381 2382 if (i->ra == MODE_HYBRID) 2383 i->ra = (master && master->ra == MODE_RELAY) ? 2384 MODE_RELAY : MODE_SERVER; 2385 2386 if (i->ndp == MODE_HYBRID) 2387 i->ndp = (master && master->ndp == MODE_RELAY) ? 2388 MODE_RELAY : MODE_DISABLED; 2389 2390 reload_services(i); 2391 } else 2392 close_interface(i); 2393 } 2394 2395 uci_free_context(uci); 2396 } 2397 2398 static void handle_signal(int signal) 2399 { 2400 char b[1] = {0}; 2401 2402 if (signal == SIGHUP) { 2403 if (write(reload_pipe[1], b, sizeof(b)) < 0) {} 2404 } else 2405 uloop_end(); 2406 } 2407 2408 static void reload_cb(struct uloop_fd *u, _unused unsigned int events) 2409 { 2410 char b[512]; 2411 if (read(u->fd, b, sizeof(b)) < 0) {} 2412 2413 odhcpd_reload(); 2414 } 2415 2416 static struct uloop_fd reload_fd = { .fd = -1, .cb = reload_cb }; 2417 2418 void odhcpd_run(void) 2419 { 2420 if (pipe2(reload_pipe, O_NONBLOCK | O_CLOEXEC) < 0) {} 2421 2422 reload_fd.fd = reload_pipe[0]; 2423 uloop_fd_add(&reload_fd, ULOOP_READ); 2424 2425 signal(SIGTERM, handle_signal); 2426 signal(SIGINT, handle_signal); 2427 signal(SIGHUP, handle_signal); 2428 2429 while (ubus_init()) 2430 sleep(1); 2431 2432 odhcpd_reload(); 2433 uloop_run(); 2434 } 2435
This page was automatically generated by LXR 0.3.1. • OpenWrt