1 #include <fcntl.h> 2 #include <resolv.h> 3 #include <signal.h> 4 #include <arpa/inet.h> 5 #include <unistd.h> 6 #include <libgen.h> 7 #include <net/if.h> 8 #include <string.h> 9 #include <sys/stat.h> 10 #include <syslog.h> 11 12 #include <uci.h> 13 #include <uci_blob.h> 14 #include <libubox/utils.h> 15 #include <libubox/avl.h> 16 #include <libubox/avl-cmp.h> 17 #include <libubox/list.h> 18 #include <libubox/vlist.h> 19 20 #include "odhcpd.h" 21 22 static struct blob_buf b; 23 static int reload_pipe[2] = { -1, -1 }; 24 25 static int lease_cmp(const void *k1, const void *k2, void *ptr); 26 static void lease_update(struct vlist_tree *tree, struct vlist_node *node_new, 27 struct vlist_node *node_old); 28 29 struct vlist_tree leases = VLIST_TREE_INIT(leases, lease_cmp, lease_update, true, false); 30 AVL_TREE(interfaces, avl_strcmp, false, NULL); 31 struct config config = {.legacy = false, .main_dhcpv4 = false, 32 .dhcp_cb = NULL, .dhcp_statefile = NULL, .dhcp_hostsfile = NULL, 33 .log_level = LOG_WARNING}; 34 35 #define START_DEFAULT 100 36 #define LIMIT_DEFAULT 150 37 38 #define HOSTID_LEN_MIN 12 39 #define HOSTID_LEN_MAX 64 40 #define HOSTID_LEN_DEFAULT HOSTID_LEN_MIN 41 42 #define PD_MIN_LEN_MAX (64-2) // must delegate at least 2 bits of prefix 43 44 #define OAF_DHCPV6 (OAF_DHCPV6_NA | OAF_DHCPV6_PD) 45 46 enum { 47 IFACE_ATTR_INTERFACE, 48 IFACE_ATTR_IFNAME, 49 IFACE_ATTR_NETWORKID, 50 IFACE_ATTR_DYNAMICDHCP, 51 IFACE_ATTR_LEASETIME, 52 IFACE_ATTR_LIMIT, 53 IFACE_ATTR_START, 54 IFACE_ATTR_MASTER, 55 IFACE_ATTR_UPSTREAM, 56 IFACE_ATTR_RA, 57 IFACE_ATTR_DHCPV4, 58 IFACE_ATTR_DHCPV6, 59 IFACE_ATTR_NDP, 60 IFACE_ATTR_ROUTER, 61 IFACE_ATTR_DNS, 62 IFACE_ATTR_DNS_SERVICE, 63 IFACE_ATTR_DOMAIN, 64 IFACE_ATTR_FILTER_CLASS, 65 IFACE_ATTR_DHCPV4_FORCERECONF, 66 IFACE_ATTR_DHCPV6_RAW, 67 IFACE_ATTR_DHCPV6_ASSIGNALL, 68 IFACE_ATTR_DHCPV6_PD, 69 IFACE_ATTR_DHCPV6_PD_MIN_LEN, 70 IFACE_ATTR_DHCPV6_NA, 71 IFACE_ATTR_DHCPV6_HOSTID_LEN, 72 IFACE_ATTR_RA_DEFAULT, 73 IFACE_ATTR_RA_MANAGEMENT, 74 IFACE_ATTR_RA_FLAGS, 75 IFACE_ATTR_RA_SLAAC, 76 IFACE_ATTR_RA_OFFLINK, 77 IFACE_ATTR_RA_PREFERENCE, 78 IFACE_ATTR_RA_ADVROUTER, 79 IFACE_ATTR_RA_MININTERVAL, 80 IFACE_ATTR_RA_MAXINTERVAL, 81 IFACE_ATTR_RA_LIFETIME, 82 IFACE_ATTR_RA_USELEASETIME, 83 IFACE_ATTR_RA_REACHABLETIME, 84 IFACE_ATTR_RA_RETRANSTIME, 85 IFACE_ATTR_RA_HOPLIMIT, 86 IFACE_ATTR_RA_MTU, 87 IFACE_ATTR_RA_DNS, 88 IFACE_ATTR_RA_PREF64, 89 IFACE_ATTR_PD_MANAGER, 90 IFACE_ATTR_PD_CER, 91 IFACE_ATTR_NDPROXY_ROUTING, 92 IFACE_ATTR_NDPROXY_SLAVE, 93 IFACE_ATTR_PREFIX_FILTER, 94 IFACE_ATTR_PREFERRED_LIFETIME, 95 IFACE_ATTR_NTP, 96 IFACE_ATTR_MAX 97 }; 98 99 static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = { 100 [IFACE_ATTR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING }, 101 [IFACE_ATTR_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, 102 [IFACE_ATTR_NETWORKID] = { .name = "networkid", .type = BLOBMSG_TYPE_STRING }, 103 [IFACE_ATTR_DYNAMICDHCP] = { .name = "dynamicdhcp", .type = BLOBMSG_TYPE_BOOL }, 104 [IFACE_ATTR_LEASETIME] = { .name = "leasetime", .type = BLOBMSG_TYPE_STRING }, 105 [IFACE_ATTR_START] = { .name = "start", .type = BLOBMSG_TYPE_INT32 }, 106 [IFACE_ATTR_LIMIT] = { .name = "limit", .type = BLOBMSG_TYPE_INT32 }, 107 [IFACE_ATTR_MASTER] = { .name = "master", .type = BLOBMSG_TYPE_BOOL }, 108 [IFACE_ATTR_UPSTREAM] = { .name = "upstream", .type = BLOBMSG_TYPE_ARRAY }, 109 [IFACE_ATTR_RA] = { .name = "ra", .type = BLOBMSG_TYPE_STRING }, 110 [IFACE_ATTR_DHCPV4] = { .name = "dhcpv4", .type = BLOBMSG_TYPE_STRING }, 111 [IFACE_ATTR_DHCPV6] = { .name = "dhcpv6", .type = BLOBMSG_TYPE_STRING }, 112 [IFACE_ATTR_NDP] = { .name = "ndp", .type = BLOBMSG_TYPE_STRING }, 113 [IFACE_ATTR_ROUTER] = { .name = "router", .type = BLOBMSG_TYPE_ARRAY }, 114 [IFACE_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY }, 115 [IFACE_ATTR_DNS_SERVICE] = { .name = "dns_service", .type = BLOBMSG_TYPE_BOOL }, 116 [IFACE_ATTR_DOMAIN] = { .name = "domain", .type = BLOBMSG_TYPE_ARRAY }, 117 [IFACE_ATTR_FILTER_CLASS] = { .name = "filter_class", .type = BLOBMSG_TYPE_STRING }, 118 [IFACE_ATTR_DHCPV4_FORCERECONF] = { .name = "dhcpv4_forcereconf", .type = BLOBMSG_TYPE_BOOL }, 119 [IFACE_ATTR_DHCPV6_RAW] = { .name = "dhcpv6_raw", .type = BLOBMSG_TYPE_STRING }, 120 [IFACE_ATTR_DHCPV6_ASSIGNALL] = { .name ="dhcpv6_assignall", .type = BLOBMSG_TYPE_BOOL }, 121 [IFACE_ATTR_DHCPV6_PD] = { .name = "dhcpv6_pd", .type = BLOBMSG_TYPE_BOOL }, 122 [IFACE_ATTR_DHCPV6_PD_MIN_LEN] = { .name = "dhcpv6_pd_min_len", .type = BLOBMSG_TYPE_INT32 }, 123 [IFACE_ATTR_DHCPV6_NA] = { .name = "dhcpv6_na", .type = BLOBMSG_TYPE_BOOL }, 124 [IFACE_ATTR_DHCPV6_HOSTID_LEN] = { .name = "dhcpv6_hostidlength", .type = BLOBMSG_TYPE_INT32 }, 125 [IFACE_ATTR_PD_MANAGER] = { .name = "pd_manager", .type = BLOBMSG_TYPE_STRING }, 126 [IFACE_ATTR_PD_CER] = { .name = "pd_cer", .type = BLOBMSG_TYPE_STRING }, 127 [IFACE_ATTR_RA_DEFAULT] = { .name = "ra_default", .type = BLOBMSG_TYPE_INT32 }, 128 [IFACE_ATTR_RA_MANAGEMENT] = { .name = "ra_management", .type = BLOBMSG_TYPE_INT32 }, 129 [IFACE_ATTR_RA_FLAGS] = { .name = "ra_flags", . type = BLOBMSG_TYPE_ARRAY }, 130 [IFACE_ATTR_RA_SLAAC] = { .name = "ra_slaac", .type = BLOBMSG_TYPE_BOOL }, 131 [IFACE_ATTR_RA_OFFLINK] = { .name = "ra_offlink", .type = BLOBMSG_TYPE_BOOL }, 132 [IFACE_ATTR_RA_PREFERENCE] = { .name = "ra_preference", .type = BLOBMSG_TYPE_STRING }, 133 [IFACE_ATTR_RA_ADVROUTER] = { .name = "ra_advrouter", .type = BLOBMSG_TYPE_BOOL }, 134 [IFACE_ATTR_RA_MININTERVAL] = { .name = "ra_mininterval", .type = BLOBMSG_TYPE_INT32 }, 135 [IFACE_ATTR_RA_MAXINTERVAL] = { .name = "ra_maxinterval", .type = BLOBMSG_TYPE_INT32 }, 136 [IFACE_ATTR_RA_LIFETIME] = { .name = "ra_lifetime", .type = BLOBMSG_TYPE_INT32 }, 137 [IFACE_ATTR_RA_USELEASETIME] = { .name = "ra_useleasetime", .type = BLOBMSG_TYPE_BOOL }, 138 [IFACE_ATTR_RA_REACHABLETIME] = { .name = "ra_reachabletime", .type = BLOBMSG_TYPE_INT32 }, 139 [IFACE_ATTR_RA_RETRANSTIME] = { .name = "ra_retranstime", .type = BLOBMSG_TYPE_INT32 }, 140 [IFACE_ATTR_RA_HOPLIMIT] = { .name = "ra_hoplimit", .type = BLOBMSG_TYPE_INT32 }, 141 [IFACE_ATTR_RA_MTU] = { .name = "ra_mtu", .type = BLOBMSG_TYPE_INT32 }, 142 [IFACE_ATTR_RA_DNS] = { .name = "ra_dns", .type = BLOBMSG_TYPE_BOOL }, 143 [IFACE_ATTR_RA_PREF64] = { .name = "ra_pref64", .type = BLOBMSG_TYPE_STRING }, 144 [IFACE_ATTR_NDPROXY_ROUTING] = { .name = "ndproxy_routing", .type = BLOBMSG_TYPE_BOOL }, 145 [IFACE_ATTR_NDPROXY_SLAVE] = { .name = "ndproxy_slave", .type = BLOBMSG_TYPE_BOOL }, 146 [IFACE_ATTR_PREFIX_FILTER] = { .name = "prefix_filter", .type = BLOBMSG_TYPE_STRING }, 147 [IFACE_ATTR_PREFERRED_LIFETIME] = { .name = "preferred_lifetime", .type = BLOBMSG_TYPE_STRING }, 148 [IFACE_ATTR_NTP] = { .name = "ntp", .type = BLOBMSG_TYPE_ARRAY }, 149 }; 150 151 static const struct uci_blob_param_info iface_attr_info[IFACE_ATTR_MAX] = { 152 [IFACE_ATTR_UPSTREAM] = { .type = BLOBMSG_TYPE_STRING }, 153 [IFACE_ATTR_DNS] = { .type = BLOBMSG_TYPE_STRING }, 154 [IFACE_ATTR_DOMAIN] = { .type = BLOBMSG_TYPE_STRING }, 155 }; 156 157 const struct uci_blob_param_list interface_attr_list = { 158 .n_params = IFACE_ATTR_MAX, 159 .params = iface_attrs, 160 .info = iface_attr_info, 161 }; 162 163 const struct blobmsg_policy lease_attrs[LEASE_ATTR_MAX] = { 164 [LEASE_ATTR_IP] = { .name = "ip", .type = BLOBMSG_TYPE_STRING }, 165 [LEASE_ATTR_MAC] = { .name = "mac", .type = BLOBMSG_TYPE_STRING }, 166 [LEASE_ATTR_DUID] = { .name = "duid", .type = BLOBMSG_TYPE_STRING }, 167 [LEASE_ATTR_HOSTID] = { .name = "hostid", .type = BLOBMSG_TYPE_STRING }, 168 [LEASE_ATTR_LEASETIME] = { .name = "leasetime", .type = BLOBMSG_TYPE_STRING }, 169 [LEASE_ATTR_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING }, 170 }; 171 172 const struct uci_blob_param_list lease_attr_list = { 173 .n_params = LEASE_ATTR_MAX, 174 .params = lease_attrs, 175 }; 176 177 enum { 178 ODHCPD_ATTR_LEGACY, 179 ODHCPD_ATTR_MAINDHCP, 180 ODHCPD_ATTR_LEASEFILE, 181 ODHCPD_ATTR_LEASETRIGGER, 182 ODHCPD_ATTR_LOGLEVEL, 183 ODHCPD_ATTR_HOSTSFILE, 184 ODHCPD_ATTR_MAX 185 }; 186 187 static const struct blobmsg_policy odhcpd_attrs[ODHCPD_ATTR_MAX] = { 188 [ODHCPD_ATTR_LEGACY] = { .name = "legacy", .type = BLOBMSG_TYPE_BOOL }, 189 [ODHCPD_ATTR_MAINDHCP] = { .name = "maindhcp", .type = BLOBMSG_TYPE_BOOL }, 190 [ODHCPD_ATTR_LEASEFILE] = { .name = "leasefile", .type = BLOBMSG_TYPE_STRING }, 191 [ODHCPD_ATTR_LEASETRIGGER] = { .name = "leasetrigger", .type = BLOBMSG_TYPE_STRING }, 192 [ODHCPD_ATTR_LOGLEVEL] = { .name = "loglevel", .type = BLOBMSG_TYPE_INT32 }, 193 [ODHCPD_ATTR_HOSTSFILE] = { .name = "hostsfile", .type = BLOBMSG_TYPE_STRING }, 194 }; 195 196 const struct uci_blob_param_list odhcpd_attr_list = { 197 .n_params = ODHCPD_ATTR_MAX, 198 .params = odhcpd_attrs, 199 }; 200 201 static const struct { const char *name; uint8_t flag; } ra_flags[] = { 202 { .name = "managed-config", .flag = ND_RA_FLAG_MANAGED }, 203 { .name = "other-config", .flag = ND_RA_FLAG_OTHER }, 204 { .name = "home-agent", .flag = ND_RA_FLAG_HOME_AGENT }, 205 { .name = "none", . flag = 0 }, 206 { .name = NULL, }, 207 }; 208 209 static void set_interface_defaults(struct interface *iface) 210 { 211 iface->ignore = true; 212 iface->dhcpv4 = MODE_DISABLED; 213 iface->dhcpv6 = MODE_DISABLED; 214 iface->ra = MODE_DISABLED; 215 iface->ndp = MODE_DISABLED; 216 iface->learn_routes = 1; 217 iface->dhcp_leasetime = 43200; 218 iface->preferred_lifetime = 43200; 219 iface->dhcpv4_start.s_addr = htonl(START_DEFAULT); 220 iface->dhcpv4_end.s_addr = htonl(START_DEFAULT + LIMIT_DEFAULT - 1); 221 iface->dhcpv6_assignall = true; 222 iface->dhcpv6_pd = true; 223 iface->dhcpv6_pd_min_len = 0; 224 iface->dhcpv6_na = true; 225 iface->dhcpv6_hostid_len = HOSTID_LEN_DEFAULT; 226 iface->dns_service = true; 227 iface->ra_flags = ND_RA_FLAG_OTHER; 228 iface->ra_slaac = true; 229 iface->ra_maxinterval = 600; 230 iface->ra_mininterval = iface->ra_maxinterval/3; 231 iface->ra_lifetime = -1; 232 iface->ra_dns = true; 233 } 234 235 static void clean_interface(struct interface *iface) 236 { 237 free(iface->dns); 238 free(iface->search); 239 free(iface->upstream); 240 free(iface->dhcpv4_router); 241 free(iface->dhcpv4_dns); 242 free(iface->dhcpv6_raw); 243 free(iface->filter_class); 244 free(iface->dhcpv4_ntp); 245 free(iface->dhcpv6_ntp); 246 free(iface->dhcpv6_sntp); 247 memset(&iface->ra, 0, sizeof(*iface) - offsetof(struct interface, ra)); 248 set_interface_defaults(iface); 249 } 250 251 static void close_interface(struct interface *iface) 252 { 253 avl_delete(&interfaces, &iface->avl); 254 255 router_setup_interface(iface, false); 256 dhcpv6_setup_interface(iface, false); 257 ndp_setup_interface(iface, false); 258 #ifdef DHCPV4_SUPPORT 259 dhcpv4_setup_interface(iface, false); 260 #endif 261 262 /* make sure timer is not on the timeouts list before freeing */ 263 uloop_timeout_cancel(&iface->timer_rs); 264 265 clean_interface(iface); 266 free(iface->addr4); 267 free(iface->addr6); 268 free(iface->invalid_addr6); 269 free(iface->ifname); 270 free(iface); 271 } 272 273 static int parse_mode(const char *mode) 274 { 275 if (!strcmp(mode, "disabled")) 276 return MODE_DISABLED; 277 else if (!strcmp(mode, "server")) 278 return MODE_SERVER; 279 else if (!strcmp(mode, "relay")) 280 return MODE_RELAY; 281 else if (!strcmp(mode, "hybrid")) 282 return MODE_HYBRID; 283 else 284 return -1; 285 } 286 287 static int parse_ra_flags(uint8_t *flags, struct blob_attr *attr) 288 { 289 struct blob_attr *cur; 290 unsigned rem; 291 292 blobmsg_for_each_attr(cur, attr, rem) { 293 int i; 294 295 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) 296 continue; 297 298 if (!blobmsg_check_attr(cur, false)) 299 continue; 300 301 for (i = 0; ra_flags[i].name; i++) { 302 if (!strcmp(ra_flags[i].name, blobmsg_get_string(cur))) { 303 *flags |= ra_flags[i].flag; 304 break; 305 } 306 } 307 308 if (!ra_flags[i].name) 309 return -1; 310 } 311 312 return 0; 313 } 314 315 static void set_config(struct uci_section *s) 316 { 317 struct blob_attr *tb[ODHCPD_ATTR_MAX], *c; 318 319 blob_buf_init(&b, 0); 320 uci_to_blob(&b, s, &odhcpd_attr_list); 321 blobmsg_parse(odhcpd_attrs, ODHCPD_ATTR_MAX, tb, blob_data(b.head), blob_len(b.head)); 322 323 if ((c = tb[ODHCPD_ATTR_LEGACY])) 324 config.legacy = blobmsg_get_bool(c); 325 326 if ((c = tb[ODHCPD_ATTR_MAINDHCP])) 327 config.main_dhcpv4 = blobmsg_get_bool(c); 328 329 if ((c = tb[ODHCPD_ATTR_LEASEFILE])) { 330 free(config.dhcp_statefile); 331 config.dhcp_statefile = strdup(blobmsg_get_string(c)); 332 } 333 334 if ((c = tb[ODHCPD_ATTR_HOSTSFILE])) { 335 free(config.dhcp_hostsfile); 336 config.dhcp_hostsfile = strdup(blobmsg_get_string(c)); 337 } 338 339 if ((c = tb[ODHCPD_ATTR_LEASETRIGGER])) { 340 free(config.dhcp_cb); 341 config.dhcp_cb = strdup(blobmsg_get_string(c)); 342 } 343 344 if ((c = tb[ODHCPD_ATTR_LOGLEVEL])) { 345 int log_level = (blobmsg_get_u32(c) & LOG_PRIMASK); 346 347 if (config.log_level != log_level) { 348 config.log_level = log_level; 349 setlogmask(LOG_UPTO(config.log_level)); 350 } 351 } 352 } 353 354 static double parse_leasetime(struct blob_attr *c) { 355 char *val = blobmsg_get_string(c), *endptr = NULL; 356 double time = strcmp(val, "infinite") ? strtod(val, &endptr) : UINT32_MAX; 357 358 if (time && endptr && endptr[0]) { 359 if (endptr[0] == 's') 360 time *= 1; 361 else if (endptr[0] == 'm') 362 time *= 60; 363 else if (endptr[0] == 'h') 364 time *= 3600; 365 else if (endptr[0] == 'd') 366 time *= 24 * 3600; 367 else if (endptr[0] == 'w') 368 time *= 7 * 24 * 3600; 369 else 370 goto err; 371 } 372 373 if (time < 60) 374 time = 60; 375 376 return time; 377 378 err: 379 return -1; 380 } 381 382 static void free_lease(struct lease *l) 383 { 384 free(l->hostname); 385 free(l); 386 } 387 388 389 int set_lease_from_blobmsg(struct blob_attr *ba) 390 { 391 struct blob_attr *tb[LEASE_ATTR_MAX], *c; 392 struct lease *l; 393 size_t duidlen = 0; 394 uint8_t *duid; 395 396 blobmsg_parse(lease_attrs, LEASE_ATTR_MAX, tb, blob_data(ba), blob_len(ba)); 397 398 if ((c = tb[LEASE_ATTR_DUID])) 399 duidlen = (blobmsg_data_len(c) - 1) / 2; 400 401 l = calloc_a(sizeof(*l), &duid, duidlen); 402 if (!l) 403 goto err; 404 405 if ((c = tb[LEASE_ATTR_MAC])) 406 if (!ether_aton_r(blobmsg_get_string(c), &l->mac)) 407 goto err; 408 409 if ((c = tb[LEASE_ATTR_DUID])) { 410 ssize_t len; 411 412 l->duid = duid; 413 len = odhcpd_unhexlify(l->duid, duidlen, blobmsg_get_string(c)); 414 415 if (len < 0) 416 goto err; 417 418 l->duid_len = len; 419 } 420 421 if ((c = tb[LEASE_ATTR_NAME])) { 422 l->hostname = strdup(blobmsg_get_string(c)); 423 if (!l->hostname || !odhcpd_valid_hostname(l->hostname)) 424 goto err; 425 } 426 427 if ((c = tb[LEASE_ATTR_IP])) 428 if (inet_pton(AF_INET, blobmsg_get_string(c), &l->ipaddr) < 0) 429 goto err; 430 431 if ((c = tb[LEASE_ATTR_HOSTID])) { 432 errno = 0; 433 l->hostid = strtoull(blobmsg_get_string(c), NULL, 16); 434 if (errno) 435 goto err; 436 } else { 437 uint32_t i4a = ntohl(l->ipaddr) & 0xff; 438 l->hostid = ((i4a / 100) << 8) | (((i4a % 100) / 10) << 4) | (i4a % 10); 439 } 440 441 if ((c = tb[LEASE_ATTR_LEASETIME])) { 442 double time = parse_leasetime(c); 443 if (time < 0) 444 goto err; 445 446 l->leasetime = time; 447 } 448 449 INIT_LIST_HEAD(&l->assignments); 450 vlist_add(&leases, &l->node, l); 451 return 0; 452 453 err: 454 if (l) 455 free_lease(l); 456 457 return -1; 458 } 459 460 static int set_lease_from_uci(struct uci_section *s) 461 { 462 blob_buf_init(&b, 0); 463 uci_to_blob(&b, s, &lease_attr_list); 464 465 return set_lease_from_blobmsg(b.head); 466 } 467 468 /* Parse NTP Options for DHCPv6 Address */ 469 static int parse_ntp_options(uint16_t *dhcpv6_ntp_len, struct in6_addr addr6, uint8_t **dhcpv6_ntp) 470 { 471 uint16_t sub_opt = 0, sub_len = htons(IPV6_ADDR_LEN); 472 uint16_t ntp_len = IPV6_ADDR_LEN + 4; 473 uint8_t *ntp = *dhcpv6_ntp; 474 size_t pos = *dhcpv6_ntp_len; 475 476 ntp = realloc(ntp, pos + ntp_len); 477 if (!ntp) 478 return -1; 479 480 *dhcpv6_ntp = ntp; 481 482 if (IN6_IS_ADDR_MULTICAST(&addr6)) 483 sub_opt = htons(NTP_SUBOPTION_MC_ADDR); 484 else 485 sub_opt = htons(NTP_SUBOPTION_SRV_ADDR); 486 487 memcpy(ntp + pos, &sub_opt, sizeof(sub_opt)); 488 pos += sizeof(sub_opt); 489 memcpy(ntp + pos, &sub_len, sizeof(sub_len)); 490 pos += sizeof(sub_len); 491 memcpy(ntp + pos, &addr6, IPV6_ADDR_LEN); 492 493 *dhcpv6_ntp_len += ntp_len; 494 495 return 0; 496 } 497 498 /* Parse NTP Options for FQDN */ 499 static int parse_ntp_fqdn(uint16_t *dhcpv6_ntp_len, char *fqdn, uint8_t **dhcpv6_ntp) 500 { 501 size_t fqdn_len = strlen(fqdn); 502 uint16_t sub_opt = 0, sub_len = 0, ntp_len = 0; 503 uint8_t *ntp = *dhcpv6_ntp; 504 size_t pos = *dhcpv6_ntp_len; 505 uint8_t buf[256] = {0}; 506 507 if (fqdn_len > 0 && fqdn[fqdn_len - 1] == '.') 508 fqdn[fqdn_len - 1] = 0; 509 510 int len = dn_comp(fqdn, buf, sizeof(buf), NULL, NULL); 511 if (len <= 0) 512 return -1; 513 514 ntp_len = len + 4; 515 516 ntp = realloc(ntp, pos + ntp_len); 517 if (!ntp) 518 return -1; 519 520 *dhcpv6_ntp = ntp; 521 522 sub_opt = htons(NTP_SUBOPTION_SRV_FQDN); 523 sub_len = htons(len); 524 525 memcpy(ntp + pos, &sub_opt, sizeof(sub_opt)); 526 pos += sizeof(sub_opt); 527 memcpy(ntp + pos, &sub_len, sizeof(sub_len)); 528 pos += sizeof(sub_len); 529 memcpy(ntp + pos, buf, len); 530 531 *dhcpv6_ntp_len += ntp_len; 532 533 return 0; 534 } 535 536 int config_parse_interface(void *data, size_t len, const char *name, bool overwrite) 537 { 538 struct odhcpd_ipaddr *addrs = NULL; 539 struct interface *iface; 540 struct blob_attr *tb[IFACE_ATTR_MAX], *c; 541 ssize_t addrs_len; 542 bool get_addrs = false; 543 int mode; 544 const char *ifname = NULL; 545 546 blobmsg_parse(iface_attrs, IFACE_ATTR_MAX, tb, data, len); 547 548 if (tb[IFACE_ATTR_INTERFACE]) 549 name = blobmsg_get_string(tb[IFACE_ATTR_INTERFACE]); 550 551 if (!name) 552 return -1; 553 554 iface = avl_find_element(&interfaces, name, iface, avl); 555 if (!iface) { 556 char *new_name; 557 558 iface = calloc_a(sizeof(*iface), &new_name, strlen(name) + 1); 559 if (!iface) 560 return -1; 561 562 iface->name = strcpy(new_name, name); 563 iface->avl.key = iface->name; 564 iface->router_event.uloop.fd = -1; 565 iface->dhcpv6_event.uloop.fd = -1; 566 iface->ndp_event.uloop.fd = -1; 567 iface->ndp_ping_fd = -1; 568 iface->dhcpv4_event.uloop.fd = -1; 569 INIT_LIST_HEAD(&iface->ia_assignments); 570 INIT_LIST_HEAD(&iface->dhcpv4_assignments); 571 INIT_LIST_HEAD(&iface->dhcpv4_fr_ips); 572 573 set_interface_defaults(iface); 574 575 avl_insert(&interfaces, &iface->avl); 576 get_addrs = overwrite = true; 577 } 578 579 if (overwrite) { 580 if ((c = tb[IFACE_ATTR_IFNAME])) 581 ifname = blobmsg_get_string(c); 582 else if ((c = tb[IFACE_ATTR_NETWORKID])) 583 ifname = blobmsg_get_string(c); 584 } 585 586 #ifdef WITH_UBUS 587 if (overwrite || !iface->ifname) 588 ifname = ubus_get_ifname(name); 589 #endif 590 591 if (!iface->ifname && !ifname) 592 goto err; 593 594 if (ifname) { 595 free(iface->ifname); 596 iface->ifname = strdup(ifname); 597 598 if (!iface->ifname) 599 goto err; 600 601 if (!iface->ifindex && 602 (iface->ifindex = if_nametoindex(iface->ifname)) <= 0) 603 goto err; 604 605 if ((iface->ifflags = odhcpd_get_flags(iface)) < 0) 606 goto err; 607 } 608 609 if (get_addrs) { 610 addrs_len = netlink_get_interface_addrs(iface->ifindex, 611 true, &iface->addr6); 612 613 if (addrs_len > 0) 614 iface->addr6_len = addrs_len; 615 616 addrs_len = netlink_get_interface_addrs(iface->ifindex, 617 false, &iface->addr4); 618 if (addrs_len > 0) 619 iface->addr4_len = addrs_len; 620 } 621 622 addrs_len = netlink_get_interface_linklocal(iface->ifindex, &addrs); 623 if (addrs_len > 0) { 624 for (ssize_t i = 0; i < addrs_len; i++) { 625 struct odhcpd_ipaddr *addr = &addrs[i]; 626 627 if (!addr->tentative) { 628 iface->have_link_local = true; 629 break; 630 } 631 } 632 } 633 634 iface->inuse = true; 635 636 if ((c = tb[IFACE_ATTR_DYNAMICDHCP])) 637 iface->no_dynamic_dhcp = !blobmsg_get_bool(c); 638 639 if ((c = tb[IFACE_ATTR_LEASETIME])) { 640 double time = parse_leasetime(c); 641 642 if (time >= 0) 643 iface->dhcp_leasetime = time; 644 else 645 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 646 iface_attrs[IFACE_ATTR_LEASETIME].name, iface->name); 647 648 } 649 650 if ((c = tb[IFACE_ATTR_PREFERRED_LIFETIME])) { 651 double time = parse_leasetime(c); 652 653 if (time >= 0) 654 iface->preferred_lifetime = time; 655 else 656 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 657 iface_attrs[IFACE_ATTR_PREFERRED_LIFETIME].name, iface->name); 658 659 } 660 661 if ((c = tb[IFACE_ATTR_START])) { 662 iface->dhcpv4_start.s_addr = htonl(blobmsg_get_u32(c)); 663 iface->dhcpv4_end.s_addr = htonl(ntohl(iface->dhcpv4_start.s_addr) + 664 LIMIT_DEFAULT - 1); 665 666 if (config.main_dhcpv4 && config.legacy) 667 iface->dhcpv4 = MODE_SERVER; 668 } 669 670 if ((c = tb[IFACE_ATTR_LIMIT])) 671 iface->dhcpv4_end.s_addr = htonl(ntohl(iface->dhcpv4_start.s_addr) + 672 blobmsg_get_u32(c) - 1); 673 674 if ((c = tb[IFACE_ATTR_MASTER])) 675 iface->master = blobmsg_get_bool(c); 676 677 if (overwrite && (c = tb[IFACE_ATTR_UPSTREAM])) { 678 struct blob_attr *cur; 679 unsigned rem; 680 681 blobmsg_for_each_attr(cur, c, rem) { 682 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 683 continue; 684 685 iface->upstream = realloc(iface->upstream, 686 iface->upstream_len + blobmsg_data_len(cur)); 687 if (!iface->upstream) 688 goto err; 689 690 memcpy(iface->upstream + iface->upstream_len, blobmsg_get_string(cur), blobmsg_data_len(cur)); 691 iface->upstream_len += blobmsg_data_len(cur); 692 } 693 } 694 695 if ((c = tb[IFACE_ATTR_RA])) { 696 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) { 697 iface->ra = mode; 698 699 if (iface->ra != MODE_DISABLED) 700 iface->ignore = false; 701 } else 702 syslog(LOG_ERR, "Invalid %s mode configured for interface '%s'", 703 iface_attrs[IFACE_ATTR_RA].name, iface->name); 704 } 705 706 if ((c = tb[IFACE_ATTR_DHCPV4])) { 707 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) { 708 if (config.main_dhcpv4) { 709 iface->dhcpv4 = mode; 710 711 if (iface->dhcpv4 != MODE_DISABLED) 712 iface->ignore = false; 713 } 714 } else 715 syslog(LOG_ERR, "Invalid %s mode configured for interface %s", 716 iface_attrs[IFACE_ATTR_DHCPV4].name, iface->name); 717 } 718 719 if ((c = tb[IFACE_ATTR_DHCPV6])) { 720 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) { 721 iface->dhcpv6 = mode; 722 723 if (iface->dhcpv6 != MODE_DISABLED) 724 iface->ignore = false; 725 } else 726 syslog(LOG_ERR, "Invalid %s mode configured for interface '%s'", 727 iface_attrs[IFACE_ATTR_DHCPV6].name, iface->name); 728 } 729 730 if ((c = tb[IFACE_ATTR_NDP])) { 731 if ((mode = parse_mode(blobmsg_get_string(c))) >= 0) { 732 iface->ndp = mode; 733 734 if (iface->ndp != MODE_DISABLED) 735 iface->ignore = false; 736 } else 737 syslog(LOG_ERR, "Invalid %s mode configured for interface '%s'", 738 iface_attrs[IFACE_ATTR_NDP].name, iface->name); 739 } 740 741 if ((c = tb[IFACE_ATTR_ROUTER])) { 742 struct blob_attr *cur; 743 unsigned rem; 744 745 blobmsg_for_each_attr(cur, c, rem) { 746 struct in_addr addr4; 747 748 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 749 continue; 750 751 if (inet_pton(AF_INET, blobmsg_get_string(cur), &addr4) == 1) { 752 iface->dhcpv4_router = realloc(iface->dhcpv4_router, 753 (++iface->dhcpv4_router_cnt) * sizeof(*iface->dhcpv4_router)); 754 if (!iface->dhcpv4_router) 755 goto err; 756 757 iface->dhcpv4_router[iface->dhcpv4_router_cnt - 1] = addr4; 758 } else 759 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 760 iface_attrs[IFACE_ATTR_ROUTER].name, iface->name); 761 } 762 } 763 764 if ((c = tb[IFACE_ATTR_DNS])) { 765 struct blob_attr *cur; 766 unsigned rem; 767 768 iface->always_rewrite_dns = true; 769 blobmsg_for_each_attr(cur, c, rem) { 770 struct in_addr addr4; 771 struct in6_addr addr6; 772 773 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 774 continue; 775 776 if (inet_pton(AF_INET, blobmsg_get_string(cur), &addr4) == 1) { 777 if (addr4.s_addr == INADDR_ANY) { 778 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 779 iface_attrs[IFACE_ATTR_DNS].name, iface->name); 780 781 continue; 782 } 783 784 iface->dhcpv4_dns = realloc(iface->dhcpv4_dns, 785 (++iface->dhcpv4_dns_cnt) * sizeof(*iface->dhcpv4_dns)); 786 if (!iface->dhcpv4_dns) 787 goto err; 788 789 iface->dhcpv4_dns[iface->dhcpv4_dns_cnt - 1] = addr4; 790 } else if (inet_pton(AF_INET6, blobmsg_get_string(cur), &addr6) == 1) { 791 if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) { 792 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 793 iface_attrs[IFACE_ATTR_DNS].name, iface->name); 794 795 continue; 796 } 797 798 iface->dns = realloc(iface->dns, 799 (++iface->dns_cnt) * sizeof(*iface->dns)); 800 if (!iface->dns) 801 goto err; 802 803 iface->dns[iface->dns_cnt - 1] = addr6; 804 } else 805 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 806 iface_attrs[IFACE_ATTR_DNS].name, iface->name); 807 } 808 } 809 810 if ((c = tb[IFACE_ATTR_DNS_SERVICE])) 811 iface->dns_service = blobmsg_get_bool(c); 812 813 if ((c = tb[IFACE_ATTR_DOMAIN])) { 814 struct blob_attr *cur; 815 unsigned rem; 816 817 blobmsg_for_each_attr(cur, c, rem) { 818 uint8_t buf[256]; 819 char *domain = blobmsg_get_string(cur); 820 size_t domainlen = strlen(domain); 821 int len; 822 823 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 824 continue; 825 826 domain = blobmsg_get_string(cur); 827 domainlen = strlen(domain); 828 829 if (domainlen > 0 && domain[domainlen - 1] == '.') 830 domain[domainlen - 1] = 0; 831 832 len = dn_comp(domain, buf, sizeof(buf), NULL, NULL); 833 if (len <= 0) { 834 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 835 iface_attrs[IFACE_ATTR_DOMAIN].name, iface->name); 836 837 continue; 838 } 839 840 iface->search = realloc(iface->search, iface->search_len + len); 841 if (!iface->search) 842 goto err; 843 844 memcpy(&iface->search[iface->search_len], buf, len); 845 iface->search_len += len; 846 } 847 } 848 849 if ((c = tb[IFACE_ATTR_FILTER_CLASS])) { 850 iface->filter_class = realloc(iface->filter_class, blobmsg_data_len(c) + 1); 851 memcpy(iface->filter_class, blobmsg_get_string(c), blobmsg_data_len(c) + 1); 852 } 853 854 if ((c = tb[IFACE_ATTR_DHCPV4_FORCERECONF])) 855 iface->dhcpv4_forcereconf = blobmsg_get_bool(c); 856 857 if ((c = tb[IFACE_ATTR_DHCPV6_RAW])) { 858 iface->dhcpv6_raw_len = blobmsg_data_len(c) / 2; 859 iface->dhcpv6_raw = realloc(iface->dhcpv6_raw, iface->dhcpv6_raw_len); 860 odhcpd_unhexlify(iface->dhcpv6_raw, iface->dhcpv6_raw_len, blobmsg_get_string(c)); 861 } 862 863 if ((c = tb[IFACE_ATTR_DHCPV6_ASSIGNALL])) 864 iface->dhcpv6_assignall = blobmsg_get_bool(c); 865 866 if ((c = tb[IFACE_ATTR_DHCPV6_PD])) 867 iface->dhcpv6_pd = blobmsg_get_bool(c); 868 869 if ((c = tb[IFACE_ATTR_DHCPV6_PD_MIN_LEN])) { 870 uint32_t pd_min_len = blobmsg_get_u32(c); 871 if (pd_min_len != 0 && pd_min_len <= PD_MIN_LEN_MAX) 872 iface->dhcpv6_pd_min_len = pd_min_len; 873 else 874 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 875 iface_attrs[IFACE_ATTR_DHCPV6_PD_MIN_LEN].name, iface->name); 876 } 877 878 if ((c = tb[IFACE_ATTR_DHCPV6_NA])) 879 iface->dhcpv6_na = blobmsg_get_bool(c); 880 881 if ((c = tb[IFACE_ATTR_DHCPV6_HOSTID_LEN])) { 882 uint32_t hostid_len = blobmsg_get_u32(c); 883 884 if (hostid_len >= HOSTID_LEN_MIN && hostid_len <= HOSTID_LEN_MAX) 885 iface->dhcpv6_hostid_len = hostid_len; 886 else 887 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 888 iface_attrs[IFACE_ATTR_DHCPV6_HOSTID_LEN].name, iface->name); 889 890 } 891 892 if ((c = tb[IFACE_ATTR_RA_DEFAULT])) 893 iface->default_router = blobmsg_get_u32(c); 894 895 if (!tb[IFACE_ATTR_RA_FLAGS] && !tb[IFACE_ATTR_RA_SLAAC] && 896 (c = tb[IFACE_ATTR_RA_MANAGEMENT])) { 897 switch (blobmsg_get_u32(c)) { 898 case 0: 899 iface->ra_flags = ND_RA_FLAG_OTHER; 900 iface->ra_slaac = true; 901 break; 902 case 1: 903 iface->ra_flags = ND_RA_FLAG_OTHER|ND_RA_FLAG_MANAGED; 904 iface->ra_slaac = true; 905 break; 906 case 2: 907 iface->ra_flags = ND_RA_FLAG_OTHER|ND_RA_FLAG_MANAGED; 908 iface->ra_slaac = false; 909 break; 910 default: 911 break; 912 } 913 } 914 915 if ((c = tb[IFACE_ATTR_RA_FLAGS])) { 916 iface->ra_flags = 0; 917 918 if (parse_ra_flags(&iface->ra_flags, c) < 0) 919 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 920 iface_attrs[IFACE_ATTR_RA_FLAGS].name, iface->name); 921 } 922 923 if ((c = tb[IFACE_ATTR_RA_REACHABLETIME])) { 924 uint32_t ra_reachabletime = blobmsg_get_u32(c); 925 926 if (ra_reachabletime <= 3600000) 927 iface->ra_reachabletime = ra_reachabletime; 928 else 929 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 930 iface_attrs[IFACE_ATTR_RA_REACHABLETIME].name, iface->name); 931 } 932 933 if ((c = tb[IFACE_ATTR_RA_RETRANSTIME])) { 934 uint32_t ra_retranstime = blobmsg_get_u32(c); 935 936 if (ra_retranstime <= 60000) 937 iface->ra_retranstime = ra_retranstime; 938 else 939 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 940 iface_attrs[IFACE_ATTR_RA_RETRANSTIME].name, iface->name); 941 } 942 943 if ((c = tb[IFACE_ATTR_RA_HOPLIMIT])) { 944 uint32_t ra_hoplimit = blobmsg_get_u32(c); 945 946 if (ra_hoplimit <= 255) 947 iface->ra_hoplimit = ra_hoplimit; 948 else 949 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 950 iface_attrs[IFACE_ATTR_RA_HOPLIMIT].name, iface->name); 951 } 952 953 if ((c = tb[IFACE_ATTR_RA_MTU])) { 954 uint32_t ra_mtu = blobmsg_get_u32(c); 955 956 if (ra_mtu >= 1280 || ra_mtu <= 65535) 957 iface->ra_mtu = ra_mtu; 958 else 959 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 960 iface_attrs[IFACE_ATTR_RA_MTU].name, iface->name); 961 } 962 963 if ((c = tb[IFACE_ATTR_RA_SLAAC])) 964 iface->ra_slaac = blobmsg_get_bool(c); 965 966 if ((c = tb[IFACE_ATTR_RA_OFFLINK])) 967 iface->ra_not_onlink = blobmsg_get_bool(c); 968 969 if ((c = tb[IFACE_ATTR_RA_ADVROUTER])) 970 iface->ra_advrouter = blobmsg_get_bool(c); 971 972 if ((c = tb[IFACE_ATTR_RA_MININTERVAL])) 973 iface->ra_mininterval = blobmsg_get_u32(c); 974 975 if ((c = tb[IFACE_ATTR_RA_MAXINTERVAL])) 976 iface->ra_maxinterval = blobmsg_get_u32(c); 977 978 if ((c = tb[IFACE_ATTR_RA_LIFETIME])) 979 iface->ra_lifetime = blobmsg_get_u32(c); 980 981 if ((c = tb[IFACE_ATTR_RA_USELEASETIME])) 982 iface->ra_useleasetime = blobmsg_get_bool(c); 983 984 if ((c = tb[IFACE_ATTR_RA_DNS])) 985 iface->ra_dns = blobmsg_get_bool(c); 986 987 if ((c = tb[IFACE_ATTR_RA_PREF64])) { 988 const char *str = blobmsg_get_string(c); 989 char *astr = malloc(strlen(str) + 1); 990 char *delim; 991 int l; 992 993 if (!astr || !strcpy(astr, str) || 994 (delim = strchr(astr, '/')) == NULL || (*(delim++) = 0) || 995 sscanf(delim, "%i", &l) == 0 || l > 128 || 996 inet_pton(AF_INET6, astr, &iface->pref64_addr) == 0) 997 iface->pref64_length = 0; 998 else 999 iface->pref64_length = l; 1000 1001 if (astr) 1002 free(astr); 1003 } 1004 1005 if ((c = tb[IFACE_ATTR_RA_PREFERENCE])) { 1006 const char *prio = blobmsg_get_string(c); 1007 1008 if (!strcmp(prio, "high")) 1009 iface->route_preference = 1; 1010 else if (!strcmp(prio, "low")) 1011 iface->route_preference = -1; 1012 else if (!strcmp(prio, "medium") || !strcmp(prio, "default")) 1013 iface->route_preference = 0; 1014 else 1015 syslog(LOG_ERR, "Invalid %s mode configured for interface '%s'", 1016 iface_attrs[IFACE_ATTR_RA_PREFERENCE].name, iface->name); 1017 } 1018 1019 if ((c = tb[IFACE_ATTR_PD_MANAGER])) 1020 strncpy(iface->dhcpv6_pd_manager, blobmsg_get_string(c), 1021 sizeof(iface->dhcpv6_pd_manager) - 1); 1022 1023 if ((c = tb[IFACE_ATTR_PD_CER]) && 1024 inet_pton(AF_INET6, blobmsg_get_string(c), &iface->dhcpv6_pd_cer) < 1) 1025 syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", 1026 iface_attrs[IFACE_ATTR_PD_CER].name, iface->name); 1027 1028 if ((c = tb[IFACE_ATTR_NDPROXY_ROUTING])) 1029 iface->learn_routes = blobmsg_get_bool(c); 1030 1031 if ((c = tb[IFACE_ATTR_NDPROXY_SLAVE])) 1032 iface->external = blobmsg_get_bool(c); 1033 1034 if ((c = tb[IFACE_ATTR_PREFIX_FILTER])) { 1035 const char *str = blobmsg_get_string(c); 1036 char *astr = malloc(strlen(str) + 1); 1037 char *delim; 1038 int l; 1039 1040 if (!astr || !strcpy(astr, str) || 1041 (delim = strchr(astr, '/')) == NULL || (*(delim++) = 0) || 1042 sscanf(delim, "%i", &l) == 0 || l > 128 || 1043 inet_pton(AF_INET6, astr, &iface->pio_filter_addr) == 0) 1044 iface->pio_filter_length = 0; 1045 else 1046 iface->pio_filter_length = l; 1047 1048 if (astr) 1049 free(astr); 1050 } 1051 1052 if (overwrite && (c = tb[IFACE_ATTR_NTP])) { 1053 struct blob_attr *cur; 1054 unsigned rem; 1055 1056 blobmsg_for_each_attr(cur, c, rem) { 1057 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false)) 1058 continue; 1059 1060 char *str = blobmsg_get_string(cur); 1061 struct in_addr addr4; 1062 struct in6_addr addr6; 1063 1064 if (inet_pton(AF_INET, str, &addr4) == 1) { 1065 if (addr4.s_addr == INADDR_ANY) 1066 goto err; 1067 1068 iface->dhcpv4_ntp = realloc(iface->dhcpv4_ntp, 1069 (++iface->dhcpv4_ntp_cnt) * sizeof(*iface->dhcpv4_ntp)); 1070 if (!iface->dhcpv4_ntp) 1071 goto err; 1072 1073 iface->dhcpv4_ntp[iface->dhcpv4_ntp_cnt - 1] = addr4; 1074 } else if (inet_pton(AF_INET6, str, &addr6) == 1) { 1075 if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) 1076 goto err; 1077 1078 iface->dhcpv6_sntp = realloc(iface->dhcpv6_sntp, 1079 (++iface->dhcpv6_sntp_cnt) * sizeof(*iface->dhcpv6_sntp)); 1080 if (!iface->dhcpv6_sntp) 1081 goto err; 1082 1083 iface->dhcpv6_sntp[iface->dhcpv6_sntp_cnt - 1] = addr6; 1084 1085 if (!parse_ntp_options(&iface->dhcpv6_ntp_len, addr6, &iface->dhcpv6_ntp)) 1086 iface->dhcpv6_ntp_cnt++; 1087 } else { 1088 if (!parse_ntp_fqdn(&iface->dhcpv6_ntp_len, str, &iface->dhcpv6_ntp)) 1089 iface->dhcpv6_ntp_cnt++; 1090 } 1091 } 1092 } 1093 1094 return 0; 1095 1096 err: 1097 close_interface(iface); 1098 return -1; 1099 } 1100 1101 static int set_interface(struct uci_section *s) 1102 { 1103 blob_buf_init(&b, 0); 1104 uci_to_blob(&b, s, &interface_attr_list); 1105 1106 return config_parse_interface(blob_data(b.head), blob_len(b.head), s->e.name, true); 1107 } 1108 1109 static void lease_delete_assignments(struct lease *l, bool v6) 1110 { 1111 struct dhcp_assignment *a, *tmp; 1112 unsigned int flag = v6 ? OAF_DHCPV6 : OAF_DHCPV4; 1113 1114 list_for_each_entry_safe(a, tmp, &l->assignments, lease_list) { 1115 if (a->flags & flag) 1116 free_assignment(a); 1117 } 1118 } 1119 1120 static void lease_update_assignments(struct lease *l) 1121 { 1122 struct dhcp_assignment *a; 1123 1124 list_for_each_entry(a, &l->assignments, lease_list) { 1125 if (a->hostname) 1126 free(a->hostname); 1127 a->hostname = NULL; 1128 1129 if (l->hostname) 1130 a->hostname = strdup(l->hostname); 1131 1132 a->leasetime = l->leasetime; 1133 } 1134 } 1135 1136 static int lease_cmp(const void *k1, const void *k2, _unused void *ptr) 1137 { 1138 const struct lease *l1 = k1, *l2 = k2; 1139 int cmp = 0; 1140 1141 if (l1->duid_len != l2->duid_len) 1142 return l1->duid_len - l2->duid_len; 1143 1144 if (l1->duid_len && l2->duid_len) 1145 cmp = memcmp(l1->duid, l2->duid, l1->duid_len); 1146 1147 if (cmp) 1148 return cmp; 1149 1150 return memcmp(l1->mac.ether_addr_octet, l2->mac.ether_addr_octet, 1151 sizeof(l1->mac.ether_addr_octet)); 1152 } 1153 1154 static void lease_change_config(struct lease *l_old, struct lease *l_new) 1155 { 1156 bool update = false; 1157 1158 if ((!!l_new->hostname != !!l_old->hostname) || 1159 (l_new->hostname && strcmp(l_new->hostname, l_old->hostname))) { 1160 free(l_old->hostname); 1161 l_old->hostname = NULL; 1162 1163 if (l_new->hostname) 1164 l_old->hostname = strdup(l_new->hostname); 1165 1166 update = true; 1167 } 1168 1169 if (l_old->leasetime != l_new->leasetime) { 1170 l_old->leasetime = l_new->leasetime; 1171 update = true; 1172 } 1173 1174 if (l_old->ipaddr != l_new->ipaddr) { 1175 l_old->ipaddr = l_new->ipaddr; 1176 lease_delete_assignments(l_old, false); 1177 } 1178 1179 if (l_old->hostid != l_new->hostid) { 1180 l_old->hostid = l_new->hostid; 1181 lease_delete_assignments(l_old, true); 1182 } 1183 1184 if (update) 1185 lease_update_assignments(l_old); 1186 1187 free_lease(l_new); 1188 } 1189 1190 static void lease_delete(struct lease *l) 1191 { 1192 struct dhcp_assignment *a, *tmp; 1193 1194 list_for_each_entry_safe(a, tmp, &l->assignments, lease_list) 1195 free_assignment(a); 1196 1197 free_lease(l); 1198 } 1199 1200 static void lease_update(_unused struct vlist_tree *tree, struct vlist_node *node_new, 1201 struct vlist_node *node_old) 1202 { 1203 struct lease *lease_new = container_of(node_new, struct lease, node); 1204 struct lease *lease_old = container_of(node_old, struct lease, node); 1205 1206 if (node_old && node_new) 1207 lease_change_config(lease_old, lease_new); 1208 else if (node_old) 1209 lease_delete(lease_old); 1210 } 1211 1212 struct lease *config_find_lease_by_duid(const uint8_t *duid, const uint16_t len) 1213 { 1214 struct lease *l; 1215 1216 vlist_for_each_element(&leases, l, node) { 1217 if (l->duid_len == len && !memcmp(l->duid, duid, len)) 1218 return l; 1219 } 1220 1221 return NULL; 1222 } 1223 1224 struct lease *config_find_lease_by_mac(const uint8_t *mac) 1225 { 1226 struct lease *l; 1227 1228 vlist_for_each_element(&leases, l, node) { 1229 if (!memcmp(l->mac.ether_addr_octet, mac, 1230 sizeof(l->mac.ether_addr_octet))) 1231 return l; 1232 } 1233 1234 return NULL; 1235 } 1236 1237 struct lease *config_find_lease_by_hostid(const uint64_t hostid) 1238 { 1239 struct lease *l; 1240 1241 vlist_for_each_element(&leases, l, node) { 1242 if (l->hostid == hostid) 1243 return l; 1244 } 1245 1246 return NULL; 1247 } 1248 1249 struct lease *config_find_lease_by_ipaddr(const uint32_t ipaddr) 1250 { 1251 struct lease *l; 1252 1253 vlist_for_each_element(&leases, l, node) { 1254 if (l->ipaddr == ipaddr) 1255 return l; 1256 } 1257 1258 return NULL; 1259 } 1260 1261 void reload_services(struct interface *iface) 1262 { 1263 if (iface->ifflags & IFF_RUNNING) { 1264 syslog(LOG_DEBUG, "Enabling services with %s running", iface->ifname); 1265 router_setup_interface(iface, iface->ra != MODE_DISABLED); 1266 dhcpv6_setup_interface(iface, iface->dhcpv6 != MODE_DISABLED); 1267 ndp_setup_interface(iface, iface->ndp != MODE_DISABLED); 1268 #ifdef DHCPV4_SUPPORT 1269 dhcpv4_setup_interface(iface, iface->dhcpv4 != MODE_DISABLED); 1270 #endif 1271 } else { 1272 syslog(LOG_DEBUG, "Disabling services with %s not running", iface->ifname); 1273 router_setup_interface(iface, false); 1274 dhcpv6_setup_interface(iface, false); 1275 ndp_setup_interface(iface, false); 1276 #ifdef DHCPV4_SUPPORT 1277 dhcpv4_setup_interface(iface, false); 1278 #endif 1279 } 1280 } 1281 1282 void odhcpd_reload(void) 1283 { 1284 struct uci_context *uci = uci_alloc_context(); 1285 struct interface *master = NULL, *i, *tmp; 1286 1287 if (!uci) 1288 return; 1289 1290 vlist_update(&leases); 1291 avl_for_each_element(&interfaces, i, avl) 1292 clean_interface(i); 1293 1294 struct uci_package *dhcp = NULL; 1295 if (!uci_load(uci, "dhcp", &dhcp)) { 1296 struct uci_element *e; 1297 1298 /* 1. Global settings */ 1299 uci_foreach_element(&dhcp->sections, e) { 1300 struct uci_section *s = uci_to_section(e); 1301 if (!strcmp(s->type, "odhcpd")) 1302 set_config(s); 1303 } 1304 1305 /* 2. DHCP pools */ 1306 uci_foreach_element(&dhcp->sections, e) { 1307 struct uci_section *s = uci_to_section(e); 1308 if (!strcmp(s->type, "dhcp")) 1309 set_interface(s); 1310 } 1311 1312 /* 3. Static leases */ 1313 uci_foreach_element(&dhcp->sections, e) { 1314 struct uci_section* s = uci_to_section(e); 1315 if (!strcmp(s->type, "host")) 1316 set_lease_from_uci(s); 1317 } 1318 } 1319 1320 if (config.dhcp_statefile) { 1321 char *path = strdup(config.dhcp_statefile); 1322 1323 mkdir_p(dirname(path), 0755); 1324 free(path); 1325 } 1326 1327 vlist_flush(&leases); 1328 1329 #ifdef WITH_UBUS 1330 ubus_apply_network(); 1331 #endif 1332 1333 bool any_dhcpv6_slave = false, any_ra_slave = false, any_ndp_slave = false; 1334 1335 /* Test for */ 1336 avl_for_each_element(&interfaces, i, avl) { 1337 if (i->master) 1338 continue; 1339 1340 if (i->dhcpv6 == MODE_HYBRID || i->dhcpv6 == MODE_RELAY) 1341 any_dhcpv6_slave = true; 1342 1343 if (i->ra == MODE_HYBRID || i->ra == MODE_RELAY) 1344 any_ra_slave = true; 1345 1346 if (i->ndp == MODE_HYBRID || i->ndp == MODE_RELAY) 1347 any_ndp_slave = true; 1348 } 1349 1350 /* Evaluate hybrid mode for master */ 1351 avl_for_each_element(&interfaces, i, avl) { 1352 if (!i->master) 1353 continue; 1354 1355 enum odhcpd_mode hybrid_mode = MODE_DISABLED; 1356 #ifdef WITH_UBUS 1357 if (!ubus_has_prefix(i->name, i->ifname)) 1358 hybrid_mode = MODE_RELAY; 1359 #endif 1360 1361 if (i->dhcpv6 == MODE_HYBRID) 1362 i->dhcpv6 = hybrid_mode; 1363 1364 if (i->dhcpv6 == MODE_RELAY && !any_dhcpv6_slave) 1365 i->dhcpv6 = MODE_DISABLED; 1366 1367 if (i->ra == MODE_HYBRID) 1368 i->ra = hybrid_mode; 1369 1370 if (i->ra == MODE_RELAY && !any_ra_slave) 1371 i->ra = MODE_DISABLED; 1372 1373 if (i->ndp == MODE_HYBRID) 1374 i->ndp = hybrid_mode; 1375 1376 if (i->ndp == MODE_RELAY && !any_ndp_slave) 1377 i->ndp = MODE_DISABLED; 1378 1379 if (i->dhcpv6 == MODE_RELAY || i->ra == MODE_RELAY || i->ndp == MODE_RELAY) 1380 master = i; 1381 } 1382 1383 1384 avl_for_each_element_safe(&interfaces, i, avl, tmp) { 1385 if (i->inuse && i->ifflags & IFF_RUNNING) { 1386 /* Resolve hybrid mode */ 1387 if (i->dhcpv6 == MODE_HYBRID) 1388 i->dhcpv6 = (master && master->dhcpv6 == MODE_RELAY) ? 1389 MODE_RELAY : MODE_SERVER; 1390 1391 if (i->ra == MODE_HYBRID) 1392 i->ra = (master && master->ra == MODE_RELAY) ? 1393 MODE_RELAY : MODE_SERVER; 1394 1395 if (i->ndp == MODE_HYBRID) 1396 i->ndp = (master && master->ndp == MODE_RELAY) ? 1397 MODE_RELAY : MODE_DISABLED; 1398 1399 reload_services(i); 1400 } else 1401 close_interface(i); 1402 } 1403 1404 uci_unload(uci, dhcp); 1405 uci_free_context(uci); 1406 } 1407 1408 static void handle_signal(int signal) 1409 { 1410 char b[1] = {0}; 1411 1412 if (signal == SIGHUP) { 1413 if (write(reload_pipe[1], b, sizeof(b)) < 0) {} 1414 } else 1415 uloop_end(); 1416 } 1417 1418 static void reload_cb(struct uloop_fd *u, _unused unsigned int events) 1419 { 1420 char b[512]; 1421 if (read(u->fd, b, sizeof(b)) < 0) {} 1422 1423 odhcpd_reload(); 1424 } 1425 1426 static struct uloop_fd reload_fd = { .fd = -1, .cb = reload_cb }; 1427 1428 void odhcpd_run(void) 1429 { 1430 if (pipe2(reload_pipe, O_NONBLOCK | O_CLOEXEC) < 0) {} 1431 1432 reload_fd.fd = reload_pipe[0]; 1433 uloop_fd_add(&reload_fd, ULOOP_READ); 1434 1435 signal(SIGTERM, handle_signal); 1436 signal(SIGINT, handle_signal); 1437 signal(SIGHUP, handle_signal); 1438 1439 #ifdef WITH_UBUS 1440 while (ubus_init()) 1441 sleep(1); 1442 #endif 1443 1444 odhcpd_reload(); 1445 uloop_run(); 1446 } 1447
This page was automatically generated by LXR 0.3.1. • OpenWrt