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