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