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_lt > (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_lt > addrs[m].preferred_lt || 132 (addrs[i].preferred_lt == addrs[m].preferred_lt && 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 preferred_lt, valid_lt; 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 preferred_lt = addrs[i].preferred_lt; 246 valid_lt = addrs[i].valid_lt; 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 (preferred_lt > (uint32_t)c->preferred_until) 263 preferred_lt = c->preferred_until; 264 265 if (preferred_lt > (uint32_t)c->valid_until) 266 preferred_lt = c->valid_until; 267 268 if (preferred_lt != UINT32_MAX) 269 preferred_lt -= now; 270 271 if (valid_lt > (uint32_t)c->valid_until) 272 valid_lt = c->valid_until; 273 274 if (valid_lt != UINT32_MAX) 275 valid_lt -= now; 276 277 func(&addr, prefix, preferred_lt, valid_lt, 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_lt, 292 _unused uint32_t valid_lt, 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_lt, 312 _unused uint32_t valid_lt, 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_lt > (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 struct odhcpd_ipaddr *n; 670 char *saveptr2, *x; 671 672 n = realloc(c->managed, (c->managed_size + 1) * sizeof(*c->managed)); 673 if (!n) 674 continue; 675 c->managed = n; 676 n = &c->managed[c->managed_size]; 677 678 x = strtok_r(line, ",", &saveptr2); 679 if (odhcpd_parse_addr6_prefix(x, &n->addr.in6, &n->prefix)) 680 continue; 681 682 x = strtok_r(NULL, ",", &saveptr2); 683 if (sscanf(x, "%u", &n->preferred_lt) < 1) 684 continue; 685 686 x = strtok_r(NULL, ",", &saveptr2); 687 if (sscanf(x, "%u", &n->valid_lt) < 1) 688 continue; 689 690 if (n->preferred_lt > n->valid_lt) 691 continue; 692 693 if (UINT32_MAX - now < n->preferred_lt) 694 n->preferred_lt = UINT32_MAX; 695 else 696 n->preferred_lt += now; 697 698 if (UINT32_MAX - now < n->valid_lt) 699 n->valid_lt = UINT32_MAX; 700 else 701 n->valid_lt += now; 702 703 n->dprefix = 0; 704 705 ++c->managed_size; 706 } 707 708 ustream_consume(s, end - data); 709 } 710 711 if (first && c->managed_size == 0) 712 free_assignment(c); 713 else if (first) 714 c->valid_until = now + 150; 715 } 716 717 718 /* TCP transmission has ended, either because of success or timeout or other error */ 719 static void managed_handle_pd_done(struct ustream *s) 720 { 721 struct ustream_fd *fd = container_of(s, struct ustream_fd, stream); 722 struct dhcp_assignment *c = container_of(fd, struct dhcp_assignment, managed_sock); 723 724 c->valid_until = odhcpd_time() + 15; 725 726 c->managed_size = 0; 727 728 if (c->accept_reconf) 729 c->reconf_cnt = 1; 730 } 731 732 static bool assign_pd(struct interface *iface, struct dhcp_assignment *assign) 733 { 734 struct dhcp_assignment *c; 735 736 if (iface->dhcpv6_pd_manager[0]) { 737 int fd = usock(USOCK_UNIX | USOCK_TCP, iface->dhcpv6_pd_manager, NULL); 738 if (fd >= 0) { 739 struct pollfd pfd = { .fd = fd, .events = POLLIN }; 740 char iaidbuf[298]; 741 742 odhcpd_hexlify(iaidbuf, assign->clid_data, assign->clid_len); 743 744 assign->managed_sock.stream.notify_read = managed_handle_pd_data; 745 assign->managed_sock.stream.notify_state = managed_handle_pd_done; 746 ustream_fd_init(&assign->managed_sock, fd); 747 ustream_printf(&assign->managed_sock.stream, "%s,%x\n::/%d,0,0\n\n", 748 iaidbuf, assign->iaid, assign->length); 749 ustream_write_pending(&assign->managed_sock.stream); 750 assign->managed_size = -1; 751 752 assign->valid_until = odhcpd_time() + 15; 753 754 list_add(&assign->head, &iface->ia_assignments); 755 756 /* Wait initial period of up to 250ms for immediate assignment */ 757 if (poll(&pfd, 1, 250) < 0) { 758 syslog(LOG_ERR, "poll(): %m"); 759 return false; 760 } 761 762 managed_handle_pd_data(&assign->managed_sock.stream, 0); 763 764 if (fcntl(fd, F_GETFL) >= 0 && assign->managed_size > 0) 765 return true; 766 } 767 768 return false; 769 } else if (iface->addr6_len < 1) 770 return false; 771 772 /* Try honoring the hint first */ 773 uint32_t current = 1, asize = (1 << (64 - assign->length)) - 1; 774 if (assign->assigned_subnet_id) { 775 list_for_each_entry(c, &iface->ia_assignments, head) { 776 if (c->flags & OAF_DHCPV6_NA) 777 continue; 778 779 if (assign->assigned_subnet_id >= current && assign->assigned_subnet_id + asize < c->assigned_subnet_id) { 780 list_add_tail(&assign->head, &c->head); 781 782 if (assign->flags & OAF_BOUND) 783 apply_lease(assign, true); 784 785 return true; 786 } 787 788 current = (c->assigned_subnet_id + (1 << (64 - c->length))); 789 } 790 } 791 792 /* Fallback to a variable assignment */ 793 current = 1; 794 list_for_each_entry(c, &iface->ia_assignments, head) { 795 if (c->flags & OAF_DHCPV6_NA) 796 continue; 797 798 current = (current + asize) & (~asize); 799 800 if (current + asize < c->assigned_subnet_id) { 801 assign->assigned_subnet_id = current; 802 list_add_tail(&assign->head, &c->head); 803 804 if (assign->flags & OAF_BOUND) 805 apply_lease(assign, true); 806 807 return true; 808 } 809 810 current = (c->assigned_subnet_id + (1 << (64 - c->length))); 811 } 812 813 return false; 814 } 815 816 /* Check iid against reserved IPv6 interface identifiers. 817 Refer to: 818 http://www.iana.org/assignments/ipv6-interface-ids */ 819 static bool is_reserved_ipv6_iid(uint64_t iid) 820 { 821 if (iid == 0x0000000000000000) 822 /* Subnet-Router Anycast [RFC4291] */ 823 return true; 824 825 if ((iid & 0xFFFFFFFFFF000000) == 0x02005EFFFE000000) 826 /* Reserved IPv6 Interface Identifiers corresponding 827 to the IANA Ethernet Block [RFC4291] */ 828 return true; 829 830 if ((iid & 0xFFFFFFFFFFFFFF80) == 0xFDFFFFFFFFFFFF80) 831 /* Reserved Subnet Anycast Addresses [RFC2526] */ 832 return true; 833 834 return false; 835 } 836 837 static bool assign_na(struct interface *iface, struct dhcp_assignment *a) 838 { 839 struct dhcp_assignment *c; 840 uint32_t seed = 0; 841 842 /* Preconfigured assignment by static lease */ 843 if (a->assigned_host_id) { 844 list_for_each_entry(c, &iface->ia_assignments, head) { 845 if (!(c->flags & OAF_DHCPV6_NA) || c->assigned_host_id > a->assigned_host_id ) { 846 list_add_tail(&a->head, &c->head); 847 return true; 848 } else if (c->assigned_host_id == a->assigned_host_id) 849 return false; 850 } 851 } 852 853 /* Seed RNG with checksum of DUID */ 854 for (size_t i = 0; i < a->clid_len; ++i) 855 seed += a->clid_data[i]; 856 srandom(seed); 857 858 /* Try to assign up to 100x */ 859 for (size_t i = 0; i < 100; ++i) { 860 uint64_t try; 861 862 if (iface->dhcpv6_hostid_len > 32) { 863 uint32_t mask_high; 864 865 if (iface->dhcpv6_hostid_len >= 64) 866 mask_high = UINT32_MAX; 867 else 868 mask_high = (1 << (iface->dhcpv6_hostid_len - 32)) - 1; 869 870 do { 871 try = (uint32_t)random(); 872 try |= (uint64_t)((uint32_t)random() & mask_high) << 32; 873 } while (try < 0x100); 874 } else { 875 uint32_t mask_low; 876 877 if (iface->dhcpv6_hostid_len == 32) 878 mask_low = UINT32_MAX; 879 else 880 mask_low = (1 << iface->dhcpv6_hostid_len) - 1; 881 do try = ((uint32_t)random()) & mask_low; while (try < 0x100); 882 } 883 884 if (is_reserved_ipv6_iid(try)) 885 continue; 886 887 if (config_find_lease_by_hostid(try)) 888 continue; 889 890 list_for_each_entry(c, &iface->ia_assignments, head) { 891 if (!(c->flags & OAF_DHCPV6_NA) || c->assigned_host_id > try) { 892 a->assigned_host_id = try; 893 list_add_tail(&a->head, &c->head); 894 return true; 895 } else if (c->assigned_host_id == try) 896 break; 897 } 898 } 899 900 return false; 901 } 902 903 static void handle_addrlist_change(struct netevent_handler_info *info) 904 { 905 struct interface *iface = info->iface; 906 struct dhcp_assignment *c, *d, *border = list_last_entry( 907 &iface->ia_assignments, struct dhcp_assignment, head); 908 struct list_head reassign = LIST_HEAD_INIT(reassign); 909 time_t now = odhcpd_time(); 910 911 list_for_each_entry(c, &iface->ia_assignments, head) { 912 if ((c->flags & OAF_DHCPV6_PD) && !(iface->ra_flags & ND_RA_FLAG_MANAGED) 913 && (c->flags & OAF_BOUND)) 914 __apply_lease(c, info->addrs_old.addrs, 915 info->addrs_old.len, false); 916 } 917 918 set_border_assignment_size(iface, border); 919 920 list_for_each_entry_safe(c, d, &iface->ia_assignments, head) { 921 if (c->clid_len == 0 || 922 !(c->flags & OAF_DHCPV6_PD) || 923 (!INFINITE_VALID(c->valid_until) && c->valid_until < now) || 924 c->managed_size) 925 continue; 926 927 if (c->assigned_subnet_id >= border->assigned_subnet_id) 928 list_move(&c->head, &reassign); 929 else if (c->flags & OAF_BOUND) 930 apply_lease(c, true); 931 932 if (c->accept_reconf && c->reconf_cnt == 0) { 933 struct dhcp_assignment *a; 934 935 start_reconf(c); 936 937 /* Leave all other assignments of that client alone */ 938 list_for_each_entry(a, &iface->ia_assignments, head) 939 if (a != c && a->clid_len == c->clid_len && 940 !memcmp(a->clid_data, c->clid_data, a->clid_len)) 941 a->reconf_cnt = INT_MAX; 942 } 943 } 944 945 while (!list_empty(&reassign)) { 946 c = list_first_entry(&reassign, struct dhcp_assignment, head); 947 list_del_init(&c->head); 948 if (!assign_pd(iface, c)) 949 free_assignment(c); 950 } 951 952 dhcpv6_ia_write_statefile(); 953 } 954 955 static void reconf_timeout_cb(struct uloop_timeout *event) 956 { 957 struct dhcp_assignment *a = container_of(event, struct dhcp_assignment, reconf_timer); 958 959 if (a->reconf_cnt > 0 && a->reconf_cnt < DHCPV6_REC_MAX_RC) { 960 send_reconf(a); 961 uloop_timeout_set(&a->reconf_timer, 962 DHCPV6_REC_TIMEOUT << a->reconf_cnt); 963 a->reconf_cnt++; 964 } else 965 stop_reconf(a); 966 } 967 968 static void start_reconf(struct dhcp_assignment *a) 969 { 970 uloop_timeout_set(&a->reconf_timer, 971 DHCPV6_REC_TIMEOUT << a->reconf_cnt); 972 a->reconf_timer.cb = reconf_timeout_cb; 973 a->reconf_cnt++; 974 975 send_reconf(a); 976 } 977 978 static void stop_reconf(struct dhcp_assignment *a) 979 { 980 uloop_timeout_cancel(&a->reconf_timer); 981 a->reconf_cnt = 0; 982 a->reconf_timer.cb = NULL; 983 } 984 985 static void valid_until_cb(struct uloop_timeout *event) 986 { 987 struct interface *iface; 988 time_t now = odhcpd_time(); 989 990 avl_for_each_element(&interfaces, iface, avl) { 991 struct dhcp_assignment *a, *n; 992 993 if (iface->dhcpv6 != MODE_SERVER) 994 continue; 995 996 list_for_each_entry_safe(a, n, &iface->ia_assignments, head) { 997 if (a->clid_len > 0 && !INFINITE_VALID(a->valid_until) && a->valid_until < now) 998 free_assignment(a); 999 } 1000 } 1001 uloop_timeout_set(event, 1000); 1002 } 1003 1004 static size_t build_ia(uint8_t *buf, size_t buflen, uint16_t status, 1005 const struct dhcpv6_ia_hdr *ia, struct dhcp_assignment *a, 1006 struct interface *iface, bool request) 1007 { 1008 struct dhcpv6_ia_hdr o_ia = { 1009 .type = ia->type, 1010 .len = 0, 1011 .iaid = ia->iaid, 1012 .t1 = 0, 1013 .t2 = 0, 1014 }; 1015 size_t ia_len = sizeof(o_ia); 1016 time_t now = odhcpd_time(); 1017 1018 if (buflen < ia_len) 1019 return 0; 1020 1021 if (status) { 1022 struct __attribute__((packed)) { 1023 uint16_t type; 1024 uint16_t len; 1025 uint16_t val; 1026 } o_status = { 1027 .type = htons(DHCPV6_OPT_STATUS), 1028 .len = htons(sizeof(o_status) - 4), 1029 .val = htons(status), 1030 }; 1031 1032 memcpy(buf + ia_len, &o_status, sizeof(o_status)); 1033 ia_len += sizeof(o_status); 1034 1035 o_ia.len = htons(ia_len - 4); 1036 memcpy(buf, &o_ia, sizeof(o_ia)); 1037 1038 return ia_len; 1039 } 1040 1041 if (a) { 1042 uint32_t leasetime, preferred_lt; 1043 1044 if (a->leasetime) { 1045 leasetime = a->leasetime; 1046 preferred_lt = a->leasetime; 1047 } else { 1048 leasetime = iface->dhcp_leasetime; 1049 preferred_lt = iface->preferred_lifetime; 1050 } 1051 1052 uint32_t valid_lt = leasetime; 1053 1054 struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->addr6; 1055 size_t addrlen = (a->managed) ? (size_t)a->managed_size : iface->addr6_len; 1056 size_t m = get_preferred_addr(addrs, addrlen); 1057 1058 for (size_t i = 0; i < addrlen; ++i) { 1059 uint32_t prefix_preferred_lt, prefix_valid_lt; 1060 1061 if (!valid_addr(&addrs[i], now)) 1062 continue; 1063 1064 /* Filter Out Prefixes */ 1065 if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface)) { 1066 char addrbuf[INET6_ADDRSTRLEN]; 1067 syslog(LOG_INFO, "Address %s filtered out on %s", 1068 inet_ntop(AF_INET6, &addrs[i].addr.in6, addrbuf, sizeof(addrbuf)), 1069 iface->name); 1070 continue; 1071 } 1072 1073 prefix_preferred_lt = addrs[i].preferred_lt; 1074 prefix_valid_lt = addrs[i].valid_lt; 1075 1076 if (prefix_preferred_lt != UINT32_MAX) 1077 prefix_preferred_lt -= now; 1078 1079 if (prefix_preferred_lt > preferred_lt) 1080 prefix_preferred_lt = preferred_lt; 1081 1082 if (prefix_valid_lt != UINT32_MAX) 1083 prefix_valid_lt -= now; 1084 1085 if (prefix_valid_lt > leasetime) 1086 prefix_valid_lt = leasetime; 1087 1088 if (prefix_preferred_lt > prefix_valid_lt) 1089 prefix_preferred_lt = prefix_valid_lt; 1090 1091 if (a->flags & OAF_DHCPV6_PD) { 1092 struct dhcpv6_ia_prefix o_ia_p = { 1093 .type = htons(DHCPV6_OPT_IA_PREFIX), 1094 .len = htons(sizeof(o_ia_p) - 4), 1095 .preferred_lt = htonl(prefix_preferred_lt), 1096 .valid_lt = htonl(prefix_valid_lt), 1097 .prefix = (a->managed_size) ? addrs[i].prefix : a->length, 1098 .addr = addrs[i].addr.in6, 1099 }; 1100 1101 o_ia_p.addr.s6_addr32[1] |= htonl(a->assigned_subnet_id); 1102 o_ia_p.addr.s6_addr32[2] = o_ia_p.addr.s6_addr32[3] = 0; 1103 1104 if (!valid_prefix_length(a, addrs[i].prefix)) 1105 continue; 1106 1107 if (buflen < ia_len + sizeof(o_ia_p)) 1108 return 0; 1109 1110 memcpy(buf + ia_len, &o_ia_p, sizeof(o_ia_p)); 1111 ia_len += sizeof(o_ia_p); 1112 } 1113 1114 if (a->flags & OAF_DHCPV6_NA) { 1115 struct dhcpv6_ia_addr o_ia_a = { 1116 .type = htons(DHCPV6_OPT_IA_ADDR), 1117 .len = htons(sizeof(o_ia_a) - 4), 1118 .addr = addrs[i].addr.in6, 1119 .preferred_lt = htonl(prefix_preferred_lt), 1120 .valid_lt = htonl(prefix_valid_lt) 1121 }; 1122 1123 o_ia_a.addr.s6_addr32[2] = htonl(a->assigned_host_id >> 32); 1124 o_ia_a.addr.s6_addr32[3] = htonl(a->assigned_host_id & UINT32_MAX); 1125 1126 if (!ADDR_ENTRY_VALID_IA_ADDR(iface, i, m, addrs)) 1127 continue; 1128 1129 if (buflen < ia_len + sizeof(o_ia_a)) 1130 return 0; 1131 1132 memcpy(buf + ia_len, &o_ia_a, sizeof(o_ia_a)); 1133 ia_len += sizeof(o_ia_a); 1134 } 1135 1136 /* Calculate T1 / T2 based on non-deprecated addresses */ 1137 if (prefix_preferred_lt > 0) { 1138 if (prefix_preferred_lt < preferred_lt) 1139 preferred_lt = prefix_preferred_lt; 1140 1141 if (prefix_valid_lt < valid_lt) 1142 valid_lt = prefix_valid_lt; 1143 } 1144 } 1145 1146 if (!INFINITE_VALID(a->valid_until)) 1147 /* UINT32_MAX is RFC defined as infinite lease-time */ 1148 a->valid_until = (valid_lt == UINT32_MAX) ? 0 : valid_lt + now; 1149 1150 if (!INFINITE_VALID(a->preferred_until)) 1151 /* UINT32_MAX is RFC defined as infinite lease-time */ 1152 a->preferred_until = (preferred_lt == UINT32_MAX) ? 0 : preferred_lt + now; 1153 1154 o_ia.t1 = htonl((preferred_lt == UINT32_MAX) ? preferred_lt : preferred_lt * 5 / 10); 1155 o_ia.t2 = htonl((preferred_lt == UINT32_MAX) ? preferred_lt : preferred_lt * 8 / 10); 1156 1157 if (!o_ia.t1) 1158 o_ia.t1 = htonl(1); 1159 1160 if (!o_ia.t2) 1161 o_ia.t2 = htonl(1); 1162 } 1163 1164 if (!request) { 1165 uint8_t *odata, *end = ((uint8_t*)ia) + htons(ia->len) + 4; 1166 uint16_t otype, olen; 1167 1168 dhcpv6_for_each_option((uint8_t*)&ia[1], end, otype, olen, odata) { 1169 struct dhcpv6_ia_prefix *ia_p = (struct dhcpv6_ia_prefix *)&odata[-4]; 1170 struct dhcpv6_ia_addr *ia_a = (struct dhcpv6_ia_addr *)&odata[-4]; 1171 bool found = false; 1172 1173 if ((otype != DHCPV6_OPT_IA_PREFIX || olen < sizeof(*ia_p) - 4) && 1174 (otype != DHCPV6_OPT_IA_ADDR || olen < sizeof(*ia_a) - 4)) 1175 continue; 1176 1177 if (a) { 1178 struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->addr6; 1179 size_t addrlen = (a->managed) ? (size_t)a->managed_size : iface->addr6_len; 1180 1181 for (size_t i = 0; i < addrlen; ++i) { 1182 struct in6_addr addr; 1183 1184 if (!valid_addr(&addrs[i], now)) 1185 continue; 1186 1187 if (!valid_prefix_length(a, addrs[i].prefix)) 1188 continue; 1189 1190 if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface)) 1191 continue; 1192 1193 addr = addrs[i].addr.in6; 1194 if (ia->type == htons(DHCPV6_OPT_IA_PD)) { 1195 addr.s6_addr32[1] |= htonl(a->assigned_subnet_id); 1196 addr.s6_addr32[2] = addr.s6_addr32[3] = 0; 1197 1198 if (!memcmp(&ia_p->addr, &addr, sizeof(addr)) && 1199 ia_p->prefix == ((a->managed) ? addrs[i].prefix : a->length)) 1200 found = true; 1201 } else { 1202 addr.s6_addr32[2] = htonl(a->assigned_host_id >> 32); 1203 addr.s6_addr32[3] = htonl(a->assigned_host_id & UINT32_MAX); 1204 1205 if (!memcmp(&ia_a->addr, &addr, sizeof(addr))) 1206 found = true; 1207 } 1208 } 1209 } 1210 1211 if (!found) { 1212 if (otype == DHCPV6_OPT_IA_PREFIX) { 1213 struct dhcpv6_ia_prefix o_ia_p = { 1214 .type = htons(DHCPV6_OPT_IA_PREFIX), 1215 .len = htons(sizeof(o_ia_p) - 4), 1216 .preferred_lt = 0, 1217 .valid_lt = 0, 1218 .prefix = ia_p->prefix, 1219 .addr = ia_p->addr, 1220 }; 1221 1222 if (buflen < ia_len + sizeof(o_ia_p)) 1223 return 0; 1224 1225 memcpy(buf + ia_len, &o_ia_p, sizeof(o_ia_p)); 1226 ia_len += sizeof(o_ia_p); 1227 } else { 1228 struct dhcpv6_ia_addr o_ia_a = { 1229 .type = htons(DHCPV6_OPT_IA_ADDR), 1230 .len = htons(sizeof(o_ia_a) - 4), 1231 .addr = ia_a->addr, 1232 .preferred_lt = 0, 1233 .valid_lt = 0, 1234 }; 1235 1236 if (buflen < ia_len + sizeof(o_ia_a)) 1237 continue; 1238 1239 memcpy(buf + ia_len, &o_ia_a, sizeof(o_ia_a)); 1240 ia_len += sizeof(o_ia_a); 1241 } 1242 } 1243 } 1244 } 1245 1246 o_ia.len = htons(ia_len - 4); 1247 memcpy(buf, &o_ia, sizeof(o_ia)); 1248 return ia_len; 1249 } 1250 1251 struct log_ctxt { 1252 char *buf; 1253 int buf_len; 1254 int buf_idx; 1255 }; 1256 1257 static void dhcpv6_log_ia_addr(struct in6_addr *addr, int prefix, _unused uint32_t pref_lt, 1258 _unused uint32_t valid_lt, void *arg) 1259 { 1260 struct log_ctxt *ctxt = (struct log_ctxt *)arg; 1261 char addrbuf[INET6_ADDRSTRLEN]; 1262 1263 inet_ntop(AF_INET6, addr, addrbuf, sizeof(addrbuf)); 1264 ctxt->buf_idx += snprintf(ctxt->buf + ctxt->buf_idx, ctxt->buf_len - ctxt->buf_idx, 1265 "%s/%d ", addrbuf, prefix); 1266 } 1267 1268 static void dhcpv6_log(uint8_t msgtype, struct interface *iface, time_t now, 1269 const char *duidbuf, bool is_pd, struct dhcp_assignment *a, int code) 1270 { 1271 const char *type = "UNKNOWN"; 1272 const char *status = "UNKNOWN"; 1273 1274 switch (msgtype) { 1275 case DHCPV6_MSG_SOLICIT: 1276 type = "SOLICIT"; 1277 break; 1278 case DHCPV6_MSG_REQUEST: 1279 type = "REQUEST"; 1280 break; 1281 case DHCPV6_MSG_CONFIRM: 1282 type = "CONFIRM"; 1283 break; 1284 case DHCPV6_MSG_RENEW: 1285 type = "RENEW"; 1286 break; 1287 case DHCPV6_MSG_REBIND: 1288 type = "REBIND"; 1289 break; 1290 case DHCPV6_MSG_RELEASE: 1291 type = "RELEASE"; 1292 break; 1293 case DHCPV6_MSG_DECLINE: 1294 type = "DECLINE"; 1295 break; 1296 } 1297 1298 switch (code) { 1299 case DHCPV6_STATUS_OK: 1300 status = "ok"; 1301 break; 1302 case DHCPV6_STATUS_NOADDRSAVAIL: 1303 status = "no addresses available"; 1304 break; 1305 case DHCPV6_STATUS_NOBINDING: 1306 status = "no binding"; 1307 break; 1308 case DHCPV6_STATUS_NOTONLINK: 1309 status = "not on-link"; 1310 break; 1311 case DHCPV6_STATUS_NOPREFIXAVAIL: 1312 status = "no prefix available"; 1313 break; 1314 } 1315 1316 char leasebuf[256] = ""; 1317 1318 if (a) { 1319 struct log_ctxt ctxt = {.buf = leasebuf, 1320 .buf_len = sizeof(leasebuf), 1321 .buf_idx = 0 }; 1322 1323 dhcpv6_ia_enum_addrs(iface, a, now, dhcpv6_log_ia_addr, &ctxt); 1324 } 1325 1326 syslog(LOG_INFO, "DHCPV6 %s %s from %s on %s: %s %s", type, (is_pd) ? "IA_PD" : "IA_NA", 1327 duidbuf, iface->name, status, leasebuf); 1328 } 1329 1330 static bool dhcpv6_ia_on_link(const struct dhcpv6_ia_hdr *ia, struct dhcp_assignment *a, 1331 struct interface *iface) 1332 { 1333 struct odhcpd_ipaddr *addrs = (a && a->managed) ? a->managed : iface->addr6; 1334 size_t addrlen = (a && a->managed) ? (size_t)a->managed_size : iface->addr6_len; 1335 time_t now = odhcpd_time(); 1336 uint8_t *odata, *end = ((uint8_t*)ia) + htons(ia->len) + 4; 1337 uint16_t otype, olen; 1338 bool onlink = true; 1339 1340 dhcpv6_for_each_option((uint8_t*)&ia[1], end, otype, olen, odata) { 1341 struct dhcpv6_ia_prefix *p = (struct dhcpv6_ia_prefix *)&odata[-4]; 1342 struct dhcpv6_ia_addr *n = (struct dhcpv6_ia_addr *)&odata[-4]; 1343 1344 if ((otype != DHCPV6_OPT_IA_PREFIX || olen < sizeof(*p) - 4) && 1345 (otype != DHCPV6_OPT_IA_ADDR || olen < sizeof(*n) - 4)) 1346 continue; 1347 1348 onlink = false; 1349 for (size_t i = 0; i < addrlen; ++i) { 1350 if (!valid_addr(&addrs[i], now)) 1351 continue; 1352 1353 if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface)) 1354 continue; 1355 1356 if (ia->type == htons(DHCPV6_OPT_IA_PD)) { 1357 if (p->prefix < addrs[i].prefix || 1358 odhcpd_bmemcmp(&p->addr, &addrs[i].addr.in6, addrs[i].prefix)) 1359 continue; 1360 1361 } else if (odhcpd_bmemcmp(&n->addr, &addrs[i].addr.in6, addrs[i].prefix)) 1362 continue; 1363 1364 onlink = true; 1365 } 1366 1367 if (!onlink) 1368 break; 1369 } 1370 1371 return onlink; 1372 } 1373 1374 ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *iface, 1375 const struct sockaddr_in6 *addr, const void *data, const uint8_t *end) 1376 { 1377 struct lease *l; 1378 struct dhcp_assignment *first = NULL; 1379 const struct dhcpv6_client_header *hdr = data; 1380 time_t now = odhcpd_time(); 1381 uint16_t otype, olen, clid_len = 0; 1382 uint8_t *start = (uint8_t *)&hdr[1], *odata; 1383 uint8_t *clid_data = NULL, mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 1384 size_t hostname_len = 0, response_len = 0; 1385 bool notonlink = false, rapid_commit = false, accept_reconf = false; 1386 char duidbuf[261], hostname[256]; 1387 1388 dhcpv6_for_each_option(start, end, otype, olen, odata) { 1389 if (otype == DHCPV6_OPT_CLIENTID) { 1390 clid_data = odata; 1391 clid_len = olen; 1392 1393 if (olen == 14 && odata[0] == 0 && odata[1] == 1) 1394 memcpy(mac, &odata[8], sizeof(mac)); 1395 else if (olen == 10 && odata[0] == 0 && odata[1] == 3) 1396 memcpy(mac, &odata[4], sizeof(mac)); 1397 1398 if (olen <= 130) 1399 odhcpd_hexlify(duidbuf, odata, olen); 1400 } else if (otype == DHCPV6_OPT_FQDN && olen >= 2 && olen <= 255) { 1401 uint8_t fqdn_buf[256]; 1402 memcpy(fqdn_buf, odata, olen); 1403 fqdn_buf[olen++] = 0; 1404 1405 if (dn_expand(&fqdn_buf[1], &fqdn_buf[olen], &fqdn_buf[1], hostname, sizeof(hostname)) > 0) 1406 hostname_len = strcspn(hostname, "."); 1407 } else if (otype == DHCPV6_OPT_RECONF_ACCEPT) 1408 accept_reconf = true; 1409 else if (otype == DHCPV6_OPT_RAPID_COMMIT && hdr->msg_type == DHCPV6_MSG_SOLICIT) 1410 rapid_commit = true; 1411 } 1412 1413 if (!clid_data || !clid_len || clid_len > 130) 1414 goto out; 1415 1416 l = config_find_lease_by_duid(clid_data, clid_len); 1417 if (!l) 1418 l = config_find_lease_by_mac(mac); 1419 1420 dhcpv6_for_each_option(start, end, otype, olen, odata) { 1421 bool is_pd = (otype == DHCPV6_OPT_IA_PD); 1422 bool is_na = (otype == DHCPV6_OPT_IA_NA); 1423 bool ia_addr_present = false; 1424 if (!is_pd && !is_na) 1425 continue; 1426 1427 struct dhcpv6_ia_hdr *ia = (struct dhcpv6_ia_hdr*)&odata[-4]; 1428 size_t ia_response_len = 0; 1429 uint8_t reqlen = (is_pd) ? 62 : 128; 1430 uint32_t reqhint = 0; 1431 1432 /* Parse request hint for IA-PD */ 1433 if (is_pd) { 1434 uint8_t *sdata; 1435 uint16_t stype, slen; 1436 dhcpv6_for_each_option(&ia[1], odata + olen, stype, slen, sdata) { 1437 if (stype != DHCPV6_OPT_IA_PREFIX || slen < sizeof(struct dhcpv6_ia_prefix) - 4) 1438 continue; 1439 1440 struct dhcpv6_ia_prefix *p = (struct dhcpv6_ia_prefix*)&sdata[-4]; 1441 if (p->prefix) { 1442 reqlen = p->prefix; 1443 reqhint = ntohl(p->addr.s6_addr32[1]); 1444 if (reqlen > 32 && reqlen <= 64) 1445 reqhint &= (1U << (64 - reqlen)) - 1; 1446 } 1447 } 1448 1449 if (reqlen > 64) 1450 reqlen = 64; 1451 1452 /* 1453 * A requesting router can include a desired prefix length for its 1454 * delegation. The delegating router (us) is not required to honor 1455 * the hint (RFC3633, section 11.2, we MAY choose to use the 1456 * information in the option; RFC8168, section 3.2 has several SHOULDs 1457 * about desired choices for selecting a prefix to delegate). 1458 * 1459 * We support a policy setting to conserve prefix space, which purposely 1460 * assigns prefixes that might not match the requesting router's hint. 1461 * 1462 * If the minimum prefix length is set in this interface's 1463 * configuration, we use it as a floor for the requested (hinted) 1464 * prefix length. This allows us to conserve prefix space so that 1465 * any single router can't grab too much of it. Consider if we have 1466 * an interface with a /56 prefix. A requesting router could ask for 1467 * a /58 and take 1/4 of our total address space. But if we set a 1468 * minimum of /60, we can limit each requesting router to get only 1469 * 1/16 of our total address space. 1470 */ 1471 if (iface->dhcpv6_pd_min_len && reqlen < iface->dhcpv6_pd_min_len) { 1472 syslog(LOG_INFO, "clamping requested PD from %d to %d", 1473 reqlen, iface->dhcpv6_pd_min_len); 1474 reqlen = iface->dhcpv6_pd_min_len; 1475 } 1476 } else if (is_na) { 1477 uint8_t *sdata; 1478 uint16_t stype, slen; 1479 dhcpv6_for_each_option(&ia[1], odata + olen, stype, slen, sdata) { 1480 if (stype != DHCPV6_OPT_IA_ADDR || slen < sizeof(struct dhcpv6_ia_addr) - 4) 1481 continue; 1482 1483 ia_addr_present = true; 1484 } 1485 } 1486 1487 /* Find assignment */ 1488 struct dhcp_assignment *c, *a = NULL; 1489 list_for_each_entry(c, &iface->ia_assignments, head) { 1490 if ((c->clid_len == clid_len && !memcmp(c->clid_data, clid_data, clid_len)) && 1491 c->iaid == ia->iaid && (INFINITE_VALID(c->valid_until) || now < c->valid_until) && 1492 ((is_pd && (c->flags & OAF_DHCPV6_PD)) || (is_na && (c->flags & OAF_DHCPV6_NA)))) { 1493 a = c; 1494 1495 /* Reset state */ 1496 if (a->flags & OAF_BOUND) 1497 apply_lease(a, false); 1498 1499 stop_reconf(a); 1500 break; 1501 } 1502 } 1503 1504 if (l && a && a->lease != l) { 1505 free_assignment(a); 1506 a = NULL; 1507 } 1508 1509 /* Generic message handling */ 1510 uint16_t status = DHCPV6_STATUS_OK; 1511 if (a && a->managed_size < 0) 1512 return -1; 1513 1514 if (hdr->msg_type == DHCPV6_MSG_SOLICIT || 1515 hdr->msg_type == DHCPV6_MSG_REQUEST || 1516 (hdr->msg_type == DHCPV6_MSG_REBIND && !a)) { 1517 bool assigned = !!a; 1518 1519 if (!a) { 1520 if ((!iface->no_dynamic_dhcp || (l && is_na)) && 1521 (iface->dhcpv6_pd || iface->dhcpv6_na)) { 1522 /* Create new binding */ 1523 a = alloc_assignment(clid_len); 1524 1525 if (a) { 1526 a->clid_len = clid_len; 1527 memcpy(a->clid_data, clid_data, clid_len); 1528 a->iaid = ia->iaid; 1529 a->length = reqlen; 1530 a->peer = *addr; 1531 if (is_na) 1532 a->assigned_host_id = l ? l->hostid : 0; 1533 else 1534 a->assigned_subnet_id = reqhint; 1535 a->valid_until = now; 1536 a->preferred_until = now; 1537 a->dhcp_free_cb = dhcpv6_ia_free_assignment; 1538 a->iface = iface; 1539 a->flags = (is_pd ? OAF_DHCPV6_PD : OAF_DHCPV6_NA); 1540 1541 if (first) 1542 memcpy(a->key, first->key, sizeof(a->key)); 1543 else 1544 odhcpd_urandom(a->key, sizeof(a->key)); 1545 1546 if (is_pd && iface->dhcpv6_pd) 1547 while (!(assigned = assign_pd(iface, a)) && 1548 !a->managed_size && ++a->length <= 64); 1549 else if (is_na && iface->dhcpv6_na) 1550 assigned = assign_na(iface, a); 1551 1552 if (l && assigned) { 1553 a->flags |= OAF_STATIC; 1554 1555 if (l->hostname) 1556 a->hostname = strdup(l->hostname); 1557 1558 if (l->leasetime) 1559 a->leasetime = l->leasetime; 1560 1561 list_add(&a->lease_list, &l->assignments); 1562 a->lease = l; 1563 } 1564 1565 if (a->managed_size && !assigned) 1566 return -1; 1567 } 1568 } 1569 } 1570 1571 if (!assigned || iface->addr6_len == 0) 1572 /* Set error status */ 1573 status = (is_pd) ? DHCPV6_STATUS_NOPREFIXAVAIL : DHCPV6_STATUS_NOADDRSAVAIL; 1574 else if (hdr->msg_type == DHCPV6_MSG_REQUEST && !dhcpv6_ia_on_link(ia, a, iface)) { 1575 /* Send NOTONLINK status for the IA */ 1576 status = DHCPV6_STATUS_NOTONLINK; 1577 assigned = false; 1578 } else if (accept_reconf && assigned && !first && 1579 hdr->msg_type != DHCPV6_MSG_REBIND) { 1580 size_t handshake_len = 4; 1581 buf[0] = 0; 1582 buf[1] = DHCPV6_OPT_RECONF_ACCEPT; 1583 buf[2] = 0; 1584 buf[3] = 0; 1585 1586 if (hdr->msg_type == DHCPV6_MSG_REQUEST) { 1587 struct dhcpv6_auth_reconfigure auth = { 1588 htons(DHCPV6_OPT_AUTH), 1589 htons(sizeof(auth) - 4), 1590 3, 1, 0, 1591 {htonl(time(NULL)), htonl(++serial)}, 1592 1, 1593 {0} 1594 }; 1595 memcpy(auth.key, a->key, sizeof(a->key)); 1596 memcpy(buf + handshake_len, &auth, sizeof(auth)); 1597 handshake_len += sizeof(auth); 1598 } 1599 1600 1601 buf += handshake_len; 1602 buflen -= handshake_len; 1603 response_len += handshake_len; 1604 1605 first = a; 1606 } 1607 1608 ia_response_len = build_ia(buf, buflen, status, ia, a, iface, 1609 hdr->msg_type == DHCPV6_MSG_REBIND ? false : true); 1610 1611 /* Was only a solicitation: mark binding for removal */ 1612 if (assigned && hdr->msg_type == DHCPV6_MSG_SOLICIT && !rapid_commit) { 1613 a->flags &= ~OAF_BOUND; 1614 a->flags |= OAF_TENTATIVE; 1615 1616 /* Keep tentative assignment around for 60 seconds */ 1617 a->valid_until = now + 60; 1618 1619 } else if (assigned && 1620 ((hdr->msg_type == DHCPV6_MSG_SOLICIT && rapid_commit) || 1621 hdr->msg_type == DHCPV6_MSG_REQUEST || 1622 hdr->msg_type == DHCPV6_MSG_REBIND)) { 1623 if ((!(a->flags & OAF_STATIC) || !a->hostname) && hostname_len > 0) { 1624 a->hostname = realloc(a->hostname, hostname_len + 1); 1625 if (a->hostname) { 1626 memcpy(a->hostname, hostname, hostname_len); 1627 a->hostname[hostname_len] = 0; 1628 1629 if (odhcpd_valid_hostname(a->hostname)) 1630 a->flags &= ~OAF_BROKEN_HOSTNAME; 1631 else 1632 a->flags |= OAF_BROKEN_HOSTNAME; 1633 } 1634 } 1635 a->accept_reconf = accept_reconf; 1636 a->flags &= ~OAF_TENTATIVE; 1637 a->flags |= OAF_BOUND; 1638 apply_lease(a, true); 1639 } else if (!assigned && a && a->managed_size == 0) { 1640 /* Cleanup failed assignment */ 1641 free_assignment(a); 1642 a = NULL; 1643 } 1644 } else if (hdr->msg_type == DHCPV6_MSG_RENEW || 1645 hdr->msg_type == DHCPV6_MSG_RELEASE || 1646 hdr->msg_type == DHCPV6_MSG_REBIND || 1647 hdr->msg_type == DHCPV6_MSG_DECLINE) { 1648 if (!a && hdr->msg_type != DHCPV6_MSG_REBIND) { 1649 status = DHCPV6_STATUS_NOBINDING; 1650 ia_response_len = build_ia(buf, buflen, status, ia, a, iface, false); 1651 } else if (hdr->msg_type == DHCPV6_MSG_RENEW || 1652 hdr->msg_type == DHCPV6_MSG_REBIND) { 1653 ia_response_len = build_ia(buf, buflen, status, ia, a, iface, false); 1654 if (a) { 1655 a->flags |= OAF_BOUND; 1656 apply_lease(a, true); 1657 } 1658 } else if (hdr->msg_type == DHCPV6_MSG_RELEASE) { 1659 a->valid_until = now - 1; 1660 } else if ((a->flags & OAF_DHCPV6_NA) && hdr->msg_type == DHCPV6_MSG_DECLINE) { 1661 a->flags &= ~OAF_BOUND; 1662 1663 if (!(a->flags & OAF_STATIC) || a->lease->hostid != a->assigned_host_id) { 1664 memset(a->clid_data, 0, a->clid_len); 1665 a->valid_until = now + 3600; /* Block address for 1h */ 1666 } else 1667 a->valid_until = now - 1; 1668 } 1669 } else if (hdr->msg_type == DHCPV6_MSG_CONFIRM) { 1670 if (ia_addr_present && !dhcpv6_ia_on_link(ia, a, iface)) { 1671 notonlink = true; 1672 break; 1673 } 1674 1675 if (!ia_addr_present || !a || !(a->flags & OAF_BOUND)) { 1676 response_len = 0; 1677 goto out; 1678 } 1679 } 1680 1681 buf += ia_response_len; 1682 buflen -= ia_response_len; 1683 response_len += ia_response_len; 1684 dhcpv6_log(hdr->msg_type, iface, now, duidbuf, is_pd, a, status); 1685 } 1686 1687 switch (hdr->msg_type) { 1688 case DHCPV6_MSG_RELEASE: 1689 case DHCPV6_MSG_DECLINE: 1690 case DHCPV6_MSG_CONFIRM: 1691 if (response_len + 6 < buflen) { 1692 buf[0] = 0; 1693 buf[1] = DHCPV6_OPT_STATUS; 1694 buf[2] = 0; 1695 buf[3] = 2; 1696 buf[4] = 0; 1697 buf[5] = (notonlink) ? DHCPV6_STATUS_NOTONLINK : DHCPV6_STATUS_OK; 1698 response_len += 6; 1699 } 1700 break; 1701 1702 default: 1703 break; 1704 } 1705 1706 dhcpv6_ia_write_statefile(); 1707 1708 out: 1709 return response_len; 1710 } 1711
This page was automatically generated by LXR 0.3.1. • OpenWrt