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