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