1 /** 2 * Copyright (C) 2013 Steven Barth <steven@midlink.org> 3 * Copyright (C) 2016 Hans Dedecker <dedeckeh@gmail.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License v2 as published by 7 * the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 */ 15 16 #include "odhcpd.h" 17 #include "dhcpv6.h" 18 #include "dhcpv4.h" 19 20 #include <time.h> 21 #include <errno.h> 22 #include <fcntl.h> 23 #include <stdio.h> 24 #include <poll.h> 25 #include <alloca.h> 26 #include <resolv.h> 27 #include <limits.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <unistd.h> 31 #include <libgen.h> 32 #include <stdbool.h> 33 #include <arpa/inet.h> 34 #include <sys/timerfd.h> 35 36 #include <libubox/md5.h> 37 #include <libubox/usock.h> 38 39 #define ADDR_ENTRY_VALID_IA_ADDR(iface, i, m, addrs) \ 40 ((iface)->dhcpv6_assignall || (i) == (m) || \ 41 (addrs)[(i)].prefix > 64) 42 43 static void dhcpv6_netevent_cb(unsigned long event, struct netevent_handler_info *info); 44 static void apply_lease(struct dhcp_assignment *a, bool add); 45 static void set_border_assignment_size(struct interface *iface, struct dhcp_assignment *b); 46 static void handle_addrlist_change(struct netevent_handler_info *info); 47 static void start_reconf(struct dhcp_assignment *a); 48 static void stop_reconf(struct dhcp_assignment *a); 49 static void valid_until_cb(struct uloop_timeout *event); 50 51 static struct netevent_handler dhcpv6_netevent_handler = { .cb = dhcpv6_netevent_cb, }; 52 static struct uloop_timeout valid_until_timeout = {.cb = valid_until_cb}; 53 static uint32_t serial = 0; 54 static uint8_t statemd5[16]; 55 56 int dhcpv6_ia_init(void) 57 { 58 uloop_timeout_set(&valid_until_timeout, 1000); 59 60 netlink_add_netevent_handler(&dhcpv6_netevent_handler); 61 62 return 0; 63 } 64 65 int dhcpv6_ia_setup_interface(struct interface *iface, bool enable) 66 { 67 enable = enable && (iface->dhcpv6 == MODE_SERVER); 68 69 if (enable) { 70 struct dhcp_assignment *border; 71 72 if (list_empty(&iface->ia_assignments)) { 73 border = alloc_assignment(0); 74 75 if (!border) { 76 syslog(LOG_WARNING, "Failed to alloc border on %s", iface->name); 77 return -1; 78 } 79 80 border->length = 64; 81 list_add(&border->head, &iface->ia_assignments); 82 } else 83 border = list_last_entry(&iface->ia_assignments, struct dhcp_assignment, head); 84 85 set_border_assignment_size(iface, border); 86 } else { 87 struct dhcp_assignment *c; 88 89 while (!list_empty(&iface->ia_assignments)) { 90 c = list_first_entry(&iface->ia_assignments, struct dhcp_assignment, head); 91 free_assignment(c); 92 } 93 } 94 95 return 0; 96 } 97 98 99 static void dhcpv6_netevent_cb(unsigned long event, struct netevent_handler_info *info) 100 { 101 struct interface *iface = info->iface; 102 103 if (!iface || iface->dhcpv6 != MODE_SERVER) 104 return; 105 106 switch (event) { 107 case NETEV_ADDR6LIST_CHANGE: 108 handle_addrlist_change(info); 109 break; 110 default: 111 break; 112 } 113 } 114 115 116 static inline bool valid_prefix_length(const struct dhcp_assignment *a, const uint8_t prefix_length) 117 { 118 return (a->managed_size || a->length > prefix_length); 119 } 120 121 static inline bool valid_addr(const struct odhcpd_ipaddr *addr, time_t now) 122 { 123 return (addr->prefix <= 96 && addr->preferred > (uint32_t)now); 124 } 125 126 static size_t get_preferred_addr(const struct odhcpd_ipaddr *addrs, const size_t addrlen) 127 { 128 size_t i, m; 129 130 for (i = 0, m = 0; i < addrlen; ++i) { 131 if (addrs[i].preferred > addrs[m].preferred || 132 (addrs[i].preferred == addrs[m].preferred && 133 memcmp(&addrs[i].addr, &addrs[m].addr, 16) > 0)) 134 m = i; 135 } 136 137 return m; 138 } 139 140 static int send_reconf(struct dhcp_assignment *assign) 141 { 142 struct { 143 struct dhcpv6_client_header hdr; 144 uint16_t srvid_type; 145 uint16_t srvid_len; 146 uint16_t duid_type; 147 uint16_t hardware_type; 148 uint8_t mac[6]; 149 uint16_t msg_type; 150 uint16_t msg_len; 151 uint8_t msg_id; 152 struct dhcpv6_auth_reconfigure auth; 153 uint16_t clid_type; 154 uint16_t clid_len; 155 uint8_t clid_data[128]; 156 } __attribute__((packed)) reconf_msg = { 157 .hdr = {DHCPV6_MSG_RECONFIGURE, {0, 0, 0}}, 158 .srvid_type = htons(DHCPV6_OPT_SERVERID), 159 .srvid_len = htons(10), 160 .duid_type = htons(3), 161 .hardware_type = htons(1), 162 .msg_type = htons(DHCPV6_OPT_RECONF_MSG), 163 .msg_len = htons(1), 164 .msg_id = DHCPV6_MSG_RENEW, 165 .auth = {htons(DHCPV6_OPT_AUTH), 166 htons(sizeof(reconf_msg.auth) - 4), 3, 1, 0, 167 {htonl(time(NULL)), htonl(++serial)}, 2, {0}}, 168 .clid_type = htons(DHCPV6_OPT_CLIENTID), 169 .clid_len = htons(assign->clid_len), 170 .clid_data = {0}, 171 }; 172 struct interface *iface = assign->iface; 173 174 odhcpd_get_mac(iface, reconf_msg.mac); 175 memcpy(reconf_msg.clid_data, assign->clid_data, assign->clid_len); 176 struct iovec iov = {&reconf_msg, sizeof(reconf_msg) - 128 + assign->clid_len}; 177 178 md5_ctx_t md5; 179 uint8_t secretbytes[64]; 180 memset(secretbytes, 0, sizeof(secretbytes)); 181 memcpy(secretbytes, assign->key, sizeof(assign->key)); 182 183 for (size_t i = 0; i < sizeof(secretbytes); ++i) 184 secretbytes[i] ^= 0x36; 185 186 md5_begin(&md5); 187 md5_hash(secretbytes, sizeof(secretbytes), &md5); 188 md5_hash(iov.iov_base, iov.iov_len, &md5); 189 md5_end(reconf_msg.auth.key, &md5); 190 191 for (size_t i = 0; i < sizeof(secretbytes); ++i) { 192 secretbytes[i] ^= 0x36; 193 secretbytes[i] ^= 0x5c; 194 } 195 196 md5_begin(&md5); 197 md5_hash(secretbytes, sizeof(secretbytes), &md5); 198 md5_hash(reconf_msg.auth.key, 16, &md5); 199 md5_end(reconf_msg.auth.key, &md5); 200 201 return odhcpd_send(iface->dhcpv6_event.uloop.fd, &assign->peer, &iov, 1, iface); 202 } 203 204 static void dhcpv6_ia_free_assignment(struct dhcp_assignment *a) 205 { 206 if (a->managed_sock.fd.registered) { 207 ustream_free(&a->managed_sock.stream); 208 close(a->managed_sock.fd.fd); 209 } 210 211 if ((a->flags & OAF_BOUND) && (a->flags & OAF_DHCPV6_PD)) 212 apply_lease(a, false); 213 214 if (a->reconf_cnt) 215 stop_reconf(a); 216 217 free(a->managed); 218 } 219 220 void dhcpv6_ia_enum_addrs(struct interface *iface, struct dhcp_assignment *c, 221 time_t now, dhcpv6_binding_cb_handler_t func, void *arg) 222 { 223 struct odhcpd_ipaddr *addrs = (c->managed) ? c->managed : iface->addr6; 224 size_t addrlen = (c->managed) ? (size_t)c->managed_size : iface->addr6_len; 225 size_t m = get_preferred_addr(addrs, addrlen); 226 227 for (size_t i = 0; i < addrlen; ++i) { 228 struct in6_addr addr; 229 uint32_t pref, valid; 230 int prefix = c->managed ? addrs[i].prefix : c->length; 231 232 if (!valid_addr(&addrs[i], now)) 233 continue; 234 235 /* Filter Out Prefixes */ 236 if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface)) { 237 char addrbuf[INET6_ADDRSTRLEN]; 238 syslog(LOG_INFO, "Address %s filtered out on %s", 239 inet_ntop(AF_INET6, &addrs[i].addr.in6, addrbuf, sizeof(addrbuf)), 240 iface->name); 241 continue; 242 } 243 244 addr = addrs[i].addr.in6; 245 pref = addrs[i].preferred; 246 valid = addrs[i].valid; 247 248 if (c->flags & OAF_DHCPV6_NA) { 249 if (!ADDR_ENTRY_VALID_IA_ADDR(iface, i, m, addrs)) 250 continue; 251 252 addr.s6_addr32[2] = htonl(c->assigned_host_id >> 32); 253 addr.s6_addr32[3] = htonl(c->assigned_host_id & UINT32_MAX); 254 } else { 255 if (!valid_prefix_length(c, addrs[i].prefix)) 256 continue; 257 258 addr.s6_addr32[1] |= htonl(c->assigned_subnet_id); 259 addr.s6_addr32[2] = addr.s6_addr32[3] = 0; 260 } 261 262 if (pref > (uint32_t)c->preferred_until) 263 pref = c->preferred_until; 264 265 if (pref > (uint32_t)c->valid_until) 266 pref = c->valid_until; 267 268 if (pref != UINT32_MAX) 269 pref -= now; 270 271 if (valid > (uint32_t)c->valid_until) 272 valid = c->valid_until; 273 274 if (valid != UINT32_MAX) 275 valid -= now; 276 277 func(&addr, prefix, pref, valid, arg); 278 } 279 } 280 281 struct write_ctxt { 282 FILE *fp; 283 md5_ctx_t md5; 284 struct dhcp_assignment *c; 285 struct interface *iface; 286 char *buf; 287 int buf_len; 288 int buf_idx; 289 }; 290 291 static void dhcpv6_write_ia_addrhosts(struct in6_addr *addr, int prefix, _unused uint32_t pref, 292 _unused uint32_t valid, void *arg) 293 { 294 struct write_ctxt *ctxt = (struct write_ctxt *)arg; 295 char ipbuf[INET6_ADDRSTRLEN]; 296 297 if ((ctxt->c->flags & OAF_DHCPV6_NA) && ctxt->c->hostname && 298 !(ctxt->c->flags & OAF_BROKEN_HOSTNAME)) { 299 inet_ntop(AF_INET6, addr, ipbuf, sizeof(ipbuf) - 1); 300 fputs(ipbuf, ctxt->fp); 301 302 char b[256]; 303 if (dn_expand(ctxt->iface->search, ctxt->iface->search + ctxt->iface->search_len, 304 ctxt->iface->search, b, sizeof(b)) > 0) 305 fprintf(ctxt->fp, "\t%s.%s", ctxt->c->hostname, b); 306 307 fprintf(ctxt->fp, "\t%s\n", ctxt->c->hostname); 308 } 309 } 310 311 static void dhcpv6_write_ia_addr(struct in6_addr *addr, int prefix, _unused uint32_t pref, 312 _unused uint32_t valid, void *arg) 313 { 314 struct write_ctxt *ctxt = (struct write_ctxt *)arg; 315 char ipbuf[INET6_ADDRSTRLEN]; 316 317 inet_ntop(AF_INET6, addr, ipbuf, sizeof(ipbuf) - 1); 318 319 if ((ctxt->c->flags & OAF_DHCPV6_NA) && ctxt->c->hostname && 320 !(ctxt->c->flags & OAF_BROKEN_HOSTNAME)) { 321 fputs(ipbuf, ctxt->fp); 322 323 char b[256]; 324 if (dn_expand(ctxt->iface->search, ctxt->iface->search + ctxt->iface->search_len, 325 ctxt->iface->search, b, sizeof(b)) > 0) 326 fprintf(ctxt->fp, "\t%s.%s", ctxt->c->hostname, b); 327 328 fprintf(ctxt->fp, "\t%s\n", ctxt->c->hostname); 329 md5_hash(ipbuf, strlen(ipbuf), &ctxt->md5); 330 md5_hash(ctxt->c->hostname, strlen(ctxt->c->hostname), &ctxt->md5); 331 } 332 333 ctxt->buf_idx += snprintf(ctxt->buf + ctxt->buf_idx,ctxt->buf_len - ctxt->buf_idx, 334 "%s/%d ", ipbuf, prefix); 335 } 336 337 static void dhcpv6_ia_write_hostsfile(time_t now) 338 { 339 struct write_ctxt ctxt; 340 341 unsigned hostsfile_strlen = strlen(config.dhcp_hostsfile) + 1; 342 unsigned tmp_hostsfile_strlen = hostsfile_strlen + 1; /* space for . */ 343 char *tmp_hostsfile = alloca(tmp_hostsfile_strlen); 344 345 char *dir_hostsfile; 346 char *base_hostsfile; 347 char *pdir_hostsfile; 348 char *pbase_hostsfile; 349 350 int fd, ret; 351 352 dir_hostsfile = strndup(config.dhcp_hostsfile, hostsfile_strlen); 353 base_hostsfile = strndup(config.dhcp_hostsfile, hostsfile_strlen); 354 355 pdir_hostsfile = dirname(dir_hostsfile); 356 pbase_hostsfile = basename(base_hostsfile); 357 358 snprintf(tmp_hostsfile, tmp_hostsfile_strlen, "%s/.%s", pdir_hostsfile, pbase_hostsfile); 359 360 free(dir_hostsfile); 361 free(base_hostsfile); 362 363 fd = open(tmp_hostsfile, O_CREAT | O_WRONLY | O_CLOEXEC, 0644); 364 if (fd < 0) 365 return; 366 367 ret = lockf(fd, F_LOCK, 0); 368 if (ret < 0) { 369 close(fd); 370 return; 371 } 372 373 if (ftruncate(fd, 0) < 0) {} 374 375 ctxt.fp = fdopen(fd, "w"); 376 if (!ctxt.fp) { 377 close(fd); 378 return; 379 } 380 381 avl_for_each_element(&interfaces, ctxt.iface, avl) { 382 if (ctxt.iface->dhcpv6 != MODE_SERVER && 383 ctxt.iface->dhcpv4 != MODE_SERVER) 384 continue; 385 386 if (ctxt.iface->dhcpv6 == MODE_SERVER) { 387 list_for_each_entry(ctxt.c, &ctxt.iface->ia_assignments, head) { 388 if (!(ctxt.c->flags & OAF_BOUND) || ctxt.c->managed_size < 0) 389 continue; 390 391 if (INFINITE_VALID(ctxt.c->valid_until) || ctxt.c->valid_until > now) 392 dhcpv6_ia_enum_addrs(ctxt.iface, ctxt.c, now, 393 dhcpv6_write_ia_addrhosts, &ctxt); 394 } 395 } 396 397 if (ctxt.iface->dhcpv4 == MODE_SERVER) { 398 struct dhcp_assignment *c; 399 400 list_for_each_entry(c, &ctxt.iface->dhcpv4_assignments, head) { 401 if (!(c->flags & OAF_BOUND)) 402 continue; 403 404 char ipbuf[INET6_ADDRSTRLEN]; 405 struct in_addr addr = {.s_addr = c->addr}; 406 inet_ntop(AF_INET, &addr, ipbuf, sizeof(ipbuf) - 1); 407 408 if (c->hostname && !(c->flags & OAF_BROKEN_HOSTNAME)) { 409 fputs(ipbuf, ctxt.fp); 410 411 char b[256]; 412 413 if (dn_expand(ctxt.iface->search, 414 ctxt.iface->search + ctxt.iface->search_len, 415 ctxt.iface->search, b, sizeof(b)) > 0) 416 fprintf(ctxt.fp, "\t%s.%s", c->hostname, b); 417 418 fprintf(ctxt.fp, "\t%s\n", c->hostname); 419 } 420 } 421 } 422 } 423 424 fclose(ctxt.fp); 425 426 rename(tmp_hostsfile, config.dhcp_hostsfile); 427 } 428 429 void dhcpv6_ia_write_statefile(void) 430 { 431 struct write_ctxt ctxt; 432 433 md5_begin(&ctxt.md5); 434 435 if (config.dhcp_statefile) { 436 unsigned statefile_strlen = strlen(config.dhcp_statefile) + 1; 437 unsigned tmp_statefile_strlen = statefile_strlen + 1; /* space for . */ 438 char *tmp_statefile = alloca(tmp_statefile_strlen); 439 440 char *dir_statefile; 441 char *base_statefile; 442 char *pdir_statefile; 443 char *pbase_statefile; 444 445 time_t now = odhcpd_time(), wall_time = time(NULL); 446 int fd, ret; 447 char leasebuf[512]; 448 449 dir_statefile = strndup(config.dhcp_statefile, statefile_strlen); 450 base_statefile = strndup(config.dhcp_statefile, statefile_strlen); 451 452 pdir_statefile = dirname(dir_statefile); 453 pbase_statefile = basename(base_statefile); 454 455 snprintf(tmp_statefile, tmp_statefile_strlen, "%s/.%s", pdir_statefile, pbase_statefile); 456 457 free(dir_statefile); 458 free(base_statefile); 459 460 fd = open(tmp_statefile, O_CREAT | O_WRONLY | O_CLOEXEC, 0644); 461 if (fd < 0) 462 return; 463 464 ret = lockf(fd, F_LOCK, 0); 465 if (ret < 0) { 466 close(fd); 467 return; 468 } 469 470 if (ftruncate(fd, 0) < 0) {} 471 472 ctxt.fp = fdopen(fd, "w"); 473 if (!ctxt.fp) { 474 close(fd); 475 return; 476 } 477 478 ctxt.buf = leasebuf; 479 ctxt.buf_len = sizeof(leasebuf); 480 481 avl_for_each_element(&interfaces, ctxt.iface, avl) { 482 if (ctxt.iface->dhcpv6 != MODE_SERVER && 483 ctxt.iface->dhcpv4 != MODE_SERVER) 484 continue; 485 486 if (ctxt.iface->dhcpv6 == MODE_SERVER) { 487 list_for_each_entry(ctxt.c, &ctxt.iface->ia_assignments, head) { 488 if (!(ctxt.c->flags & OAF_BOUND) || ctxt.c->managed_size < 0) 489 continue; 490 491 char duidbuf[264]; 492 493 odhcpd_hexlify(duidbuf, ctxt.c->clid_data, ctxt.c->clid_len); 494 495 /* iface DUID iaid hostname lifetime assigned_host_id length [addrs...] */ 496 ctxt.buf_idx = snprintf(ctxt.buf, ctxt.buf_len, "# %s %s %x %s%s %"PRId64" ", 497 ctxt.iface->ifname, duidbuf, ntohl(ctxt.c->iaid), 498 (ctxt.c->flags & OAF_BROKEN_HOSTNAME) ? "broken\\x20" : "", 499 (ctxt.c->hostname ? ctxt.c->hostname : "-"), 500 (ctxt.c->valid_until > now ? 501 (int64_t)(ctxt.c->valid_until - now + wall_time) : 502 (INFINITE_VALID(ctxt.c->valid_until) ? -1 : 0))); 503 504 if (ctxt.c->flags & OAF_DHCPV6_NA) 505 ctxt.buf_idx += snprintf(ctxt.buf + ctxt.buf_idx, ctxt.buf_len - ctxt.buf_idx, 506 "%" PRIx64" %u ", ctxt.c->assigned_host_id, (unsigned)ctxt.c->length); 507 else 508 ctxt.buf_idx += snprintf(ctxt.buf + ctxt.buf_idx, ctxt.buf_len - ctxt.buf_idx, 509 "%" PRIx32" %u ", ctxt.c->assigned_subnet_id, (unsigned)ctxt.c->length); 510 511 if (INFINITE_VALID(ctxt.c->valid_until) || ctxt.c->valid_until > now) 512 dhcpv6_ia_enum_addrs(ctxt.iface, ctxt.c, now, 513 dhcpv6_write_ia_addr, &ctxt); 514 515 ctxt.buf[ctxt.buf_idx - 1] = '\n'; 516 fwrite(ctxt.buf, 1, ctxt.buf_idx, ctxt.fp); 517 } 518 } 519 520 if (ctxt.iface->dhcpv4 == MODE_SERVER) { 521 struct dhcp_assignment *c; 522 523 list_for_each_entry(c, &ctxt.iface->dhcpv4_assignments, head) { 524 if (!(c->flags & OAF_BOUND)) 525 continue; 526 527 char ipbuf[INET6_ADDRSTRLEN]; 528 char duidbuf[16]; 529 odhcpd_hexlify(duidbuf, c->hwaddr, sizeof(c->hwaddr)); 530 531 /* iface DUID iaid hostname lifetime assigned length [addrs...] */ 532 ctxt.buf_idx = snprintf(ctxt.buf, ctxt.buf_len, "# %s %s ipv4 %s%s %"PRId64" %x 32 ", 533 ctxt.iface->ifname, duidbuf, 534 (c->flags & OAF_BROKEN_HOSTNAME) ? "broken\\x20" : "", 535 (c->hostname ? c->hostname : "-"), 536 (c->valid_until > now ? 537 (int64_t)(c->valid_until - now + wall_time) : 538 (INFINITE_VALID(c->valid_until) ? -1 : 0)), 539 ntohl(c->addr)); 540 541 struct in_addr addr = {.s_addr = c->addr}; 542 inet_ntop(AF_INET, &addr, ipbuf, sizeof(ipbuf) - 1); 543 544 if (c->hostname && !(c->flags & OAF_BROKEN_HOSTNAME)) { 545 fputs(ipbuf, ctxt.fp); 546 547 char b[256]; 548 if (dn_expand(ctxt.iface->search, 549 ctxt.iface->search + ctxt.iface->search_len, 550 ctxt.iface->search, b, sizeof(b)) > 0) 551 fprintf(ctxt.fp, "\t%s.%s", c->hostname, b); 552 553 fprintf(ctxt.fp, "\t%s\n", c->hostname); 554 md5_hash(ipbuf, strlen(ipbuf), &ctxt.md5); 555 md5_hash(c->hostname, strlen(c->hostname), &ctxt.md5); 556 } 557 558 ctxt.buf_idx += snprintf(ctxt.buf + ctxt.buf_idx, 559 ctxt.buf_len - ctxt.buf_idx, 560 "%s/32 ", ipbuf); 561 ctxt.buf[ctxt.buf_idx - 1] = '\n'; 562 fwrite(ctxt.buf, 1, ctxt.buf_idx, ctxt.fp); 563 } 564 } 565 } 566 567 fclose(ctxt.fp); 568 569 uint8_t newmd5[16]; 570 md5_end(newmd5, &ctxt.md5); 571 572 rename(tmp_statefile, config.dhcp_statefile); 573 574 if (memcmp(newmd5, statemd5, sizeof(newmd5))) { 575 memcpy(statemd5, newmd5, sizeof(statemd5)); 576 577 if (config.dhcp_hostsfile) 578 dhcpv6_ia_write_hostsfile(now); 579 580 if (config.dhcp_cb) { 581 char *argv[2] = {config.dhcp_cb, NULL}; 582 if (!vfork()) { 583 execv(argv[0], argv); 584 _exit(128); 585 } 586 } 587 } 588 } 589 } 590 591 static void __apply_lease(struct dhcp_assignment *a, 592 struct odhcpd_ipaddr *addrs, ssize_t addr_len, bool add) 593 { 594 if (a->flags & OAF_DHCPV6_NA) 595 return; 596 597 for (ssize_t i = 0; i < addr_len; ++i) { 598 struct in6_addr prefix; 599 600 if (ADDR_MATCH_PIO_FILTER(&addrs[i], a->iface)) 601 continue; 602 603 prefix = addrs[i].addr.in6; 604 prefix.s6_addr32[1] |= htonl(a->assigned_subnet_id); 605 prefix.s6_addr32[2] = prefix.s6_addr32[3] = 0; 606 netlink_setup_route(&prefix, (a->managed_size) ? addrs[i].prefix : a->length, 607 a->iface->ifindex, &a->peer.sin6_addr, 1024, add); 608 } 609 } 610 611 static void apply_lease(struct dhcp_assignment *a, bool add) 612 { 613 struct interface *iface = a->iface; 614 struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->addr6; 615 ssize_t addrlen = (a->managed) ? a->managed_size : (ssize_t)iface->addr6_len; 616 617 __apply_lease(a, addrs, addrlen, add); 618 } 619 620 /* Set border assignment size based on the IPv6 address prefixes */ 621 static void set_border_assignment_size(struct interface *iface, struct dhcp_assignment *b) 622 { 623 time_t now = odhcpd_time(); 624 int minprefix = -1; 625 626 for (size_t i = 0; i < iface->addr6_len; ++i) { 627 struct odhcpd_ipaddr *addr = &iface->addr6[i]; 628 629 if (ADDR_MATCH_PIO_FILTER(addr, iface)) 630 continue; 631 632 if (addr->preferred > (uint32_t)now && 633 addr->prefix < 64 && 634 addr->prefix > minprefix) 635 minprefix = addr->prefix; 636 } 637 638 if (minprefix > 32 && minprefix <= 64) 639 b->assigned_subnet_id = 1U << (64 - minprefix); 640 else 641 b->assigned_subnet_id = 0; 642 } 643 644 /* More data was received from TCP connection */ 645 static void managed_handle_pd_data(struct ustream *s, _unused int bytes_new) 646 { 647 struct ustream_fd *fd = container_of(s, struct ustream_fd, stream); 648 struct dhcp_assignment *c = container_of(fd, struct dhcp_assignment, managed_sock); 649 time_t now = odhcpd_time(); 650 bool first = c->managed_size < 0; 651 652 for (;;) { 653 int pending; 654 char *data = ustream_get_read_buf(s, &pending); 655 char *end = memmem(data, pending, "\n\n", 2); 656 657 if (!end) 658 break; 659 660 end += 2; 661 end[-1] = 0; 662 663 c->managed_size = 0; 664 if (c->accept_reconf) 665 c->reconf_cnt = 1; 666 667 char *saveptr; 668 for (char *line = strtok_r(data, "\n", &saveptr); line; line = strtok_r(NULL, "\n", &saveptr)) { 669 c->managed = realloc(c->managed, (c->managed_size + 1) * sizeof(*c->managed)); 670 struct odhcpd_ipaddr *n = &c->managed[c->managed_size]; 671 672 char *saveptr2, *x = strtok_r(line, "/", &saveptr2); 673 if (!x || inet_pton(AF_INET6, x, &n->addr) < 1) 674 continue; 675 676 x = strtok_r(NULL, ",", &saveptr2); 677 if (sscanf(x, "%hhu", &n->prefix) < 1) 678 continue; 679 680 x = strtok_r(NULL, ",", &saveptr2); 681 if (sscanf(x, "%u", &n->preferred) < 1) 682 continue; 683 684 x = strtok_r(NULL, ",", &saveptr2); 685 if (sscanf(x, "%u", &n->valid) < 1) 686 continue; 687 688 if (n->preferred > n->valid) 689 continue; 690 691 if (UINT32_MAX - now < n->preferred) 692 n->preferred = UINT32_MAX; 693 else 694 n->preferred += now; 695 696 if (UINT32_MAX - now < n->valid) 697 n->valid = UINT32_MAX; 698 else 699 n->valid += now; 700 701 n->dprefix = 0; 702 703 ++c->managed_size; 704 } 705 706 ustream_consume(s, end - data); 707 } 708 709 if (first && c->managed_size == 0) 710 free_assignment(c); 711 else if (first) 712 c->valid_until = now + 150; 713 } 714 715 716 /* TCP transmission has ended, either because of success or timeout or other error */ 717 static void managed_handle_pd_done(struct ustream *s) 718 { 719 struct ustream_fd *fd = container_of(s, struct ustream_fd, stream); 720 struct dhcp_assignment *c = container_of(fd, struct dhcp_assignment, managed_sock); 721 722 c->valid_until = odhcpd_time() + 15; 723 724 c->managed_size = 0; 725 726 if (c->accept_reconf) 727 c->reconf_cnt = 1; 728 } 729 730 static bool assign_pd(struct interface *iface, struct dhcp_assignment *assign) 731 { 732 struct dhcp_assignment *c; 733 734 if (iface->dhcpv6_pd_manager[0]) { 735 int fd = usock(USOCK_UNIX | USOCK_TCP, iface->dhcpv6_pd_manager, NULL); 736 if (fd >= 0) { 737 struct pollfd pfd = { .fd = fd, .events = POLLIN }; 738 char iaidbuf[298]; 739 740 odhcpd_hexlify(iaidbuf, assign->clid_data, assign->clid_len); 741 742 assign->managed_sock.stream.notify_read = managed_handle_pd_data; 743 assign->managed_sock.stream.notify_state = managed_handle_pd_done; 744 ustream_fd_init(&assign->managed_sock, fd); 745 ustream_printf(&assign->managed_sock.stream, "%s,%x\n::/%d,0,0\n\n", 746 iaidbuf, assign->iaid, assign->length); 747 ustream_write_pending(&assign->managed_sock.stream); 748 assign->managed_size = -1; 749 750 assign->valid_until = odhcpd_time() + 15; 751 752 list_add(&assign->head, &iface->ia_assignments); 753 754 /* Wait initial period of up to 250ms for immediate assignment */ 755 if (poll(&pfd, 1, 250) < 0) { 756 syslog(LOG_ERR, "poll(): %m"); 757 return false; 758 } 759 760 managed_handle_pd_data(&assign->managed_sock.stream, 0); 761 762 if (fcntl(fd, F_GETFL) >= 0 && assign->managed_size > 0) 763 return true; 764 } 765 766 return false; 767 } else if (iface->addr6_len < 1) 768 return false; 769 770 /* Try honoring the hint first */ 771 uint32_t current = 1, asize = (1 << (64 - assign->length)) - 1; 772 if (assign->assigned_subnet_id) { 773 list_for_each_entry(c, &iface->ia_assignments, head) { 774 if (c->flags & OAF_DHCPV6_NA) 775 continue; 776 777 if (assign->assigned_subnet_id >= current && assign->assigned_subnet_id + asize < c->assigned_subnet_id) { 778 list_add_tail(&assign->head, &c->head); 779 780 if (assign->flags & OAF_BOUND) 781 apply_lease(assign, true); 782 783 return true; 784 } 785 786 current = (c->assigned_subnet_id + (1 << (64 - c->length))); 787 } 788 } 789 790 /* Fallback to a variable assignment */ 791 current = 1; 792 list_for_each_entry(c, &iface->ia_assignments, head) { 793 if (c->flags & OAF_DHCPV6_NA) 794 continue; 795 796 current = (current + asize) & (~asize); 797 798 if (current + asize < c->assigned_subnet_id) { 799 assign->assigned_subnet_id = current; 800 list_add_tail(&assign->head, &c->head); 801 802 if (assign->flags & OAF_BOUND) 803 apply_lease(assign, true); 804 805 return true; 806 } 807 808 current = (c->assigned_subnet_id + (1 << (64 - c->length))); 809 } 810 811 return false; 812 } 813 814 /* Check iid against reserved IPv6 interface identifiers. 815 Refer to: 816 http://www.iana.org/assignments/ipv6-interface-ids */ 817 static bool is_reserved_ipv6_iid(uint64_t iid) 818 { 819 if (iid == 0x0000000000000000) 820 /* Subnet-Router Anycast [RFC4291] */ 821 return true; 822 823 if ((iid & 0xFFFFFFFFFF000000) == 0x02005EFFFE000000) 824 /* Reserved IPv6 Interface Identifiers corresponding 825 to the IANA Ethernet Block [RFC4291] */ 826 return true; 827 828 if ((iid & 0xFFFFFFFFFFFFFF80) == 0xFDFFFFFFFFFFFF80) 829 /* Reserved Subnet Anycast Addresses [RFC2526] */ 830 return true; 831 832 return false; 833 } 834 835 static bool assign_na(struct interface *iface, struct dhcp_assignment *a) 836 { 837 struct dhcp_assignment *c; 838 uint32_t seed = 0; 839 840 /* Preconfigured assignment by static lease */ 841 if (a->assigned_host_id) { 842 list_for_each_entry(c, &iface->ia_assignments, head) { 843 if (!(c->flags & OAF_DHCPV6_NA) || c->assigned_host_id > a->assigned_host_id ) { 844 list_add_tail(&a->head, &c->head); 845 return true; 846 } else if (c->assigned_host_id == a->assigned_host_id) 847 return false; 848 } 849 } 850 851 /* Seed RNG with checksum of DUID */ 852 for (size_t i = 0; i < a->clid_len; ++i) 853 seed += a->clid_data[i]; 854 srandom(seed); 855 856 /* Try to assign up to 100x */ 857 for (size_t i = 0; i < 100; ++i) { 858 uint64_t try; 859 860 if (iface->dhcpv6_hostid_len > 32) { 861 uint32_t mask_high; 862 863 if (iface->dhcpv6_hostid_len >= 64) 864 mask_high = UINT32_MAX; 865 else 866 mask_high = (1 << (iface->dhcpv6_hostid_len - 32)) - 1; 867 868 do { 869 try = (uint32_t)random(); 870 try |= (uint64_t)((uint32_t)random() & mask_high) << 32; 871 } while (try < 0x100); 872 } else { 873 uint32_t mask_low; 874 875 if (iface->dhcpv6_hostid_len == 32) 876 mask_low = UINT32_MAX; 877 else 878 mask_low = (1 << iface->dhcpv6_hostid_len) - 1; 879 do try = ((uint32_t)random()) & mask_low; while (try < 0x100); 880 } 881 882 if (is_reserved_ipv6_iid(try)) 883 continue; 884 885 if (config_find_lease_by_hostid(try)) 886 continue; 887 888 list_for_each_entry(c, &iface->ia_assignments, head) { 889 if (!(c->flags & OAF_DHCPV6_NA) || c->assigned_host_id > try) { 890 a->assigned_host_id = try; 891 list_add_tail(&a->head, &c->head); 892 return true; 893 } else if (c->assigned_host_id == try) 894 break; 895 } 896 } 897 898 return false; 899 } 900 901 static void handle_addrlist_change(struct netevent_handler_info *info) 902 { 903 struct interface *iface = info->iface; 904 struct dhcp_assignment *c, *d, *border = list_last_entry( 905 &iface->ia_assignments, struct dhcp_assignment, head); 906 struct list_head reassign = LIST_HEAD_INIT(reassign); 907 time_t now = odhcpd_time(); 908 909 list_for_each_entry(c, &iface->ia_assignments, head) { 910 if ((c->flags & OAF_DHCPV6_PD) && !(iface->ra_flags & ND_RA_FLAG_MANAGED) 911 && (c->flags & OAF_BOUND)) 912 __apply_lease(c, info->addrs_old.addrs, 913 info->addrs_old.len, false); 914 } 915 916 set_border_assignment_size(iface, border); 917 918 list_for_each_entry_safe(c, d, &iface->ia_assignments, head) { 919 if (c->clid_len == 0 || 920 !(c->flags & OAF_DHCPV6_PD) || 921 (!INFINITE_VALID(c->valid_until) && c->valid_until < now) || 922 c->managed_size) 923 continue; 924 925 if (c->assigned_subnet_id >= border->assigned_subnet_id) 926 list_move(&c->head, &reassign); 927 else if (c->flags & OAF_BOUND) 928 apply_lease(c, true); 929 930 if (c->accept_reconf && c->reconf_cnt == 0) { 931 struct dhcp_assignment *a; 932 933 start_reconf(c); 934 935 /* Leave all other assignments of that client alone */ 936 list_for_each_entry(a, &iface->ia_assignments, head) 937 if (a != c && a->clid_len == c->clid_len && 938 !memcmp(a->clid_data, c->clid_data, a->clid_len)) 939 a->reconf_cnt = INT_MAX; 940 } 941 } 942 943 while (!list_empty(&reassign)) { 944 c = list_first_entry(&reassign, struct dhcp_assignment, head); 945 list_del_init(&c->head); 946 if (!assign_pd(iface, c)) 947 free_assignment(c); 948 } 949 950 dhcpv6_ia_write_statefile(); 951 } 952 953 static void reconf_timeout_cb(struct uloop_timeout *event) 954 { 955 struct dhcp_assignment *a = container_of(event, struct dhcp_assignment, reconf_timer); 956 957 if (a->reconf_cnt > 0 && a->reconf_cnt < DHCPV6_REC_MAX_RC) { 958 send_reconf(a); 959 uloop_timeout_set(&a->reconf_timer, 960 DHCPV6_REC_TIMEOUT << a->reconf_cnt); 961 a->reconf_cnt++; 962 } else 963 stop_reconf(a); 964 } 965 966 static void start_reconf(struct dhcp_assignment *a) 967 { 968 uloop_timeout_set(&a->reconf_timer, 969 DHCPV6_REC_TIMEOUT << a->reconf_cnt); 970 a->reconf_timer.cb = reconf_timeout_cb; 971 a->reconf_cnt++; 972 973 send_reconf(a); 974 } 975 976 static void stop_reconf(struct dhcp_assignment *a) 977 { 978 uloop_timeout_cancel(&a->reconf_timer); 979 a->reconf_cnt = 0; 980 a->reconf_timer.cb = NULL; 981 } 982 983 static void valid_until_cb(struct uloop_timeout *event) 984 { 985 struct interface *iface; 986 time_t now = odhcpd_time(); 987 988 avl_for_each_element(&interfaces, iface, avl) { 989 struct dhcp_assignment *a, *n; 990 991 if (iface->dhcpv6 != MODE_SERVER) 992 continue; 993 994 list_for_each_entry_safe(a, n, &iface->ia_assignments, head) { 995 if (a->clid_len > 0 && !INFINITE_VALID(a->valid_until) && a->valid_until < now) 996 free_assignment(a); 997 } 998 } 999 uloop_timeout_set(event, 1000); 1000 } 1001 1002 static size_t build_ia(uint8_t *buf, size_t buflen, uint16_t status, 1003 const struct dhcpv6_ia_hdr *ia, struct dhcp_assignment *a, 1004 struct interface *iface, bool request) 1005 { 1006 struct dhcpv6_ia_hdr o_ia = { 1007 .type = ia->type, 1008 .len = 0, 1009 .iaid = ia->iaid, 1010 .t1 = 0, 1011 .t2 = 0, 1012 }; 1013 size_t ia_len = sizeof(o_ia); 1014 time_t now = odhcpd_time(); 1015 1016 if (buflen < ia_len) 1017 return 0; 1018 1019 if (status) { 1020 struct __attribute__((packed)) { 1021 uint16_t type; 1022 uint16_t len; 1023 uint16_t val; 1024 } o_status = { 1025 .type = htons(DHCPV6_OPT_STATUS), 1026 .len = htons(sizeof(o_status) - 4), 1027 .val = htons(status), 1028 }; 1029 1030 memcpy(buf + ia_len, &o_status, sizeof(o_status)); 1031 ia_len += sizeof(o_status); 1032 1033 o_ia.len = htons(ia_len - 4); 1034 memcpy(buf, &o_ia, sizeof(o_ia)); 1035 1036 return ia_len; 1037 } 1038 1039 if (a) { 1040 uint32_t leasetime, pref; 1041 1042 if (a->leasetime) { 1043 leasetime = a->leasetime; 1044 pref = a->leasetime; 1045 } else { 1046 leasetime = iface->dhcp_leasetime; 1047 pref = iface->preferred_lifetime; 1048 } 1049 1050 uint32_t valid = leasetime; 1051 1052 struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->addr6; 1053 size_t addrlen = (a->managed) ? (size_t)a->managed_size : iface->addr6_len; 1054 size_t m = get_preferred_addr(addrs, addrlen); 1055 1056 for (size_t i = 0; i < addrlen; ++i) { 1057 uint32_t prefix_pref, prefix_valid; 1058 1059 if (!valid_addr(&addrs[i], now)) 1060 continue; 1061 1062 /* Filter Out Prefixes */ 1063 if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface)) { 1064 char addrbuf[INET6_ADDRSTRLEN]; 1065 syslog(LOG_INFO, "Address %s filtered out on %s", 1066 inet_ntop(AF_INET6, &addrs[i].addr.in6, addrbuf, sizeof(addrbuf)), 1067 iface->name); 1068 continue; 1069 } 1070 1071 prefix_pref = addrs[i].preferred; 1072 prefix_valid = addrs[i].valid; 1073 1074 if (prefix_pref != UINT32_MAX) 1075 prefix_pref -= now; 1076 1077 if (prefix_pref > pref) 1078 prefix_pref = pref; 1079 1080 if (prefix_valid != UINT32_MAX) 1081 prefix_valid -= now; 1082 1083 if (prefix_valid > leasetime) 1084 prefix_valid = leasetime; 1085 1086 if (prefix_pref > prefix_valid) 1087 prefix_pref = prefix_valid; 1088 1089 if (a->flags & OAF_DHCPV6_PD) { 1090 struct dhcpv6_ia_prefix o_ia_p = { 1091 .type = htons(DHCPV6_OPT_IA_PREFIX), 1092 .len = htons(sizeof(o_ia_p) - 4), 1093 .preferred = htonl(prefix_pref), 1094 .valid = htonl(prefix_valid), 1095 .prefix = (a->managed_size) ? addrs[i].prefix : a->length, 1096 .addr = addrs[i].addr.in6, 1097 }; 1098 1099 o_ia_p.addr.s6_addr32[1] |= htonl(a->assigned_subnet_id); 1100 o_ia_p.addr.s6_addr32[2] = o_ia_p.addr.s6_addr32[3] = 0; 1101 1102 if (!valid_prefix_length(a, addrs[i].prefix)) 1103 continue; 1104 1105 if (buflen < ia_len + sizeof(o_ia_p)) 1106 return 0; 1107 1108 memcpy(buf + ia_len, &o_ia_p, sizeof(o_ia_p)); 1109 ia_len += sizeof(o_ia_p); 1110 } 1111 1112 if (a->flags & OAF_DHCPV6_NA) { 1113 struct dhcpv6_ia_addr o_ia_a = { 1114 .type = htons(DHCPV6_OPT_IA_ADDR), 1115 .len = htons(sizeof(o_ia_a) - 4), 1116 .addr = addrs[i].addr.in6, 1117 .preferred = htonl(prefix_pref), 1118 .valid = htonl(prefix_valid) 1119 }; 1120 1121 o_ia_a.addr.s6_addr32[2] = htonl(a->assigned_host_id >> 32); 1122 o_ia_a.addr.s6_addr32[3] = htonl(a->assigned_host_id & UINT32_MAX); 1123 1124 if (!ADDR_ENTRY_VALID_IA_ADDR(iface, i, m, addrs)) 1125 continue; 1126 1127 if (buflen < ia_len + sizeof(o_ia_a)) 1128 return 0; 1129 1130 memcpy(buf + ia_len, &o_ia_a, sizeof(o_ia_a)); 1131 ia_len += sizeof(o_ia_a); 1132 } 1133 1134 /* Calculate T1 / T2 based on non-deprecated addresses */ 1135 if (prefix_pref > 0) { 1136 if (prefix_pref < pref) 1137 pref = prefix_pref; 1138 1139 if (prefix_valid < valid) 1140 valid = prefix_valid; 1141 } 1142 } 1143 1144 if (!INFINITE_VALID(a->valid_until)) 1145 /* UINT32_MAX is considered as infinite leasetime */ 1146 a->valid_until = (valid == UINT32_MAX) ? 0 : valid + now; 1147 1148 if (!INFINITE_VALID(a->preferred_until)) 1149 /* UINT32_MAX is considered as infinite leasetime */ 1150 a->preferred_until = (pref == UINT32_MAX) ? 0 : pref + now; 1151 1152 o_ia.t1 = htonl((pref == UINT32_MAX) ? pref : pref * 5 / 10); 1153 o_ia.t2 = htonl((pref == UINT32_MAX) ? pref : pref * 8 / 10); 1154 1155 if (!o_ia.t1) 1156 o_ia.t1 = htonl(1); 1157 1158 if (!o_ia.t2) 1159 o_ia.t2 = htonl(1); 1160 } 1161 1162 if (!request) { 1163 uint8_t *odata, *end = ((uint8_t*)ia) + htons(ia->len) + 4; 1164 uint16_t otype, olen; 1165 1166 dhcpv6_for_each_option((uint8_t*)&ia[1], end, otype, olen, odata) { 1167 struct dhcpv6_ia_prefix *ia_p = (struct dhcpv6_ia_prefix *)&odata[-4]; 1168 struct dhcpv6_ia_addr *ia_a = (struct dhcpv6_ia_addr *)&odata[-4]; 1169 bool found = false; 1170 1171 if ((otype != DHCPV6_OPT_IA_PREFIX || olen < sizeof(*ia_p) - 4) && 1172 (otype != DHCPV6_OPT_IA_ADDR || olen < sizeof(*ia_a) - 4)) 1173 continue; 1174 1175 if (a) { 1176 struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->addr6; 1177 size_t addrlen = (a->managed) ? (size_t)a->managed_size : iface->addr6_len; 1178 1179 for (size_t i = 0; i < addrlen; ++i) { 1180 struct in6_addr addr; 1181 1182 if (!valid_addr(&addrs[i], now)) 1183 continue; 1184 1185 if (!valid_prefix_length(a, addrs[i].prefix)) 1186 continue; 1187 1188 if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface)) 1189 continue; 1190 1191 addr = addrs[i].addr.in6; 1192 if (ia->type == htons(DHCPV6_OPT_IA_PD)) { 1193 addr.s6_addr32[1] |= htonl(a->assigned_subnet_id); 1194 addr.s6_addr32[2] = addr.s6_addr32[3] = 0; 1195 1196 if (!memcmp(&ia_p->addr, &addr, sizeof(addr)) && 1197 ia_p->prefix == ((a->managed) ? addrs[i].prefix : a->length)) 1198 found = true; 1199 } else { 1200 addr.s6_addr32[2] = htonl(a->assigned_host_id >> 32); 1201 addr.s6_addr32[3] = htonl(a->assigned_host_id & UINT32_MAX); 1202 1203 if (!memcmp(&ia_a->addr, &addr, sizeof(addr))) 1204 found = true; 1205 } 1206 } 1207 } 1208 1209 if (!found) { 1210 if (otype == DHCPV6_OPT_IA_PREFIX) { 1211 struct dhcpv6_ia_prefix o_ia_p = { 1212 .type = htons(DHCPV6_OPT_IA_PREFIX), 1213 .len = htons(sizeof(o_ia_p) - 4), 1214 .preferred = 0, 1215 .valid = 0, 1216 .prefix = ia_p->prefix, 1217 .addr = ia_p->addr, 1218 }; 1219 1220 if (buflen < ia_len + sizeof(o_ia_p)) 1221 return 0; 1222 1223 memcpy(buf + ia_len, &o_ia_p, sizeof(o_ia_p)); 1224 ia_len += sizeof(o_ia_p); 1225 } else { 1226 struct dhcpv6_ia_addr o_ia_a = { 1227 .type = htons(DHCPV6_OPT_IA_ADDR), 1228 .len = htons(sizeof(o_ia_a) - 4), 1229 .addr = ia_a->addr, 1230 .preferred = 0, 1231 .valid = 0, 1232 }; 1233 1234 if (buflen < ia_len + sizeof(o_ia_a)) 1235 continue; 1236 1237 memcpy(buf + ia_len, &o_ia_a, sizeof(o_ia_a)); 1238 ia_len += sizeof(o_ia_a); 1239 } 1240 } 1241 } 1242 } 1243 1244 o_ia.len = htons(ia_len - 4); 1245 memcpy(buf, &o_ia, sizeof(o_ia)); 1246 return ia_len; 1247 } 1248 1249 struct log_ctxt { 1250 char *buf; 1251 int buf_len; 1252 int buf_idx; 1253 }; 1254 1255 static void dhcpv6_log_ia_addr(struct in6_addr *addr, int prefix, _unused uint32_t pref, 1256 _unused uint32_t valid, void *arg) 1257 { 1258 struct log_ctxt *ctxt = (struct log_ctxt *)arg; 1259 char addrbuf[INET6_ADDRSTRLEN]; 1260 1261 inet_ntop(AF_INET6, addr, addrbuf, sizeof(addrbuf)); 1262 ctxt->buf_idx += snprintf(ctxt->buf + ctxt->buf_idx, ctxt->buf_len - ctxt->buf_idx, 1263 "%s/%d ", addrbuf, prefix); 1264 } 1265 1266 static void dhcpv6_log(uint8_t msgtype, struct interface *iface, time_t now, 1267 const char *duidbuf, bool is_pd, struct dhcp_assignment *a, int code) 1268 { 1269 const char *type = "UNKNOWN"; 1270 const char *status = "UNKNOWN"; 1271 1272 switch (msgtype) { 1273 case DHCPV6_MSG_SOLICIT: 1274 type = "SOLICIT"; 1275 break; 1276 case DHCPV6_MSG_REQUEST: 1277 type = "REQUEST"; 1278 break; 1279 case DHCPV6_MSG_CONFIRM: 1280 type = "CONFIRM"; 1281 break; 1282 case DHCPV6_MSG_RENEW: 1283 type = "RENEW"; 1284 break; 1285 case DHCPV6_MSG_REBIND: 1286 type = "REBIND"; 1287 break; 1288 case DHCPV6_MSG_RELEASE: 1289 type = "RELEASE"; 1290 break; 1291 case DHCPV6_MSG_DECLINE: 1292 type = "DECLINE"; 1293 break; 1294 } 1295 1296 switch (code) { 1297 case DHCPV6_STATUS_OK: 1298 status = "ok"; 1299 break; 1300 case DHCPV6_STATUS_NOADDRSAVAIL: 1301 status = "no addresses available"; 1302 break; 1303 case DHCPV6_STATUS_NOBINDING: 1304 status = "no binding"; 1305 break; 1306 case DHCPV6_STATUS_NOTONLINK: 1307 status = "not on-link"; 1308 break; 1309 case DHCPV6_STATUS_NOPREFIXAVAIL: 1310 status = "no prefix available"; 1311 break; 1312 } 1313 1314 char leasebuf[256] = ""; 1315 1316 if (a) { 1317 struct log_ctxt ctxt = {.buf = leasebuf, 1318 .buf_len = sizeof(leasebuf), 1319 .buf_idx = 0 }; 1320 1321 dhcpv6_ia_enum_addrs(iface, a, now, dhcpv6_log_ia_addr, &ctxt); 1322 } 1323 1324 syslog(LOG_INFO, "DHCPV6 %s %s from %s on %s: %s %s", type, (is_pd) ? "IA_PD" : "IA_NA", 1325 duidbuf, iface->name, status, leasebuf); 1326 } 1327 1328 static bool dhcpv6_ia_on_link(const struct dhcpv6_ia_hdr *ia, struct dhcp_assignment *a, 1329 struct interface *iface) 1330 { 1331 struct odhcpd_ipaddr *addrs = (a && a->managed) ? a->managed : iface->addr6; 1332 size_t addrlen = (a && a->managed) ? (size_t)a->managed_size : iface->addr6_len; 1333 time_t now = odhcpd_time(); 1334 uint8_t *odata, *end = ((uint8_t*)ia) + htons(ia->len) + 4; 1335 uint16_t otype, olen; 1336 bool onlink = true; 1337 1338 dhcpv6_for_each_option((uint8_t*)&ia[1], end, otype, olen, odata) { 1339 struct dhcpv6_ia_prefix *p = (struct dhcpv6_ia_prefix *)&odata[-4]; 1340 struct dhcpv6_ia_addr *n = (struct dhcpv6_ia_addr *)&odata[-4]; 1341 1342 if ((otype != DHCPV6_OPT_IA_PREFIX || olen < sizeof(*p) - 4) && 1343 (otype != DHCPV6_OPT_IA_ADDR || olen < sizeof(*n) - 4)) 1344 continue; 1345 1346 onlink = false; 1347 for (size_t i = 0; i < addrlen; ++i) { 1348 if (!valid_addr(&addrs[i], now)) 1349 continue; 1350 1351 if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface)) 1352 continue; 1353 1354 if (ia->type == htons(DHCPV6_OPT_IA_PD)) { 1355 if (p->prefix < addrs[i].prefix || 1356 odhcpd_bmemcmp(&p->addr, &addrs[i].addr.in6, addrs[i].prefix)) 1357 continue; 1358 1359 } else if (odhcpd_bmemcmp(&n->addr, &addrs[i].addr.in6, addrs[i].prefix)) 1360 continue; 1361 1362 onlink = true; 1363 } 1364 1365 if (!onlink) 1366 break; 1367 } 1368 1369 return onlink; 1370 } 1371 1372 ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *iface, 1373 const struct sockaddr_in6 *addr, const void *data, const uint8_t *end) 1374 { 1375 struct lease *l; 1376 struct dhcp_assignment *first = NULL; 1377 const struct dhcpv6_client_header *hdr = data; 1378 time_t now = odhcpd_time(); 1379 uint16_t otype, olen, clid_len = 0; 1380 uint8_t *start = (uint8_t *)&hdr[1], *odata; 1381 uint8_t *clid_data = NULL, mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 1382 size_t hostname_len = 0, response_len = 0; 1383 bool notonlink = false, rapid_commit = false, accept_reconf = false; 1384 char duidbuf[261], hostname[256]; 1385 1386 dhcpv6_for_each_option(start, end, otype, olen, odata) { 1387 if (otype == DHCPV6_OPT_CLIENTID) { 1388 clid_data = odata; 1389 clid_len = olen; 1390 1391 if (olen == 14 && odata[0] == 0 && odata[1] == 1) 1392 memcpy(mac, &odata[8], sizeof(mac)); 1393 else if (olen == 10 && odata[0] == 0 && odata[1] == 3) 1394 memcpy(mac, &odata[4], sizeof(mac)); 1395 1396 if (olen <= 130) 1397 odhcpd_hexlify(duidbuf, odata, olen); 1398 } else if (otype == DHCPV6_OPT_FQDN && olen >= 2 && olen <= 255) { 1399 uint8_t fqdn_buf[256]; 1400 memcpy(fqdn_buf, odata, olen); 1401 fqdn_buf[olen++] = 0; 1402 1403 if (dn_expand(&fqdn_buf[1], &fqdn_buf[olen], &fqdn_buf[1], hostname, sizeof(hostname)) > 0) 1404 hostname_len = strcspn(hostname, "."); 1405 } else if (otype == DHCPV6_OPT_RECONF_ACCEPT) 1406 accept_reconf = true; 1407 else if (otype == DHCPV6_OPT_RAPID_COMMIT && hdr->msg_type == DHCPV6_MSG_SOLICIT) 1408 rapid_commit = true; 1409 } 1410 1411 if (!clid_data || !clid_len || clid_len > 130) 1412 goto out; 1413 1414 l = config_find_lease_by_duid(clid_data, clid_len); 1415 if (!l) 1416 l = config_find_lease_by_mac(mac); 1417 1418 dhcpv6_for_each_option(start, end, otype, olen, odata) { 1419 bool is_pd = (otype == DHCPV6_OPT_IA_PD); 1420 bool is_na = (otype == DHCPV6_OPT_IA_NA); 1421 bool ia_addr_present = false; 1422 if (!is_pd && !is_na) 1423 continue; 1424 1425 struct dhcpv6_ia_hdr *ia = (struct dhcpv6_ia_hdr*)&odata[-4]; 1426 size_t ia_response_len = 0; 1427 uint8_t reqlen = (is_pd) ? 62 : 128; 1428 uint32_t reqhint = 0; 1429 1430 /* Parse request hint for IA-PD */ 1431 if (is_pd) { 1432 uint8_t *sdata; 1433 uint16_t stype, slen; 1434 dhcpv6_for_each_option(&ia[1], odata + olen, stype, slen, sdata) { 1435 if (stype != DHCPV6_OPT_IA_PREFIX || slen < sizeof(struct dhcpv6_ia_prefix) - 4) 1436 continue; 1437 1438 struct dhcpv6_ia_prefix *p = (struct dhcpv6_ia_prefix*)&sdata[-4]; 1439 if (p->prefix) { 1440 reqlen = p->prefix; 1441 reqhint = ntohl(p->addr.s6_addr32[1]); 1442 if (reqlen > 32 && reqlen <= 64) 1443 reqhint &= (1U << (64 - reqlen)) - 1; 1444 } 1445 } 1446 1447 if (reqlen > 64) 1448 reqlen = 64; 1449 1450 /* 1451 * A requesting router can include a desired prefix length for its 1452 * delegation. The delegating router (us) is not required to honor 1453 * the hint (RFC3633, section 11.2, we MAY choose to use the 1454 * information in the option; RFC8168, section 3.2 has several SHOULDs 1455 * about desired choices for selecting a prefix to delegate). 1456 * 1457 * We support a policy setting to conserve prefix space, which purposely 1458 * assigns prefixes that might not match the requesting router's hint. 1459 * 1460 * If the minimum prefix length is set in this interface's 1461 * configuration, we use it as a floor for the requested (hinted) 1462 * prefix length. This allows us to conserve prefix space so that 1463 * any single router can't grab too much of it. Consider if we have 1464 * an interface with a /56 prefix. A requesting router could ask for 1465 * a /58 and take 1/4 of our total address space. But if we set a 1466 * minimum of /60, we can limit each requesting router to get only 1467 * 1/16 of our total address space. 1468 */ 1469 if (iface->dhcpv6_pd_min_len && reqlen < iface->dhcpv6_pd_min_len) { 1470 syslog(LOG_INFO, "clamping requested PD from %d to %d", 1471 reqlen, iface->dhcpv6_pd_min_len); 1472 reqlen = iface->dhcpv6_pd_min_len; 1473 } 1474 } else if (is_na) { 1475 uint8_t *sdata; 1476 uint16_t stype, slen; 1477 dhcpv6_for_each_option(&ia[1], odata + olen, stype, slen, sdata) { 1478 if (stype != DHCPV6_OPT_IA_ADDR || slen < sizeof(struct dhcpv6_ia_addr) - 4) 1479 continue; 1480 1481 ia_addr_present = true; 1482 } 1483 } 1484 1485 /* Find assignment */ 1486 struct dhcp_assignment *c, *a = NULL; 1487 list_for_each_entry(c, &iface->ia_assignments, head) { 1488 if ((c->clid_len == clid_len && !memcmp(c->clid_data, clid_data, clid_len)) && 1489 c->iaid == ia->iaid && (INFINITE_VALID(c->valid_until) || now < c->valid_until) && 1490 ((is_pd && (c->flags & OAF_DHCPV6_PD)) || (is_na && (c->flags & OAF_DHCPV6_NA)))) { 1491 a = c; 1492 1493 /* Reset state */ 1494 if (a->flags & OAF_BOUND) 1495 apply_lease(a, false); 1496 1497 stop_reconf(a); 1498 break; 1499 } 1500 } 1501 1502 if (l && a && a->lease != l) { 1503 free_assignment(a); 1504 a = NULL; 1505 } 1506 1507 /* Generic message handling */ 1508 uint16_t status = DHCPV6_STATUS_OK; 1509 if (a && a->managed_size < 0) 1510 return -1; 1511 1512 if (hdr->msg_type == DHCPV6_MSG_SOLICIT || 1513 hdr->msg_type == DHCPV6_MSG_REQUEST || 1514 (hdr->msg_type == DHCPV6_MSG_REBIND && !a)) { 1515 bool assigned = !!a; 1516 1517 if (!a) { 1518 if ((!iface->no_dynamic_dhcp || (l && is_na)) && 1519 (iface->dhcpv6_pd || iface->dhcpv6_na)) { 1520 /* Create new binding */ 1521 a = alloc_assignment(clid_len); 1522 1523 if (a) { 1524 a->clid_len = clid_len; 1525 memcpy(a->clid_data, clid_data, clid_len); 1526 a->iaid = ia->iaid; 1527 a->length = reqlen; 1528 a->peer = *addr; 1529 if (is_na) 1530 a->assigned_host_id = l ? l->hostid : 0; 1531 else 1532 a->assigned_subnet_id = reqhint; 1533 a->valid_until = now; 1534 a->preferred_until = now; 1535 a->dhcp_free_cb = dhcpv6_ia_free_assignment; 1536 a->iface = iface; 1537 a->flags = (is_pd ? OAF_DHCPV6_PD : OAF_DHCPV6_NA); 1538 1539 if (first) 1540 memcpy(a->key, first->key, sizeof(a->key)); 1541 else 1542 odhcpd_urandom(a->key, sizeof(a->key)); 1543 1544 if (is_pd && iface->dhcpv6_pd) 1545 while (!(assigned = assign_pd(iface, a)) && 1546 !a->managed_size && ++a->length <= 64); 1547 else if (is_na && iface->dhcpv6_na) 1548 assigned = assign_na(iface, a); 1549 1550 if (l && assigned) { 1551 a->flags |= OAF_STATIC; 1552 1553 if (l->hostname) 1554 a->hostname = strdup(l->hostname); 1555 1556 if (l->leasetime) 1557 a->leasetime = l->leasetime; 1558 1559 list_add(&a->lease_list, &l->assignments); 1560 a->lease = l; 1561 } 1562 1563 if (a->managed_size && !assigned) 1564 return -1; 1565 } 1566 } 1567 } 1568 1569 if (!assigned || iface->addr6_len == 0) 1570 /* Set error status */ 1571 status = (is_pd) ? DHCPV6_STATUS_NOPREFIXAVAIL : DHCPV6_STATUS_NOADDRSAVAIL; 1572 else if (hdr->msg_type == DHCPV6_MSG_REQUEST && !dhcpv6_ia_on_link(ia, a, iface)) { 1573 /* Send NOTONLINK staus for the IA */ 1574 status = DHCPV6_STATUS_NOTONLINK; 1575 assigned = false; 1576 } else if (accept_reconf && assigned && !first && 1577 hdr->msg_type != DHCPV6_MSG_REBIND) { 1578 size_t handshake_len = 4; 1579 buf[0] = 0; 1580 buf[1] = DHCPV6_OPT_RECONF_ACCEPT; 1581 buf[2] = 0; 1582 buf[3] = 0; 1583 1584 if (hdr->msg_type == DHCPV6_MSG_REQUEST) { 1585 struct dhcpv6_auth_reconfigure auth = { 1586 htons(DHCPV6_OPT_AUTH), 1587 htons(sizeof(auth) - 4), 1588 3, 1, 0, 1589 {htonl(time(NULL)), htonl(++serial)}, 1590 1, 1591 {0} 1592 }; 1593 memcpy(auth.key, a->key, sizeof(a->key)); 1594 memcpy(buf + handshake_len, &auth, sizeof(auth)); 1595 handshake_len += sizeof(auth); 1596 } 1597 1598 1599 buf += handshake_len; 1600 buflen -= handshake_len; 1601 response_len += handshake_len; 1602 1603 first = a; 1604 } 1605 1606 ia_response_len = build_ia(buf, buflen, status, ia, a, iface, 1607 hdr->msg_type == DHCPV6_MSG_REBIND ? false : true); 1608 1609 /* Was only a solicitation: mark binding for removal */ 1610 if (assigned && hdr->msg_type == DHCPV6_MSG_SOLICIT && !rapid_commit) { 1611 a->flags &= ~OAF_BOUND; 1612 a->flags |= OAF_TENTATIVE; 1613 1614 /* Keep tentative assignment around for 60 seconds */ 1615 a->valid_until = now + 60; 1616 1617 } else if (assigned && 1618 ((hdr->msg_type == DHCPV6_MSG_SOLICIT && rapid_commit) || 1619 hdr->msg_type == DHCPV6_MSG_REQUEST || 1620 hdr->msg_type == DHCPV6_MSG_REBIND)) { 1621 if ((!(a->flags & OAF_STATIC) || !a->hostname) && hostname_len > 0) { 1622 a->hostname = realloc(a->hostname, hostname_len + 1); 1623 if (a->hostname) { 1624 memcpy(a->hostname, hostname, hostname_len); 1625 a->hostname[hostname_len] = 0; 1626 1627 if (odhcpd_valid_hostname(a->hostname)) 1628 a->flags &= ~OAF_BROKEN_HOSTNAME; 1629 else 1630 a->flags |= OAF_BROKEN_HOSTNAME; 1631 } 1632 } 1633 a->accept_reconf = accept_reconf; 1634 a->flags &= ~OAF_TENTATIVE; 1635 a->flags |= OAF_BOUND; 1636 apply_lease(a, true); 1637 } else if (!assigned && a && a->managed_size == 0) { 1638 /* Cleanup failed assignment */ 1639 free_assignment(a); 1640 a = NULL; 1641 } 1642 } else if (hdr->msg_type == DHCPV6_MSG_RENEW || 1643 hdr->msg_type == DHCPV6_MSG_RELEASE || 1644 hdr->msg_type == DHCPV6_MSG_REBIND || 1645 hdr->msg_type == DHCPV6_MSG_DECLINE) { 1646 if (!a && hdr->msg_type != DHCPV6_MSG_REBIND) { 1647 status = DHCPV6_STATUS_NOBINDING; 1648 ia_response_len = build_ia(buf, buflen, status, ia, a, iface, false); 1649 } else if (hdr->msg_type == DHCPV6_MSG_RENEW || 1650 hdr->msg_type == DHCPV6_MSG_REBIND) { 1651 ia_response_len = build_ia(buf, buflen, status, ia, a, iface, false); 1652 if (a) { 1653 a->flags |= OAF_BOUND; 1654 apply_lease(a, true); 1655 } 1656 } else if (hdr->msg_type == DHCPV6_MSG_RELEASE) { 1657 a->valid_until = now - 1; 1658 } else if ((a->flags & OAF_DHCPV6_NA) && hdr->msg_type == DHCPV6_MSG_DECLINE) { 1659 a->flags &= ~OAF_BOUND; 1660 1661 if (!(a->flags & OAF_STATIC) || a->lease->hostid != a->assigned_host_id) { 1662 memset(a->clid_data, 0, a->clid_len); 1663 a->valid_until = now + 3600; /* Block address for 1h */ 1664 } else 1665 a->valid_until = now - 1; 1666 } 1667 } else if (hdr->msg_type == DHCPV6_MSG_CONFIRM) { 1668 if (ia_addr_present && !dhcpv6_ia_on_link(ia, a, iface)) { 1669 notonlink = true; 1670 break; 1671 } 1672 1673 if (!ia_addr_present || !a || !(a->flags & OAF_BOUND)) { 1674 response_len = 0; 1675 goto out; 1676 } 1677 } 1678 1679 buf += ia_response_len; 1680 buflen -= ia_response_len; 1681 response_len += ia_response_len; 1682 dhcpv6_log(hdr->msg_type, iface, now, duidbuf, is_pd, a, status); 1683 } 1684 1685 switch (hdr->msg_type) { 1686 case DHCPV6_MSG_RELEASE: 1687 case DHCPV6_MSG_DECLINE: 1688 case DHCPV6_MSG_CONFIRM: 1689 if (response_len + 6 < buflen) { 1690 buf[0] = 0; 1691 buf[1] = DHCPV6_OPT_STATUS; 1692 buf[2] = 0; 1693 buf[3] = 2; 1694 buf[4] = 0; 1695 buf[5] = (notonlink) ? DHCPV6_STATUS_NOTONLINK : DHCPV6_STATUS_OK; 1696 response_len += 6; 1697 } 1698 break; 1699 1700 default: 1701 break; 1702 } 1703 1704 dhcpv6_ia_write_statefile(); 1705 1706 out: 1707 return response_len; 1708 } 1709
This page was automatically generated by LXR 0.3.1. • OpenWrt