1 /** 2 * Copyright (C) 2012-2014 Steven Barth <steven@midlink.org> 3 * Copyright (C) 2017-2018 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 <arpa/inet.h> 17 #include <ctype.h> 18 #include <endian.h> 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <inttypes.h> 22 #include <libubox/md5.h> 23 #include <limits.h> 24 #include <netinet/in.h> 25 #include <net/if.h> 26 #include <net/ethernet.h> 27 #include <resolv.h> 28 #include <signal.h> 29 #include <stdbool.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <sys/ioctl.h> 33 #include <sys/socket.h> 34 #include <sys/time.h> 35 #include <time.h> 36 #include <unistd.h> 37 38 #include "config.h" 39 #include "odhcp6c.h" 40 41 #define ALL_DHCPV6_RELAYS {{{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ 42 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02}}} 43 #define DHCPV6_CLIENT_PORT 546 44 #define DHCPV6_SERVER_PORT 547 45 #define DHCPV6_DUID_LLADDR 3 46 47 #define DHCPV6_SOL_MAX_RT_MIN 60 48 #define DHCPV6_SOL_MAX_RT_MAX 86400 49 #define DHCPV6_INF_MAX_RT_MIN 60 50 #define DHCPV6_INF_MAX_RT_MAX 86400 51 52 static bool dhcpv6_response_is_valid(const void *buf, ssize_t len, 53 const uint8_t transaction[3], enum dhcpv6_msg req_msg_type, 54 const struct in6_addr *daddr); 55 56 static unsigned int dhcpv6_parse_ia(void *opt, void *end, int *ret); 57 58 static unsigned int dhcpv6_calc_refresh_timers(void); 59 static void dhcpv6_handle_status_code(_o_unused const enum dhcpv6_msg orig, 60 const uint16_t code, const void *status_msg, const int len, 61 int *ret); 62 static void dhcpv6_handle_ia_status_code(const enum dhcpv6_msg orig, 63 const struct dhcpv6_ia_hdr *ia_hdr, const uint16_t code, 64 const void *status_msg, const int len, 65 bool handled_status_codes[_DHCPV6_Status_Max], 66 int *ret); 67 static void dhcpv6_add_server_cand(const struct dhcpv6_server_cand *cand); 68 static void dhcpv6_clear_all_server_cand(void); 69 70 static void dhcpv6_log_status_code(const uint16_t code, const char *scope, 71 const void *status_msg, int len); 72 73 static reply_handler dhcpv6_handle_reply; 74 static reply_handler dhcpv6_handle_advert; 75 static reply_handler dhcpv6_handle_rebind_reply; 76 static reply_handler dhcpv6_handle_reconfigure; 77 static int dhcpv6_commit_advert(void); 78 79 // RFC 3315 - 5.5 Timeout and Delay values 80 static const struct dhcpv6_retx dhcpv6_retx_default[_DHCPV6_MSG_MAX] = { 81 [DHCPV6_MSG_UNKNOWN] = { 82 0, 83 1, 84 120, 85 0, 86 "<POLL>", 87 dhcpv6_handle_reconfigure, 88 NULL, 89 false, 90 0, 91 0, 92 0, 93 {0, 0, 0}, 94 0, 95 0, 96 0, 97 -1, 98 0 99 }, 100 [DHCPV6_MSG_SOLICIT] = { 101 DHCPV6_MAX_DELAY, 102 DHCPV6_SOL_INIT_RT, 103 DHCPV6_SOL_MAX_RT, 104 0, 105 "SOLICIT", 106 dhcpv6_handle_advert, 107 dhcpv6_commit_advert, 108 false, 109 0, 110 0, 111 0, 112 {0, 0, 0}, 113 0, 114 0, 115 0, 116 -1, 117 0 118 }, 119 [DHCPV6_MSG_REQUEST] = { 120 0, 121 DHCPV6_REQ_INIT_RT, 122 DHCPV6_REQ_MAX_RT, 123 DHCPV6_REQ_MAX_RC, 124 "REQUEST", 125 dhcpv6_handle_reply, 126 NULL, 127 false, 128 0, 129 0, 130 0, 131 {0, 0, 0}, 132 0, 133 0, 134 0, 135 -1, 136 0 137 }, 138 [DHCPV6_MSG_RENEW] = { 139 0, 140 DHCPV6_REN_INIT_RT, 141 DHCPV6_REN_MAX_RT, 142 0, 143 "RENEW", 144 dhcpv6_handle_reply, 145 NULL, 146 false, 147 0, 148 0, 149 0, 150 {0, 0, 0}, 151 0, 152 0, 153 0, 154 -1, 155 0 156 }, 157 [DHCPV6_MSG_REBIND] = { 158 0, 159 DHCPV6_REB_INIT_RT, 160 DHCPV6_REB_MAX_RT, 161 0, 162 "REBIND", 163 dhcpv6_handle_rebind_reply, 164 NULL, 165 false, 166 0, 167 0, 168 0, 169 {0, 0, 0}, 170 0, 171 0, 172 0, 173 -1, 174 0 175 }, 176 [DHCPV6_MSG_RELEASE] = { 177 0, 178 DHCPV6_REL_INIT_RT, 179 0, 180 DHCPV6_REL_MAX_RC, 181 "RELEASE", 182 NULL, 183 NULL, 184 false, 185 0, 186 0, 187 0, 188 {0, 0, 0}, 189 0, 190 0, 191 0, 192 -1, 193 0 194 }, 195 [DHCPV6_MSG_DECLINE] = { 196 0, 197 DHCPV6_DEC_INIT_RT, 198 0, 199 DHCPV6_DEC_MAX_RC, 200 "DECLINE", 201 NULL, 202 NULL, 203 false, 204 0, 205 0, 206 0, 207 {0, 0, 0}, 208 0, 209 0, 210 0, 211 -1, 212 0 213 }, 214 [DHCPV6_MSG_INFO_REQ] = { 215 DHCPV6_MAX_DELAY, 216 DHCPV6_INF_INIT_RT, 217 DHCPV6_INF_MAX_RT, 218 0, 219 "INFOREQ", 220 dhcpv6_handle_reply, 221 NULL, 222 false, 223 0, 224 0, 225 0, 226 {0, 0, 0}, 227 0, 228 0, 229 0, 230 -1, 231 0 232 }, 233 }; 234 static struct dhcpv6_retx dhcpv6_retx[_DHCPV6_MSG_MAX] = {0}; 235 236 // Sockets 237 static int sock = -1; 238 static int ifindex = -1; 239 static int64_t t1 = 0, t2 = 0, t3 = 0; 240 241 // IA states 242 static enum odhcp6c_ia_mode na_mode = IA_MODE_NONE, pd_mode = IA_MODE_NONE; 243 static bool stateful_only_mode = false; 244 static bool accept_reconfig = false; 245 // Server unicast address 246 static struct in6_addr server_addr = IN6ADDR_ANY_INIT; 247 248 // Initial state of the DHCPv6 service 249 static enum dhcpv6_state dhcpv6_state = DHCPV6_INIT; 250 static int dhcpv6_state_timeout = 0; 251 252 // Authentication options 253 static enum odhcp6c_auth_protocol auth_protocol = AUTH_PROT_RKAP; 254 static uint8_t reconf_key[16]; 255 static uint64_t reconf_replay; 256 static bool reconf_replay_seen; 257 258 // client options 259 static unsigned int client_options = 0; 260 261 // counters for statistics 262 static struct dhcpv6_stats dhcpv6_stats = {0}; 263 264 // config 265 static struct config_dhcp* config_dhcp = NULL; 266 267 // store unique ifname hash to use as IA->IAID 268 static uint32_t ifname_hash_iaid = 0; 269 270 static uint32_t ntohl_unaligned(const uint8_t *data) 271 { 272 uint32_t buf; 273 274 memcpy(&buf, data, sizeof(buf)); 275 return ntohl(buf); 276 } 277 278 static void dhcpv6_next_state(void) 279 { 280 dhcpv6_state++; 281 dhcpv6_reset_state_timeout(); 282 } 283 284 static void dhcpv6_prev_state(void) 285 { 286 dhcpv6_state--; 287 dhcpv6_reset_state_timeout(); 288 } 289 290 static void dhcpv6_inc_counter(enum dhcpv6_msg type) 291 { 292 switch (type) { 293 case DHCPV6_MSG_SOLICIT: 294 dhcpv6_stats.solicit++; 295 break; 296 297 case DHCPV6_MSG_ADVERT: 298 dhcpv6_stats.advertise++; 299 break; 300 301 case DHCPV6_MSG_REQUEST: 302 dhcpv6_stats.request++; 303 break; 304 305 case DHCPV6_MSG_RENEW: 306 dhcpv6_stats.renew++; 307 break; 308 309 case DHCPV6_MSG_REBIND: 310 dhcpv6_stats.rebind++; 311 break; 312 313 case DHCPV6_MSG_REPLY: 314 dhcpv6_stats.reply++; 315 break; 316 317 case DHCPV6_MSG_RELEASE: 318 dhcpv6_stats.release++; 319 break; 320 321 case DHCPV6_MSG_DECLINE: 322 dhcpv6_stats.decline++; 323 break; 324 325 case DHCPV6_MSG_RECONF: 326 dhcpv6_stats.reconfigure++; 327 break; 328 329 case DHCPV6_MSG_INFO_REQ: 330 dhcpv6_stats.information_request++; 331 break; 332 333 default: 334 break; 335 } 336 } 337 338 static char *dhcpv6_msg_to_str(enum dhcpv6_msg msg) 339 { 340 switch (msg) { 341 case DHCPV6_MSG_SOLICIT: 342 return "SOLICIT"; 343 344 case DHCPV6_MSG_ADVERT: 345 return "ADVERTISE"; 346 347 case DHCPV6_MSG_REQUEST: 348 return "REQUEST"; 349 350 case DHCPV6_MSG_RENEW: 351 return "RENEW"; 352 353 case DHCPV6_MSG_REBIND: 354 return "REBIND"; 355 356 case DHCPV6_MSG_REPLY: 357 return "REPLY"; 358 359 case DHCPV6_MSG_RELEASE: 360 return "RELEASE"; 361 362 case DHCPV6_MSG_DECLINE: 363 return "DECLINE"; 364 365 case DHCPV6_MSG_RECONF: 366 return "RECONFIGURE"; 367 368 case DHCPV6_MSG_INFO_REQ: 369 return "INFORMATION REQUEST"; 370 371 default: 372 break; 373 } 374 375 return "UNKNOWN"; 376 } 377 378 static char *dhcpv6_status_code_to_str(uint16_t code) 379 { 380 switch (code) { 381 case DHCPV6_Success: 382 return "Success"; 383 384 case DHCPV6_UnspecFail: 385 return "Unspecified Failure"; 386 387 case DHCPV6_NoAddrsAvail: 388 return "No Address Available"; 389 390 case DHCPV6_NoBinding: 391 return "No Binding"; 392 393 case DHCPV6_NotOnLink: 394 return "Not On Link"; 395 396 case DHCPV6_UseMulticast: 397 return "Use Multicast"; 398 399 case DHCPV6_NoPrefixAvail: 400 return "No Prefix Available"; 401 402 default: 403 break; 404 } 405 406 return "Unknown"; 407 } 408 409 const char *dhcpv6_state_to_str(enum dhcpv6_state state) 410 { 411 switch (state) { 412 case DHCPV6_INIT: 413 return "INIT"; 414 415 case DHCPV6_SOLICIT: 416 return "SOLICIT"; 417 418 case DHCPV6_SOLICIT_PROCESSING: 419 return "SOLICIT_PROCESSING"; 420 421 case DHCPV6_ADVERT: 422 return "ADVERT"; 423 424 case DHCPV6_REQUEST: 425 return "REQUEST"; 426 427 case DHCPV6_REQUEST_PROCESSING: 428 return "REQUEST_PROCESSING"; 429 430 case DHCPV6_REPLY: 431 return "REPLY"; 432 433 case DHCPV6_BOUND: 434 return "BOUND"; 435 436 case DHCPV6_BOUND_PROCESSING: 437 return "BOUND_PROCESSING"; 438 439 case DHCPV6_BOUND_REPLY: 440 return "BOUND_REPLY"; 441 442 case DHCPV6_RECONF: 443 return "RECONF"; 444 445 case DHCPV6_RECONF_PROCESSING: 446 return "RECONF_PROCESSING"; 447 448 case DHCPV6_RECONF_REPLY: 449 return "RECONF_REPLY"; 450 451 case DHCPV6_RENEW: 452 return "RENEW"; 453 454 case DHCPV6_RENEW_PROCESSING: 455 return "RENEW_PROCESSING"; 456 457 case DHCPV6_RENEW_REPLY: 458 return "RENEW_REPLY"; 459 460 case DHCPV6_REBIND: 461 return "REBIND"; 462 463 case DHCPV6_REBIND_PROCESSING: 464 return "REBIND_PROCESSING"; 465 466 case DHCPV6_REBIND_REPLY: 467 return "REBIND_REPLY"; 468 469 case DHCPV6_INFO: 470 return "INFO"; 471 472 case DHCPV6_INFO_PROCESSING: 473 return "INFO_PROCESSING"; 474 475 case DHCPV6_INFO_REPLY: 476 return "INFO_REPLY"; 477 478 case DHCPV6_EXIT: 479 return "EXIT"; 480 481 default: 482 return "INVALID_STATE"; 483 } 484 } 485 486 static int fd_set_nonblocking(int sockfd) 487 { 488 int flags = fcntl(sockfd, F_GETFL, 0); 489 if (flags == -1) { 490 error( 491 "Failed to get the dhcpv6 socket flags: fcntl F_GETFL failed (%s)", 492 strerror(errno)); 493 return -1; 494 } 495 496 // Set the socket to non-blocking 497 if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) { 498 error( 499 "Failed to set the dhcpv6 socket to non-blocking: fcntl F_SETFL failed (%s)", 500 strerror(errno)); 501 return -1; 502 } 503 504 return 0; 505 } 506 507 int dhcpv6_get_socket(void) 508 { 509 return sock; 510 } 511 512 enum dhcpv6_state dhcpv6_get_state(void) 513 { 514 return dhcpv6_state; 515 } 516 517 void dhcpv6_set_state(enum dhcpv6_state state) 518 { 519 dhcpv6_state = state; 520 dhcpv6_reset_state_timeout(); 521 } 522 523 int dhcpv6_get_state_timeout(void) 524 { 525 return dhcpv6_state_timeout; 526 } 527 528 void dhcpv6_set_state_timeout(int timeout) 529 { 530 if (timeout > 0 && (dhcpv6_state_timeout == 0 || timeout < dhcpv6_state_timeout)) { 531 dhcpv6_state_timeout = timeout; 532 } 533 } 534 535 void dhcpv6_reset_state_timeout(void) 536 { 537 dhcpv6_state_timeout = 0; 538 } 539 540 struct dhcpv6_stats dhcpv6_get_stats(void) 541 { 542 return dhcpv6_stats; 543 } 544 545 void dhcpv6_reset_stats(void) 546 { 547 memset(&dhcpv6_stats, 0, sizeof(dhcpv6_stats)); 548 } 549 550 static uint32_t dhcpv6_generate_iface_iaid(const char *ifname) { 551 uint8_t hash[16] = {0}; 552 uint32_t iaid; 553 md5_ctx_t md5; 554 555 md5_begin(&md5); 556 md5_hash(ifname, strlen(ifname), &md5); 557 md5_end(hash, &md5); 558 559 iaid = (uint32_t)hash[0] << 24; 560 iaid |= (uint32_t)hash[1] << 16; 561 iaid |= (uint32_t)hash[2] << 8; 562 iaid |= (uint32_t)hash[3]; 563 564 return iaid; 565 } 566 567 int init_dhcpv6(const char *ifname) 568 { 569 config_dhcp = config_dhcp_get(); 570 571 memcpy(dhcpv6_retx, dhcpv6_retx_default, sizeof(dhcpv6_retx)); 572 config_apply_dhcp_rtx(dhcpv6_retx); 573 574 client_options = config_dhcp->client_options; 575 na_mode = config_dhcp->ia_na_mode; 576 pd_mode = config_dhcp->ia_pd_mode; 577 stateful_only_mode = config_dhcp->stateful_only_mode; 578 auth_protocol = config_dhcp->auth_protocol; 579 580 sock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); 581 if (sock < 0) 582 goto failure; 583 584 // Detect interface 585 struct ifreq ifr; 586 memset(&ifr, 0, sizeof(ifr)); 587 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); 588 if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) 589 goto failure; 590 591 ifname_hash_iaid = dhcpv6_generate_iface_iaid(ifname); 592 593 ifindex = ifr.ifr_ifindex; 594 595 // Set the socket to non-blocking mode 596 if (fd_set_nonblocking(sock) < 0) 597 goto failure; 598 599 // Build our FQDN 600 size_t fqdn_len; 601 odhcp6c_get_state(STATE_OUR_FQDN, &fqdn_len); 602 if(fqdn_len == 0) { 603 char fqdn_buf[256]; 604 gethostname(fqdn_buf, sizeof(fqdn_buf) - 1); 605 fqdn_buf[sizeof(fqdn_buf) - 1] = '\0'; 606 struct { 607 uint16_t type; 608 uint16_t len; 609 uint8_t flags; 610 uint8_t data[256]; 611 } fqdn = {0}; 612 int dn_result = dn_comp(fqdn_buf, fqdn.data, 613 sizeof(fqdn.data), NULL, NULL); 614 fqdn_len = 0; 615 if (dn_result > 0) { 616 fqdn.type = htons(DHCPV6_OPT_FQDN); 617 fqdn.len = htons(1 + dn_result); 618 fqdn.flags = 0; 619 fqdn_len = DHCPV6_OPT_HDR_SIZE + 1 + dn_result; 620 } 621 odhcp6c_add_state(STATE_OUR_FQDN, &fqdn, fqdn_len); 622 } 623 624 // Create client DUID 625 size_t client_id_len; 626 odhcp6c_get_state(STATE_CLIENT_ID, &client_id_len); 627 if (client_id_len == 0) { 628 uint8_t duid[14] = {0, DHCPV6_OPT_CLIENTID, 0, 10, 0, 629 DHCPV6_DUID_LLADDR, 0, 1}; 630 631 if (ioctl(sock, SIOCGIFHWADDR, &ifr) >= 0) 632 memcpy(&duid[8], ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); 633 634 uint8_t zero[ETHER_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; 635 struct ifreq ifs[100], *ifp, *ifend; 636 struct ifconf ifc; 637 ifc.ifc_req = ifs; 638 ifc.ifc_len = sizeof(ifs); 639 640 if (!memcmp(&duid[8], zero, ETHER_ADDR_LEN) && 641 ioctl(sock, SIOCGIFCONF, &ifc) >= 0) { 642 // If our interface doesn't have an address... 643 ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq)); 644 for (ifp = ifc.ifc_req; ifp < ifend && 645 !memcmp(&duid[8], zero, ETHER_ADDR_LEN); ifp++) { 646 memcpy(ifr.ifr_name, ifp->ifr_name, 647 sizeof(ifr.ifr_name)); 648 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) 649 continue; 650 651 memcpy(&duid[8], ifr.ifr_hwaddr.sa_data, 652 ETHER_ADDR_LEN); 653 } 654 } 655 656 odhcp6c_add_state(STATE_CLIENT_ID, duid, sizeof(duid)); 657 } 658 659 // Create ORO 660 if (!(client_options & DHCPV6_STRICT_OPTIONS)) { 661 uint16_t oro[] = { 662 htons(DHCPV6_OPT_SIP_SERVER_D), 663 htons(DHCPV6_OPT_SIP_SERVER_A), 664 htons(DHCPV6_OPT_DNS_SERVERS), 665 htons(DHCPV6_OPT_DNS_DOMAIN), 666 htons(DHCPV6_OPT_SNTP_SERVERS), 667 htons(DHCPV6_OPT_NTP_SERVER), 668 htons(DHCPV6_OPT_PD_EXCLUDE), 669 /* RFC8910: Clients that support this option SHOULD include it */ 670 htons(DHCPV6_OPT_CAPTIVE_PORTAL), 671 }; 672 odhcp6c_add_state(STATE_ORO, oro, sizeof(oro)); 673 } 674 // Required ORO 675 uint16_t req_oro[] = { 676 htons(DHCPV6_OPT_INF_MAX_RT), 677 htons(DHCPV6_OPT_SOL_MAX_RT), 678 htons(DHCPV6_OPT_INFO_REFRESH), 679 }; 680 odhcp6c_add_state(STATE_ORO, req_oro, sizeof(req_oro)); 681 682 // Configure IPv6-options 683 int val = 1; 684 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)) < 0) 685 goto failure; 686 687 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) 688 goto failure; 689 690 if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)) < 0) 691 goto failure; 692 693 if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) 694 goto failure; 695 696 if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &(config_dhcp->sk_prio), sizeof(config_dhcp->sk_prio)) < 0) 697 goto failure; 698 699 val = config_dhcp->dscp << 2; 700 if (setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0) { 701 goto failure; 702 } 703 704 struct sockaddr_in6 client_addr = { .sin6_family = AF_INET6, 705 .sin6_port = htons(DHCPV6_CLIENT_PORT), .sin6_flowinfo = 0 }; 706 707 if (bind(sock, (struct sockaddr*)&client_addr, sizeof(client_addr)) < 0) 708 goto failure; 709 710 return 0; 711 712 failure: 713 if (sock >= 0) 714 close(sock); 715 716 return -1; 717 } 718 719 enum { 720 IOV_HDR=0, 721 IOV_ORO, 722 IOV_CL_ID, 723 IOV_SRV_ID, 724 IOV_OPTS, 725 IOV_RECONF_ACCEPT, 726 IOV_FQDN, 727 IOV_HDR_IA_NA, 728 IOV_IA_NA, 729 IOV_IA_PD, 730 IOV_TOTAL 731 }; 732 733 int dhcpv6_get_ia_mode(void) 734 { 735 int mode = DHCPV6_UNKNOWN; 736 737 if (na_mode == IA_MODE_NONE && pd_mode == IA_MODE_NONE) 738 mode = DHCPV6_STATELESS; 739 else if (na_mode == IA_MODE_FORCE || pd_mode == IA_MODE_FORCE) 740 mode = DHCPV6_STATEFUL; 741 742 return mode; 743 } 744 745 static void dhcpv6_send(enum dhcpv6_msg req_msg_type, uint8_t trid[3], uint32_t ecs) 746 { 747 // Build FQDN 748 size_t fqdn_len; 749 void *fqdn = odhcp6c_get_state(STATE_OUR_FQDN, &fqdn_len); 750 751 // Build Client ID 752 size_t cl_id_len; 753 void *cl_id = odhcp6c_get_state(STATE_CLIENT_ID, &cl_id_len); 754 755 // Get Server ID 756 size_t srv_id_len; 757 void *srv_id = odhcp6c_get_state(STATE_SERVER_ID, &srv_id_len); 758 759 // Build IA_PDs 760 size_t ia_pd_entry_cnt = 0, ia_pd_len = 0; 761 uint8_t *ia_pd; 762 struct odhcp6c_entry *pd_entries = odhcp6c_get_state(STATE_IA_PD, &ia_pd_entry_cnt); 763 ia_pd_entry_cnt /= sizeof(*pd_entries); 764 765 if (req_msg_type == DHCPV6_MSG_SOLICIT || (req_msg_type == DHCPV6_MSG_REQUEST && ia_pd_entry_cnt == 0 && pd_mode != IA_MODE_NONE)) { 766 odhcp6c_clear_state(STATE_IA_PD); 767 size_t n_prefixes; 768 struct odhcp6c_request_prefix *request_prefixes = odhcp6c_get_state(STATE_IA_PD_INIT, &n_prefixes); 769 n_prefixes /= sizeof(struct odhcp6c_request_prefix); 770 771 ia_pd = alloca(n_prefixes * (sizeof(struct dhcpv6_ia_hdr) + sizeof(struct dhcpv6_ia_prefix))); 772 773 for (size_t i = 0; i < n_prefixes; i++) { 774 struct dhcpv6_ia_hdr hdr_ia_pd = { 775 htons(DHCPV6_OPT_IA_PD), 776 htons(sizeof(hdr_ia_pd) - DHCPV6_OPT_HDR_SIZE + 777 sizeof(struct dhcpv6_ia_prefix) * !!request_prefixes[i].length), 778 request_prefixes[i].iaid, 0, 0 779 }; 780 struct dhcpv6_ia_prefix pref = { 781 .type = htons(DHCPV6_OPT_IA_PREFIX), 782 .len = htons(sizeof(pref) - DHCPV6_OPT_HDR_SIZE), 783 .prefix = request_prefixes[i].length, 784 .addr = request_prefixes[i].addr 785 }; 786 memcpy(ia_pd + ia_pd_len, &hdr_ia_pd, sizeof(hdr_ia_pd)); 787 ia_pd_len += sizeof(hdr_ia_pd); 788 if (request_prefixes[i].length) { 789 memcpy(ia_pd + ia_pd_len, &pref, sizeof(pref)); 790 ia_pd_len += sizeof(pref); 791 } 792 } 793 } else { 794 // we're too lazy to count our distinct IAIDs, 795 // so just allocate maximally needed space 796 ia_pd = alloca(ia_pd_entry_cnt * (sizeof(struct dhcpv6_ia_prefix) + 10 + 797 sizeof(struct dhcpv6_ia_hdr))); 798 799 for (size_t i = 0; i < ia_pd_entry_cnt; ++i) { 800 uint32_t iaid = pd_entries[i].iaid; 801 802 // check if this is an unprocessed IAID and skip if not. 803 bool new_iaid = true; 804 for (int j = i-1; j >= 0; j--) { 805 if (pd_entries[j].iaid == iaid) { 806 new_iaid = false; 807 break; 808 } 809 } 810 811 if (!new_iaid) 812 continue; 813 814 // construct header 815 struct dhcpv6_ia_hdr hdr_ia_pd = { 816 htons(DHCPV6_OPT_IA_PD), 817 htons(sizeof(hdr_ia_pd) - DHCPV6_OPT_HDR_SIZE), 818 iaid, 0, 0 819 }; 820 821 memcpy(ia_pd + ia_pd_len, &hdr_ia_pd, sizeof(hdr_ia_pd)); 822 struct dhcpv6_ia_hdr *hdr = (struct dhcpv6_ia_hdr *) (ia_pd + ia_pd_len); 823 ia_pd_len += sizeof(hdr_ia_pd); 824 825 for (size_t j = i; j < ia_pd_entry_cnt; j++) { 826 if (pd_entries[j].iaid != iaid) 827 continue; 828 829 uint8_t excl_subnet_id_nbits, excl_subnet_id_nbytes, excl_opt_len = 0; 830 if (pd_entries[j].exclusion_length > 0) { 831 excl_subnet_id_nbits = pd_entries[j].exclusion_length - pd_entries[j].length; 832 excl_subnet_id_nbytes = ((excl_subnet_id_nbits - 1) / 8) + 1; 833 excl_opt_len = excl_subnet_id_nbytes + DHCPV6_OPT_HDR_SIZE + 1; 834 } 835 struct dhcpv6_ia_prefix p = { 836 .type = htons(DHCPV6_OPT_IA_PREFIX), 837 .len = htons(sizeof(p) - DHCPV6_OPT_HDR_SIZE_U + excl_opt_len), 838 .prefix = pd_entries[j].length, 839 .addr = pd_entries[j].target 840 }; 841 842 if (req_msg_type == DHCPV6_MSG_REQUEST) { 843 p.preferred = htonl(pd_entries[j].preferred); 844 p.valid = htonl(pd_entries[j].valid); 845 } 846 847 memcpy(ia_pd + ia_pd_len, &p, sizeof(p)); 848 ia_pd_len += sizeof(p); 849 850 if (excl_opt_len) { 851 ia_pd[ia_pd_len++] = 0; 852 ia_pd[ia_pd_len++] = DHCPV6_OPT_PD_EXCLUDE; 853 ia_pd[ia_pd_len++] = 0; 854 ia_pd[ia_pd_len++] = excl_opt_len - DHCPV6_OPT_HDR_SIZE; 855 ia_pd[ia_pd_len++] = pd_entries[j].exclusion_length; 856 857 uint32_t excluded_bits = ntohl(pd_entries[j].router.s6_addr32[1]); 858 excluded_bits >>= (64 - pd_entries[j].exclusion_length); /* Right align subnet ID bits */ 859 excluded_bits <<= (32 - excl_subnet_id_nbits); /* Left align subnet ID bits */ 860 861 /* Copy subnet ID bits into the option MSB first */ 862 for (size_t k = 0; k < excl_subnet_id_nbytes; ++k) { 863 ia_pd[ia_pd_len++] = excluded_bits >> 24; 864 excluded_bits <<= 8; 865 } 866 } 867 868 hdr->len = htons(ntohs(hdr->len) + ntohs(p.len) + 4U); 869 } 870 } 871 } 872 873 // Build IA_NAs 874 size_t ia_na_entry_cnt, ia_na_len = 0; 875 void *ia_na = NULL; 876 struct odhcp6c_entry *ia_entries = odhcp6c_get_state(STATE_IA_NA, &ia_na_entry_cnt); 877 ia_na_entry_cnt /= sizeof(*ia_entries); 878 879 struct dhcpv6_ia_hdr hdr_ia_na = { 880 .type = htons(DHCPV6_OPT_IA_NA), 881 .len = htons(sizeof(hdr_ia_na) - DHCPV6_OPT_HDR_SIZE), 882 .iaid = htonl(ifname_hash_iaid), 883 .t1 = 0, 884 .t2 = 0, 885 }; 886 887 struct dhcpv6_ia_addr ia_na_array[ia_na_entry_cnt]; 888 for (size_t i = 0; i < ia_na_entry_cnt; ++i) { 889 ia_na_array[i].type = htons(DHCPV6_OPT_IA_ADDR); 890 ia_na_array[i].len = htons(sizeof(ia_na_array[i]) - DHCPV6_OPT_HDR_SIZE_U); 891 ia_na_array[i].addr = ia_entries[i].target; 892 893 if (req_msg_type == DHCPV6_MSG_REQUEST) { 894 ia_na_array[i].preferred = htonl(ia_entries[i].preferred); 895 ia_na_array[i].valid = htonl(ia_entries[i].valid); 896 } else { 897 ia_na_array[i].preferred = 0; 898 ia_na_array[i].valid = 0; 899 } 900 } 901 902 ia_na = ia_na_array; 903 ia_na_len = sizeof(ia_na_array); 904 hdr_ia_na.len = htons(ntohs(hdr_ia_na.len) + ia_na_len); 905 906 // Reconfigure Accept 907 struct { 908 uint16_t type; 909 uint16_t length; 910 } reconf_accept = {htons(DHCPV6_OPT_RECONF_ACCEPT), 0}; 911 912 // Option list 913 size_t opts_len; 914 void *opts = odhcp6c_get_state(STATE_OPTS, &opts_len); 915 916 // Option Request List 917 size_t oro_entries, oro_len = 0; 918 uint16_t *oro, *s_oro = odhcp6c_get_state(STATE_ORO, &oro_entries); 919 920 oro_entries /= sizeof(*s_oro); 921 oro = alloca(oro_entries * sizeof(*oro)); 922 923 for (size_t i = 0; i < oro_entries; i++) { 924 struct odhcp6c_opt *opt = odhcp6c_find_opt(htons(s_oro[i])); 925 926 if (opt) { 927 if (!(opt->flags & OPT_ORO)) 928 continue; 929 930 if ((opt->flags & OPT_ORO_SOLICIT) && req_msg_type != DHCPV6_MSG_SOLICIT) 931 continue; 932 933 if ((opt->flags & OPT_ORO_STATELESS) && req_msg_type != DHCPV6_MSG_INFO_REQ) 934 continue; 935 936 if ((opt->flags & OPT_ORO_STATEFUL) && req_msg_type == DHCPV6_MSG_INFO_REQ) 937 continue; 938 } 939 940 oro[oro_len++] = s_oro[i]; 941 } 942 oro_len *= sizeof(*oro); 943 944 // Prepare Header 945 struct { 946 uint8_t type; 947 uint8_t trid[3]; 948 uint16_t elapsed_type; 949 uint16_t elapsed_len; 950 uint16_t elapsed_value; 951 uint16_t oro_type; 952 uint16_t oro_len; 953 } hdr = { 954 req_msg_type, {trid[0], trid[1], trid[2]}, 955 htons(DHCPV6_OPT_ELAPSED), htons(2), 956 htons((ecs > 0xffff) ? 0xffff : ecs), 957 htons(DHCPV6_OPT_ORO), htons(oro_len), 958 }; 959 960 struct iovec iov[IOV_TOTAL] = { 961 [IOV_HDR] = {&hdr, sizeof(hdr)}, 962 [IOV_ORO] = {oro, oro_len}, 963 [IOV_CL_ID] = {cl_id, cl_id_len}, 964 [IOV_SRV_ID] = {srv_id, srv_id_len}, 965 [IOV_OPTS] = { opts, opts_len }, 966 [IOV_RECONF_ACCEPT] = {&reconf_accept, sizeof(reconf_accept)}, 967 [IOV_FQDN] = {fqdn, fqdn_len}, 968 [IOV_HDR_IA_NA] = {&hdr_ia_na, sizeof(hdr_ia_na)}, 969 [IOV_IA_NA] = {ia_na, ia_na_len}, 970 [IOV_IA_PD] = {ia_pd, ia_pd_len}, 971 }; 972 973 size_t cnt = IOV_TOTAL; 974 if (req_msg_type == DHCPV6_MSG_INFO_REQ) 975 cnt = IOV_HDR_IA_NA; 976 977 // Disable IAs if not used 978 if (na_mode == IA_MODE_NONE) { 979 iov[IOV_HDR_IA_NA].iov_len = 0; 980 } else if (ia_na_len == 0) { 981 /* RFC7550 §4.2 982 * Solution: a client SHOULD accept Advertise messages, even 983 * when not all IA option types are being offered. And, in 984 * this case, the client SHOULD include the not offered IA 985 * option types in its Request. A client SHOULD only ignore 986 * an Advertise message when none of the requested IA 987 * options include offered addresses or delegated prefixes. 988 * Note that ignored messages MUST still be processed for 989 * SOL_MAX_RT and INF_MAX_RT options as specified in 990 * [RFC7083]. 991 */ 992 993 switch (req_msg_type) { 994 case DHCPV6_MSG_REQUEST: 995 if (!config_dhcp->strict_rfc7550) { 996 /* Some broken ISPs won't behave properly if IA_NA is 997 * sent on Requests when they have provided an empty 998 * IA_NA on Advertise. 999 * Therefore we don't comply with RFC7550 and omit 1000 * IA_NA as a workaround. 1001 */ 1002 iov[IOV_HDR_IA_NA].iov_len = 0; 1003 } 1004 break; 1005 case DHCPV6_MSG_SOLICIT: 1006 break; 1007 default: 1008 iov[IOV_HDR_IA_NA].iov_len = 0; 1009 break; 1010 } 1011 } 1012 1013 if ((req_msg_type != DHCPV6_MSG_SOLICIT && req_msg_type != DHCPV6_MSG_REQUEST) || 1014 !(client_options & DHCPV6_ACCEPT_RECONFIGURE)) 1015 iov[IOV_RECONF_ACCEPT].iov_len = 0; 1016 1017 if (!(client_options & DHCPV6_CLIENT_FQDN)) { 1018 iov[IOV_FQDN].iov_len = 0; 1019 } else { 1020 switch (req_msg_type) { 1021 /* RFC4704 §5 1022 A client MUST only include the Client FQDN option in SOLICIT, 1023 REQUEST, RENEW, or REBIND messages. 1024 */ 1025 case DHCPV6_MSG_SOLICIT: 1026 case DHCPV6_MSG_REQUEST: 1027 case DHCPV6_MSG_RENEW: 1028 case DHCPV6_MSG_REBIND: 1029 /* RFC4704 §6 1030 Servers MUST only include a Client FQDN option in ADVERTISE and REPLY 1031 messages... 1032 case DHCPV6_MSG_ADVERT: 1033 case DHCPV6_MSG_REPLY: 1034 */ 1035 /* leave FQDN as-is */ 1036 break; 1037 default: 1038 /* remaining MSG types cannot contain client FQDN */ 1039 iov[IOV_FQDN].iov_len = 0; 1040 break; 1041 } 1042 } 1043 1044 struct sockaddr_in6 srv = {AF_INET6, htons(DHCPV6_SERVER_PORT), 1045 0, ALL_DHCPV6_RELAYS, ifindex}; 1046 struct msghdr msg = {.msg_name = &srv, .msg_namelen = sizeof(srv), 1047 .msg_iov = iov, .msg_iovlen = cnt}; 1048 1049 switch (req_msg_type) { 1050 case DHCPV6_MSG_REQUEST: 1051 case DHCPV6_MSG_RENEW: 1052 case DHCPV6_MSG_RELEASE: 1053 case DHCPV6_MSG_DECLINE: 1054 if (!IN6_IS_ADDR_UNSPECIFIED(&server_addr) && 1055 odhcp6c_addr_in_scope(&server_addr)) { 1056 srv.sin6_addr = server_addr; 1057 if (!IN6_IS_ADDR_LINKLOCAL(&server_addr)) 1058 srv.sin6_scope_id = 0; 1059 } 1060 break; 1061 default: 1062 break; 1063 } 1064 1065 if (sendmsg(sock, &msg, 0) < 0) { 1066 char in6_str[INET6_ADDRSTRLEN]; 1067 1068 error("Failed to send %s message to %s (%s)", 1069 dhcpv6_msg_to_str(req_msg_type), 1070 inet_ntop(AF_INET6, (const void *)&srv.sin6_addr, 1071 in6_str, sizeof(in6_str)), strerror(errno)); 1072 dhcpv6_stats.transmit_failures++; 1073 } else { 1074 dhcpv6_inc_counter(req_msg_type); 1075 } 1076 } 1077 1078 static int64_t dhcpv6_rand_delay(int64_t time) 1079 { 1080 int random; 1081 odhcp6c_random(&random, sizeof(random)); 1082 1083 return (time * ((int64_t)random % (config_dhcp->rand_factor*10LL))) / 10000LL; 1084 } 1085 1086 // Message validation checks according to RFC3315 chapter 15 1087 static bool dhcpv6_response_is_valid(const void *buf, ssize_t len, 1088 const uint8_t transaction[3], enum dhcpv6_msg req_msg_type, 1089 const struct in6_addr *daddr) 1090 { 1091 const struct dhcpv6_header *response_buf = buf; 1092 if (len < (ssize_t)sizeof(*response_buf) || memcmp(response_buf->tr_id, 1093 transaction, sizeof(response_buf->tr_id))) 1094 return false; // Invalid reply 1095 1096 if (req_msg_type == DHCPV6_MSG_SOLICIT) { 1097 if (response_buf->msg_type != DHCPV6_MSG_ADVERT && 1098 response_buf->msg_type != DHCPV6_MSG_REPLY) 1099 return false; 1100 } else if (req_msg_type == DHCPV6_MSG_UNKNOWN) { 1101 if (!accept_reconfig || response_buf->msg_type != DHCPV6_MSG_RECONF) 1102 return false; 1103 } else if (response_buf->msg_type != DHCPV6_MSG_REPLY) { 1104 return false; 1105 } 1106 1107 uint8_t *end = ((uint8_t*)buf) + len, *odata = NULL, 1108 rcmsg = DHCPV6_MSG_UNKNOWN; 1109 uint16_t otype, olen = UINT16_MAX; 1110 bool clientid_ok = false, serverid_ok = false, rcauth_ok = false, 1111 auth_present = false, ia_present = false, options_valid = true; 1112 1113 size_t client_id_len, server_id_len; 1114 void *client_id = odhcp6c_get_state(STATE_CLIENT_ID, &client_id_len); 1115 void *server_id = odhcp6c_get_state(STATE_SERVER_ID, &server_id_len); 1116 1117 dhcpv6_for_each_option(&response_buf[1], end, otype, olen, odata) { 1118 switch (otype) { 1119 case DHCPV6_OPT_CLIENTID: 1120 clientid_ok = (olen + DHCPV6_OPT_HDR_SIZE_U == client_id_len) && !memcmp( 1121 &odata[-DHCPV6_OPT_HDR_SIZE], client_id, client_id_len); 1122 break; 1123 1124 case DHCPV6_OPT_SERVERID: 1125 if (server_id_len) 1126 serverid_ok = (olen + DHCPV6_OPT_HDR_SIZE_U == server_id_len) && !memcmp( 1127 &odata[-DHCPV6_OPT_HDR_SIZE], server_id, server_id_len); 1128 else if (req_msg_type != DHCPV6_MSG_UNKNOWN) 1129 serverid_ok = true; 1130 break; 1131 1132 case DHCPV6_OPT_AUTH: 1133 struct dhcpv6_auth *r = (void*)&odata[-DHCPV6_OPT_HDR_SIZE]; 1134 if (auth_present) { 1135 options_valid = false; 1136 continue; 1137 } 1138 1139 auth_present = true; 1140 if (auth_protocol == AUTH_PROT_RKAP) { 1141 struct dhcpv6_auth_reconfigure *rkap = (void*)r->data; 1142 if (olen != 28 || r->protocol != AUTH_PROT_RKAP || r->algorithm != AUTH_ALG_HMACMD5 || rkap->reconf_type != RKAP_TYPE_HMACMD5) 1143 continue; 1144 1145 /* RFC 8415 §20.4.3: the replay-detection field must be 1146 * monotonically increasing per (client, server-id) pair. 1147 * Drop any Reconfigure whose replay value does not exceed 1148 * the highest one we have already accepted. */ 1149 uint64_t replay; 1150 memcpy(&replay, &r->replay, sizeof(replay)); 1151 replay = be64toh(replay); 1152 if (reconf_replay_seen && replay <= reconf_replay) 1153 continue; 1154 1155 md5_ctx_t md5; 1156 uint8_t serverhash[16], secretbytes[64]; 1157 uint32_t hash[4]; 1158 memcpy(serverhash, rkap->key, sizeof(serverhash)); 1159 memset(rkap->key, 0, sizeof(rkap->key)); 1160 1161 memset(secretbytes, 0, sizeof(secretbytes)); 1162 memcpy(secretbytes, reconf_key, sizeof(reconf_key)); 1163 1164 for (size_t i = 0; i < sizeof(secretbytes); ++i) 1165 secretbytes[i] ^= 0x36; 1166 1167 md5_begin(&md5); 1168 md5_hash(secretbytes, sizeof(secretbytes), &md5); 1169 md5_hash(buf, len, &md5); 1170 md5_end(hash, &md5); 1171 1172 for (size_t i = 0; i < sizeof(secretbytes); ++i) { 1173 secretbytes[i] ^= 0x36; 1174 secretbytes[i] ^= 0x5c; 1175 } 1176 1177 md5_begin(&md5); 1178 md5_hash(secretbytes, sizeof(secretbytes), &md5); 1179 md5_hash(hash, 16, &md5); 1180 md5_end(hash, &md5); 1181 1182 rcauth_ok = !memcmp(hash, serverhash, sizeof(hash)); 1183 if (rcauth_ok) { 1184 reconf_replay = replay; 1185 reconf_replay_seen = true; 1186 } 1187 } else if (auth_protocol == AUTH_PROT_TOKEN) { 1188 if (olen < 12 || r->protocol != AUTH_PROT_TOKEN || r->algorithm != AUTH_ALG_TOKEN) 1189 continue; 1190 1191 uint16_t token_len = olen - 11; 1192 if (config_dhcp->auth_token == NULL || strlen(config_dhcp->auth_token) != token_len) 1193 continue; 1194 1195 rcauth_ok = !memcmp(r->data, config_dhcp->auth_token, token_len); 1196 } 1197 break; 1198 case DHCPV6_OPT_RECONF_MESSAGE: 1199 if (olen != 1) 1200 return false; 1201 rcmsg = odata[0]; 1202 break; 1203 1204 case DHCPV6_OPT_IA_PD: 1205 case DHCPV6_OPT_IA_NA: 1206 ia_present = true; 1207 if (olen < sizeof(struct dhcpv6_ia_hdr) - DHCPV6_OPT_HDR_SIZE) 1208 options_valid = false; 1209 break; 1210 1211 case DHCPV6_OPT_IA_ADDR: 1212 case DHCPV6_OPT_IA_PREFIX: 1213 case DHCPV6_OPT_PD_EXCLUDE: 1214 // Options are not allowed on global level 1215 options_valid = false; 1216 break; 1217 1218 default: 1219 break; 1220 } 1221 } 1222 1223 if (!options_valid || ((odata + olen) > end)) 1224 return false; 1225 1226 if (req_msg_type == DHCPV6_MSG_INFO_REQ && ia_present) 1227 return false; 1228 1229 if (response_buf->msg_type == DHCPV6_MSG_RECONF) { 1230 if ((rcmsg != DHCPV6_MSG_RENEW && rcmsg != DHCPV6_MSG_REBIND && rcmsg != DHCPV6_MSG_INFO_REQ) || 1231 (rcmsg == DHCPV6_MSG_INFO_REQ && ia_present) || 1232 !rcauth_ok || IN6_IS_ADDR_MULTICAST(daddr)) 1233 return false; 1234 } 1235 1236 return clientid_ok && serverid_ok; 1237 } 1238 1239 static int dhcpv6_handle_reconfigure(enum dhcpv6_msg orig, const int rc, 1240 const void *opt, const void *end, _o_unused const struct sockaddr_in6 *from) 1241 { 1242 uint16_t otype, olen; 1243 uint8_t *odata; 1244 enum dhcpv6_msg msg = DHCPV6_MSG_UNKNOWN; 1245 bool reconf_msg_seen = false; 1246 1247 dhcpv6_for_each_option(opt, end, otype, olen, odata) { 1248 if (otype != DHCPV6_OPT_RECONF_MESSAGE) 1249 continue; 1250 1251 /* RFC 8415 §21.19: the Reconfigure Message option MUST appear 1252 * exactly once. Drop the message if it appears more than once 1253 * or carries an unexpected length. */ 1254 if (reconf_msg_seen || olen != 1) 1255 return -1; 1256 1257 reconf_msg_seen = true; 1258 1259 switch (odata[0]) { 1260 case DHCPV6_MSG_REBIND: 1261 case DHCPV6_MSG_RENEW: 1262 case DHCPV6_MSG_INFO_REQ: 1263 msg = odata[0]; 1264 notice("Need to respond with %s in reply to %s", 1265 dhcpv6_msg_to_str(msg), dhcpv6_msg_to_str(DHCPV6_MSG_RECONF)); 1266 break; 1267 1268 default: 1269 return -1; 1270 } 1271 } 1272 1273 if (msg == DHCPV6_MSG_REBIND && t2 != UINT32_MAX) 1274 t2 = 0; 1275 if ((msg == DHCPV6_MSG_REBIND || msg == DHCPV6_MSG_RENEW) && t1 != UINT32_MAX) 1276 t1 = 0; 1277 1278 if (msg != DHCPV6_MSG_UNKNOWN) 1279 dhcpv6_handle_reply(orig, rc, NULL, NULL, NULL); 1280 1281 return (msg == DHCPV6_MSG_UNKNOWN? -1: (int)msg); 1282 } 1283 1284 // Collect all advertised servers 1285 static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc, 1286 const void *opt, const void *end, _o_unused const struct sockaddr_in6 *from) 1287 { 1288 uint16_t olen, otype; 1289 uint8_t *odata, pref = 0; 1290 struct dhcpv6_server_cand cand = {false, false, 0, 0, {0}, 1291 IN6ADDR_ANY_INIT, DHCPV6_SOL_MAX_RT, 1292 DHCPV6_INF_MAX_RT, NULL, NULL, 0, 0}; 1293 bool have_na = false; 1294 int have_pd = 0; 1295 1296 dhcpv6_for_each_option(opt, end, otype, olen, odata) { 1297 if (orig == DHCPV6_MSG_SOLICIT && 1298 ((otype == DHCPV6_OPT_IA_PD && pd_mode != IA_MODE_NONE) || 1299 (otype == DHCPV6_OPT_IA_NA && na_mode != IA_MODE_NONE)) && 1300 olen > sizeof(struct dhcpv6_ia_hdr) - DHCPV6_OPT_HDR_SIZE) { 1301 struct dhcpv6_ia_hdr *ia_hdr = (void*)(&odata[-DHCPV6_OPT_HDR_SIZE]); 1302 dhcpv6_parse_ia(ia_hdr, odata + olen, NULL); 1303 } 1304 1305 switch (otype) { 1306 case DHCPV6_OPT_SERVERID: 1307 if (olen <= DHCPV6_DUID_MAX_LEN) { 1308 memcpy(cand.duid, odata, olen); 1309 cand.duid_len = olen; 1310 } 1311 break; 1312 1313 case DHCPV6_OPT_PREF: 1314 if (olen >= 1 && cand.preference >= 0) 1315 cand.preference = pref = odata[0]; 1316 break; 1317 1318 case DHCPV6_OPT_UNICAST: 1319 if (olen == sizeof(cand.server_addr) && 1320 !(client_options & DHCPV6_IGNORE_OPT_UNICAST)) 1321 cand.server_addr = *(struct in6_addr *)odata; 1322 break; 1323 1324 case DHCPV6_OPT_RECONF_ACCEPT: 1325 cand.wants_reconfigure = true; 1326 break; 1327 1328 case DHCPV6_OPT_SOL_MAX_RT: 1329 if (olen == 4) { 1330 uint32_t sol_max_rt = ntohl_unaligned(odata); 1331 if (sol_max_rt >= DHCPV6_SOL_MAX_RT_MIN && 1332 sol_max_rt <= DHCPV6_SOL_MAX_RT_MAX) 1333 cand.sol_max_rt = sol_max_rt; 1334 } 1335 break; 1336 1337 case DHCPV6_OPT_INF_MAX_RT: 1338 if (olen == 4) { 1339 uint32_t inf_max_rt = ntohl_unaligned(odata); 1340 if (inf_max_rt >= DHCPV6_INF_MAX_RT_MIN && 1341 inf_max_rt <= DHCPV6_INF_MAX_RT_MAX) 1342 cand.inf_max_rt = inf_max_rt; 1343 } 1344 break; 1345 1346 case DHCPV6_OPT_IA_PD: 1347 if (olen >= sizeof(struct dhcpv6_ia_hdr) - DHCPV6_OPT_HDR_SIZE) { 1348 struct dhcpv6_ia_hdr *h = (struct dhcpv6_ia_hdr *)&odata[-DHCPV6_OPT_HDR_SIZE]; 1349 uint8_t *oend = odata + olen, *d; 1350 1351 dhcpv6_for_each_option(&h[1], oend, otype, olen, d) { 1352 if (otype == DHCPV6_OPT_IA_PREFIX && 1353 olen >= sizeof(struct dhcpv6_ia_prefix) - DHCPV6_OPT_HDR_SIZE) { 1354 struct dhcpv6_ia_prefix *p = 1355 (struct dhcpv6_ia_prefix *)&d[-DHCPV6_OPT_HDR_SIZE]; 1356 have_pd = p->prefix; 1357 } 1358 } 1359 } 1360 break; 1361 1362 case DHCPV6_OPT_IA_NA: 1363 if (olen >= sizeof(struct dhcpv6_ia_hdr) - DHCPV6_OPT_HDR_SIZE) { 1364 struct dhcpv6_ia_hdr *h = (struct dhcpv6_ia_hdr *)&odata[-DHCPV6_OPT_HDR_SIZE]; 1365 uint8_t *oend = odata + olen, *d; 1366 1367 dhcpv6_for_each_option(&h[1], oend, otype, olen, d) { 1368 if (otype == DHCPV6_OPT_IA_ADDR && 1369 olen >= sizeof(struct dhcpv6_ia_addr) - DHCPV6_OPT_HDR_SIZE) 1370 have_na = true; 1371 } 1372 } 1373 break; 1374 1375 default: 1376 break; 1377 } 1378 } 1379 1380 if ((stateful_only_mode && !have_na && !have_pd) || 1381 (!have_na && na_mode == IA_MODE_FORCE) || 1382 (!have_pd && pd_mode == IA_MODE_FORCE)) { 1383 /* 1384 * RFC7083 states to process the SOL_MAX_RT and 1385 * INF_MAX_RT options even if the DHCPv6 server 1386 * did not propose any IA_NA and/or IA_PD 1387 */ 1388 dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = cand.sol_max_rt; 1389 dhcpv6_retx[DHCPV6_MSG_INFO_REQ].max_timeo = cand.inf_max_rt; 1390 return -1; 1391 } 1392 1393 if (na_mode != IA_MODE_NONE && !have_na) { 1394 cand.has_noaddravail = true; 1395 cand.preference -= 1000; 1396 } 1397 1398 if (pd_mode != IA_MODE_NONE) { 1399 if (have_pd) 1400 cand.preference += 2000 + (128 - have_pd); 1401 else 1402 cand.preference -= 2000; 1403 } 1404 1405 if (cand.duid_len > 0) { 1406 cand.ia_na = odhcp6c_move_state(STATE_IA_NA, &cand.ia_na_len); 1407 cand.ia_pd = odhcp6c_move_state(STATE_IA_PD, &cand.ia_pd_len); 1408 dhcpv6_add_server_cand(&cand); 1409 } 1410 1411 return (rc > 1 || (pref == 255 && cand.preference > 0)) ? 1 : -1; 1412 } 1413 1414 static int dhcpv6_commit_advert(void) 1415 { 1416 return dhcpv6_promote_server_cand(); 1417 } 1418 1419 static int dhcpv6_handle_rebind_reply(enum dhcpv6_msg orig, const int rc, 1420 const void *opt, const void *end, const struct sockaddr_in6 *from) 1421 { 1422 dhcpv6_handle_advert(orig, rc, opt, end, from); 1423 if (dhcpv6_commit_advert() < 0) 1424 return -1; 1425 1426 return dhcpv6_handle_reply(orig, rc, opt, end, from); 1427 } 1428 1429 static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _o_unused const int rc, 1430 const void *opt, const void *end, const struct sockaddr_in6 *from) 1431 { 1432 uint8_t *odata; 1433 uint16_t otype, olen; 1434 uint32_t refresh = config_dhcp->irt_default; 1435 int ret = 1; 1436 unsigned int state_IAs; 1437 unsigned int updated_IAs = 0; 1438 bool handled_status_codes[_DHCPV6_Status_Max] = { false, }; 1439 1440 odhcp6c_expire(true); 1441 1442 if (orig == DHCPV6_MSG_UNKNOWN) { 1443 static time_t last_update = 0; 1444 time_t now = odhcp6c_get_milli_time() / 1000; 1445 1446 uint32_t elapsed = (last_update > 0) ? now - last_update : 0; 1447 last_update = now; 1448 1449 if (t1 != UINT32_MAX) 1450 t1 -= elapsed; 1451 1452 if (t2 != UINT32_MAX) 1453 t2 -= elapsed; 1454 1455 if (t3 != UINT32_MAX) 1456 t3 -= elapsed; 1457 1458 if (t1 < 0) 1459 t1 = 0; 1460 1461 if (t2 < 0) 1462 t2 = 0; 1463 1464 if (t3 < 0) 1465 t3 = 0; 1466 } 1467 1468 if (orig == DHCPV6_MSG_REQUEST && !odhcp6c_is_bound()) { 1469 // Delete NA and PD we have in the state from the Advert 1470 odhcp6c_clear_state(STATE_IA_NA); 1471 odhcp6c_clear_state(STATE_IA_PD); 1472 } 1473 1474 if (opt) { 1475 odhcp6c_clear_state(STATE_DNS); 1476 odhcp6c_clear_state(STATE_SEARCH); 1477 odhcp6c_clear_state(STATE_SNTP_IP); 1478 odhcp6c_clear_state(STATE_NTP_IP); 1479 odhcp6c_clear_state(STATE_NTP_FQDN); 1480 odhcp6c_clear_state(STATE_SIP_IP); 1481 odhcp6c_clear_state(STATE_SIP_FQDN); 1482 odhcp6c_clear_state(STATE_AFTR_NAME); 1483 odhcp6c_clear_state(STATE_S46_MAPT); 1484 odhcp6c_clear_state(STATE_S46_MAPE); 1485 odhcp6c_clear_state(STATE_S46_LW); 1486 odhcp6c_clear_state(STATE_CAPT_PORT_DHCPV6); 1487 odhcp6c_clear_state(STATE_PASSTHRU); 1488 odhcp6c_clear_state(STATE_CUSTOM_OPTS); 1489 1490 // Parse and find all matching IAs 1491 dhcpv6_for_each_option(opt, end, otype, olen, odata) { 1492 struct odhcp6c_opt *dopt = odhcp6c_find_opt(otype); 1493 1494 switch (otype) { 1495 1496 case DHCPV6_OPT_IA_NA: 1497 case DHCPV6_OPT_IA_PD: 1498 if (olen > sizeof(struct dhcpv6_ia_hdr) - DHCPV6_OPT_HDR_SIZE) { 1499 struct dhcpv6_ia_hdr *ia_hdr = (void*)(&odata[-DHCPV6_OPT_HDR_SIZE]); 1500 1501 if ((na_mode == IA_MODE_NONE && otype == DHCPV6_OPT_IA_NA) || 1502 (pd_mode == IA_MODE_NONE && otype == DHCPV6_OPT_IA_PD)) 1503 continue; 1504 1505 // Test ID 1506 if (ia_hdr->iaid != htonl(ifname_hash_iaid) && otype == DHCPV6_OPT_IA_NA) 1507 continue; 1508 1509 uint16_t code = DHCPV6_Success; 1510 uint16_t stype, slen; 1511 uint8_t *sdata; 1512 bool dhcpv6_successful_once = false; 1513 // Get and handle status code 1514 dhcpv6_for_each_option(&ia_hdr[1], odata + olen, stype, slen, sdata) { 1515 if (stype == DHCPV6_OPT_STATUS && slen >= 2) { 1516 uint8_t *mdata = (slen > 2) ? &sdata[2] : NULL; 1517 uint16_t mlen = (slen > 2) ? slen - 2 : 0; 1518 1519 code = ((int)sdata[0] << 8) | ((int)sdata[1]); 1520 1521 if (code == DHCPV6_Success) { 1522 dhcpv6_successful_once = true; 1523 continue; 1524 } 1525 1526 dhcpv6_handle_ia_status_code(orig, ia_hdr, 1527 code, mdata, mlen, handled_status_codes, &ret); 1528 1529 break; 1530 } 1531 } 1532 1533 if (!dhcpv6_successful_once && code != DHCPV6_Success) 1534 continue; 1535 1536 updated_IAs += dhcpv6_parse_ia(ia_hdr, odata + olen, &ret); 1537 } 1538 break; 1539 1540 case DHCPV6_OPT_UNICAST: 1541 if (olen == sizeof(server_addr) && 1542 !(client_options & DHCPV6_IGNORE_OPT_UNICAST)) 1543 server_addr = *(struct in6_addr *)odata; 1544 break; 1545 1546 case DHCPV6_OPT_STATUS: 1547 if (olen >= 2) { 1548 uint8_t *mdata = (olen > 2) ? &odata[2] : NULL; 1549 uint16_t mlen = (olen > 2) ? olen - 2 : 0; 1550 uint16_t code = ((int)odata[0] << 8) | ((int)odata[1]); 1551 1552 dhcpv6_handle_status_code(orig, code, mdata, mlen, &ret); 1553 } 1554 break; 1555 1556 case DHCPV6_OPT_DNS_SERVERS: 1557 if (olen % sizeof(struct in6_addr) == 0) 1558 odhcp6c_add_state(STATE_DNS, odata, olen); 1559 break; 1560 1561 case DHCPV6_OPT_DNS_DOMAIN: 1562 odhcp6c_add_state(STATE_SEARCH, odata, olen); 1563 break; 1564 1565 case DHCPV6_OPT_SNTP_SERVERS: 1566 if (olen % sizeof(struct in6_addr) == 0) 1567 odhcp6c_add_state(STATE_SNTP_IP, odata, olen); 1568 break; 1569 1570 case DHCPV6_OPT_NTP_SERVER: 1571 uint16_t stype, slen; 1572 uint8_t *sdata; 1573 // Test status and bail if error 1574 dhcpv6_for_each_option(odata, odata + olen, 1575 stype, slen, sdata) { 1576 if (slen == sizeof(struct in6_addr) && (stype == NTP_MC_ADDR || stype == NTP_SRV_ADDR)) 1577 odhcp6c_add_state(STATE_NTP_IP, sdata, slen); 1578 else if (slen > 0 && stype == NTP_SRV_FQDN) 1579 odhcp6c_add_state(STATE_NTP_FQDN, sdata, slen); 1580 } 1581 break; 1582 1583 case DHCPV6_OPT_SIP_SERVER_A: 1584 if (olen == sizeof(struct in6_addr)) 1585 odhcp6c_add_state(STATE_SIP_IP, odata, olen); 1586 break; 1587 1588 case DHCPV6_OPT_SIP_SERVER_D: 1589 odhcp6c_add_state(STATE_SIP_FQDN, odata, olen); 1590 break; 1591 1592 case DHCPV6_OPT_INFO_REFRESH: 1593 if (olen == 4) 1594 refresh = ntohl_unaligned(odata); 1595 break; 1596 1597 case DHCPV6_OPT_AUTH: 1598 struct dhcpv6_auth *r = (void*)&odata[-DHCPV6_OPT_HDR_SIZE]; 1599 if (auth_protocol == AUTH_PROT_RKAP && olen == 28) { 1600 struct dhcpv6_auth_reconfigure *rkap = (void*)r->data; 1601 if (r->protocol == AUTH_PROT_RKAP && r->algorithm == AUTH_ALG_HMACMD5 && 1602 rkap->reconf_type == RKAP_TYPE_KEY) 1603 memcpy(reconf_key, rkap->key, sizeof(rkap->key)); 1604 } 1605 break; 1606 1607 case DHCPV6_OPT_AFTR_NAME: 1608 if (olen > 3) { 1609 size_t cur_len; 1610 odhcp6c_get_state(STATE_AFTR_NAME, &cur_len); 1611 if (cur_len == 0) 1612 odhcp6c_add_state(STATE_AFTR_NAME, odata, olen); 1613 } 1614 break; 1615 1616 case DHCPV6_OPT_SOL_MAX_RT: 1617 if (olen == 4) { 1618 uint32_t sol_max_rt = ntohl_unaligned(odata); 1619 if (sol_max_rt >= DHCPV6_SOL_MAX_RT_MIN && sol_max_rt <= DHCPV6_SOL_MAX_RT_MAX) 1620 dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = sol_max_rt; 1621 } 1622 break; 1623 1624 case DHCPV6_OPT_INF_MAX_RT: 1625 if (olen == 4) { 1626 uint32_t inf_max_rt = ntohl_unaligned(odata); 1627 if (inf_max_rt >= DHCPV6_INF_MAX_RT_MIN && inf_max_rt <= DHCPV6_INF_MAX_RT_MAX) 1628 dhcpv6_retx[DHCPV6_MSG_INFO_REQ].max_timeo = inf_max_rt; 1629 } 1630 break; 1631 1632 case DHCPV6_OPT_S46_CONT_MAPT: 1633 odhcp6c_add_state(STATE_S46_MAPT, odata, olen); 1634 break; 1635 1636 case DHCPV6_OPT_S46_CONT_MAPE: 1637 size_t mape_len; 1638 odhcp6c_get_state(STATE_S46_MAPE, &mape_len); 1639 if (mape_len == 0) 1640 odhcp6c_add_state(STATE_S46_MAPE, odata, olen); 1641 break; 1642 1643 case DHCPV6_OPT_S46_CONT_LW: 1644 odhcp6c_add_state(STATE_S46_LW, odata, olen); 1645 break; 1646 1647 case DHCPV6_OPT_CAPTIVE_PORTAL: /* RFC8910 §2.2 */ 1648 size_t ref_len = sizeof(URN_IETF_CAPT_PORT_UNRESTR) - 1; 1649 /* RFC8910 §2: 1650 * Networks with no captive portals may explicitly indicate this 1651 * condition by using this option with the IANA-assigned URI for 1652 * this purpose. Clients observing the URI value ... may forego 1653 * time-consuming forms of captive portal detection. */ 1654 if (olen < ref_len || 1655 memcmp(odata, URN_IETF_CAPT_PORT_UNRESTR, ref_len) != 0) 1656 odhcp6c_add_state(STATE_CAPT_PORT_DHCPV6, odata, olen); 1657 break; 1658 1659 default: 1660 odhcp6c_add_state(STATE_CUSTOM_OPTS, &odata[-DHCPV6_OPT_HDR_SIZE], olen + DHCPV6_OPT_HDR_SIZE); 1661 break; 1662 } 1663 1664 // Pass-through unless explicitly disabled, for every option 1665 if (!dopt || !(dopt->flags & OPT_NO_PASSTHRU)) 1666 odhcp6c_add_state(STATE_PASSTHRU, &odata[-DHCPV6_OPT_HDR_SIZE], olen + DHCPV6_OPT_HDR_SIZE); 1667 } 1668 } 1669 1670 // Bail out if fatal status code was received 1671 if (ret <= 0) 1672 return ret; 1673 1674 switch (orig) { 1675 case DHCPV6_MSG_REQUEST: 1676 case DHCPV6_MSG_REBIND: 1677 case DHCPV6_MSG_RENEW: 1678 state_IAs = dhcpv6_calc_refresh_timers(); 1679 // In case there're no state IA entries 1680 // keep sending request/renew/rebind messages 1681 if (state_IAs == 0) { 1682 ret = 0; 1683 break; 1684 } 1685 1686 switch (orig) { 1687 case DHCPV6_MSG_REQUEST: 1688 // All server candidates can be cleared if not yet bound 1689 if (!odhcp6c_is_bound()) 1690 dhcpv6_clear_all_server_cand(); 1691 1692 odhcp6c_clear_state(STATE_SERVER_ADDR); 1693 odhcp6c_add_state(STATE_SERVER_ADDR, &from->sin6_addr, sizeof(struct in6_addr)); 1694 break; 1695 case DHCPV6_MSG_RENEW: 1696 // Send further renews if T1 is not set and if 1697 // there're IAs which were not in the Reply message 1698 if (!t1 && state_IAs != updated_IAs) { 1699 if (updated_IAs) 1700 // Publish updates 1701 notify_state_change("updated", 0, false); 1702 1703 /* 1704 * RFC8415 states following in §18.2.10.1 : 1705 * Sends a Renew/Rebind if any of the IAs are not in the Reply 1706 * message, but as this likely indicates that the server that 1707 * responded does not support that IA type, sending immediately is 1708 * unlikely to produce a different result. Therefore, the client 1709 * MUST rate-limit its transmissions (see Section 14.1) and MAY just 1710 * wait for the normal retransmission time (as if the Reply message 1711 * had not been received). The client continues to use other 1712 * bindings for which the server did return information 1713 */ 1714 ret = -1; 1715 } 1716 break; 1717 case DHCPV6_MSG_REBIND: 1718 odhcp6c_clear_state(STATE_SERVER_ADDR); 1719 odhcp6c_add_state(STATE_SERVER_ADDR, &from->sin6_addr, sizeof(struct in6_addr)); 1720 1721 // Send further rebinds if T1 and T2 is not set and if 1722 // there're IAs which were not in the Reply message 1723 if (!t1 && !t2 && state_IAs != updated_IAs) { 1724 if (updated_IAs) 1725 // Publish updates 1726 notify_state_change("updated", 0, false); 1727 1728 /* 1729 * RFC8415 states following in §18.2.10.1 : 1730 * Sends a Renew/Rebind if any of the IAs are not in the Reply 1731 * message, but as this likely indicates that the server that 1732 * responded does not support that IA type, sending immediately is 1733 * unlikely to produce a different result. Therefore, the client 1734 * MUST rate-limit its transmissions (see Section 14.1) and MAY just 1735 * wait for the normal retransmission time (as if the Reply message 1736 * had not been received). The client continues to use other 1737 * bindings for which the server did return information 1738 */ 1739 ret = -1; 1740 } 1741 break; 1742 1743 default: 1744 break; 1745 } 1746 break; 1747 1748 case DHCPV6_MSG_INFO_REQ: 1749 // All server candidates can be cleared if not yet bound 1750 if (!odhcp6c_is_bound()) 1751 dhcpv6_clear_all_server_cand(); 1752 1753 odhcp6c_clear_state(STATE_SERVER_ADDR); 1754 odhcp6c_add_state(STATE_SERVER_ADDR, &from->sin6_addr, sizeof(struct in6_addr)); 1755 1756 t1 = (refresh < config_dhcp->irt_min) ? config_dhcp->irt_min : refresh; 1757 break; 1758 1759 default: 1760 break; 1761 } 1762 1763 return ret; 1764 } 1765 1766 static unsigned int dhcpv6_parse_ia(void *opt, void *end, int *ret) 1767 { 1768 struct dhcpv6_ia_hdr *ia_hdr = (struct dhcpv6_ia_hdr *)opt; 1769 unsigned int updated_IAs = 0; 1770 uint32_t t1, t2; 1771 uint16_t otype, olen; 1772 uint8_t *odata; 1773 char buf[INET6_ADDRSTRLEN]; 1774 1775 t1 = ntohl(ia_hdr->t1); 1776 t2 = ntohl(ia_hdr->t2); 1777 1778 /* RFC 8415 §21.4 1779 If a client receives an IA_NA with T1 greater than T2 and both T1 and 1780 T2 are greater than 0, the client discards the IA_NA option and 1781 processes the remainder of the message as though the server had not 1782 included the invalid IA_NA option. */ 1783 if (t1 > t2 && t1 > 0 && t2 > 0) 1784 return 0; 1785 1786 info("%s %04x T1 %d T2 %d", ntohs(ia_hdr->type) == DHCPV6_OPT_IA_PD ? "IA_PD" : "IA_NA", ntohl(ia_hdr->iaid), t1, t2); 1787 1788 // Update address IA 1789 dhcpv6_for_each_option(&ia_hdr[1], end, otype, olen, odata) { 1790 struct odhcp6c_entry entry = { 1791 .router = IN6ADDR_ANY_INIT, 1792 .auxlen = 0, 1793 .length = 0, 1794 .ra_flags = 0, 1795 .exclusion_length = 0, 1796 .target = IN6ADDR_ANY_INIT, 1797 .priority = 0, 1798 .valid = 0, 1799 .preferred = 0, 1800 .t1 = 0, 1801 .t2 = 0, 1802 .iaid = ia_hdr->iaid, 1803 }; 1804 1805 switch (otype) { 1806 case DHCPV6_OPT_IA_PREFIX: { 1807 struct dhcpv6_ia_prefix *prefix = (void*)&odata[-DHCPV6_OPT_HDR_SIZE]; 1808 if (olen + DHCPV6_OPT_HDR_SIZE_U < sizeof(*prefix)) 1809 continue; 1810 1811 entry.valid = ntohl(prefix->valid); 1812 entry.preferred = ntohl(prefix->preferred); 1813 1814 if (entry.preferred > entry.valid) 1815 continue; 1816 1817 /* RFC 8415 §21.21 1818 Recommended values for T1 and T2 are 0.5 and 0.8 times the 1819 shortest preferred lifetime of the prefixes in the IA_PD that the 1820 server is willing to extend. */ 1821 entry.t1 = (t1 ? t1 : (entry.preferred != UINT32_MAX ? 0.5 * entry.preferred : UINT32_MAX)); 1822 entry.t2 = (t2 ? t2 : (entry.preferred != UINT32_MAX ? 0.8 * entry.preferred : UINT32_MAX)); 1823 if (entry.t1 > entry.t2) 1824 entry.t1 = entry.t2; 1825 1826 entry.length = prefix->prefix; 1827 entry.target = prefix->addr; 1828 uint16_t stype, slen; 1829 uint8_t *sdata; 1830 1831 // Parse sub-options for PD-exclude or error status code 1832 bool update_state = true; 1833 dhcpv6_for_each_option(odata + sizeof(*prefix) - DHCPV6_OPT_HDR_SIZE, 1834 odata + olen, stype, slen, sdata) { 1835 if (stype == DHCPV6_OPT_STATUS && slen >= 2) { 1836 /* RFC 8415 §21.22 1837 The status of any operations involving this IA Prefix option is 1838 indicated in a Status Code option (see Section 21.13) in the 1839 IAprefix-options field. */ 1840 uint8_t *status_msg = (slen > 2) ? &sdata[2] : NULL; 1841 uint16_t msg_len = (slen > 2) ? slen - 2 : 0; 1842 uint16_t code = ((int)sdata[0]) << 8 | ((int)sdata[1]); 1843 1844 if (code == DHCPV6_Success) 1845 continue; 1846 1847 dhcpv6_log_status_code(code, "IA_PREFIX", status_msg, msg_len); 1848 if (ret) *ret = 0; // renewal failed 1849 } else if (stype == DHCPV6_OPT_PD_EXCLUDE && slen >= 2) { 1850 /* RFC 6603 §4.2 Prefix Exclude option */ 1851 uint8_t exclude_length = sdata[0]; 1852 uint8_t *excl_subnet_id = &sdata[1]; 1853 if (exclude_length > 64) 1854 exclude_length = 64; 1855 1856 if (entry.length < 32 || exclude_length <= entry.length) { 1857 update_state = false; 1858 continue; 1859 } 1860 1861 uint8_t excl_subnet_id_nbits = exclude_length - entry.length; 1862 uint8_t excl_subnet_id_nbytes = ((excl_subnet_id_nbits - 1) / 8) + 1; 1863 if ((excl_subnet_id + excl_subnet_id_nbytes) > (sdata + slen)) { 1864 update_state = false; 1865 continue; 1866 } 1867 1868 uint32_t excluded_bits = 0; 1869 /* Copy subnet ID bits out of the option MSB first */ 1870 for(size_t i = 0; i < excl_subnet_id_nbytes; i++) 1871 excluded_bits = (excluded_bits << 8) | excl_subnet_id[i]; 1872 excluded_bits >>= (8 * excl_subnet_id_nbytes) - excl_subnet_id_nbits; /* Right align subnet ID bits */ 1873 excluded_bits <<= (64 - exclude_length); /* Shift subnet ID bits into the low-order bits of the prefix */ 1874 1875 // Re-using router field to hold the prefix 1876 entry.router = entry.target; // base prefix 1877 entry.router.s6_addr32[1] |= htonl(excluded_bits); 1878 entry.exclusion_length = exclude_length; 1879 } 1880 } 1881 1882 if (update_state) { 1883 if (odhcp6c_update_entry(STATE_IA_PD, &entry, 0)) 1884 updated_IAs++; 1885 1886 info("%s/%d preferred %d valid %d", 1887 inet_ntop(AF_INET6, &entry.target, buf, sizeof(buf)), 1888 entry.length, entry.preferred , entry.valid); 1889 1890 if (entry.exclusion_length) { 1891 info("PD_EXCLUDE %s/%d", 1892 inet_ntop(AF_INET6, &entry.router, buf, sizeof(buf)), 1893 entry.exclusion_length); 1894 } 1895 } 1896 1897 entry.priority = 0; 1898 memset(&entry.router, 0, sizeof(entry.router)); 1899 break; 1900 } 1901 case DHCPV6_OPT_IA_ADDR: { 1902 struct dhcpv6_ia_addr *addr = (void*)&odata[-DHCPV6_OPT_HDR_SIZE]; 1903 if (olen + DHCPV6_OPT_HDR_SIZE_U < sizeof(*addr)) 1904 continue; 1905 1906 entry.preferred = ntohl(addr->preferred); 1907 entry.valid = ntohl(addr->valid); 1908 1909 if (entry.preferred > entry.valid) 1910 continue; 1911 1912 entry.t1 = (t1 ? t1 : (entry.preferred != UINT32_MAX ? 0.5 * entry.preferred : UINT32_MAX)); 1913 entry.t2 = (t2 ? t2 : (entry.preferred != UINT32_MAX ? 0.8 * entry.preferred : UINT32_MAX)); 1914 if (entry.t1 > entry.t2) 1915 entry.t1 = entry.t2; 1916 1917 entry.length = 128; 1918 entry.target = addr->addr; 1919 uint16_t stype, slen; 1920 uint8_t *sdata; 1921 1922 bool update_state = true; 1923 dhcpv6_for_each_option(odata + sizeof(*addr) - DHCPV6_OPT_HDR_SIZE_U, 1924 odata + olen, stype, slen, sdata) { 1925 if (stype == DHCPV6_OPT_STATUS && slen >= 2) { 1926 /* RFC 8415 §21.6 1927 The status of any operations involving this IA Address is indicated 1928 in a Status Code option in the IAaddr-options field, as specified in 1929 Section 21.13. */ 1930 uint8_t *status_msg = (slen > 2) ? &sdata[2] : NULL; 1931 uint16_t msg_len = (slen > 2) ? slen - 2 : 0; 1932 uint16_t code = ((int)sdata[0]) << 8 | ((int)sdata[1]); 1933 1934 if (code == DHCPV6_Success) 1935 continue; 1936 1937 dhcpv6_log_status_code(code, "IA_ADDR", status_msg, msg_len); 1938 if (ret) *ret = 0; // renewal failed 1939 update_state = false; 1940 } 1941 } 1942 1943 if (update_state) { 1944 if (odhcp6c_update_entry(STATE_IA_NA, &entry, 0)) 1945 updated_IAs++; 1946 1947 info("%s preferred %d valid %d", 1948 inet_ntop(AF_INET6, &entry.target, buf, sizeof(buf)), 1949 entry.preferred , entry.valid); 1950 } 1951 break; 1952 } 1953 default: 1954 break; 1955 } 1956 } 1957 1958 return updated_IAs; 1959 } 1960 1961 static unsigned int dhcpv6_calc_refresh_timers(void) 1962 { 1963 struct odhcp6c_entry *pd_entries; 1964 struct odhcp6c_entry *ia_entries; 1965 size_t ia_na_entry_cnt, ia_pd_entry_cnt, i; 1966 size_t invalid_entries = 0; 1967 int64_t l_t1 = UINT32_MAX, l_t2 = UINT32_MAX, l_t3 = 0; 1968 1969 ia_entries = odhcp6c_get_state(STATE_IA_NA, &ia_na_entry_cnt); 1970 ia_na_entry_cnt /= sizeof(*ia_entries); 1971 1972 for (i = 0; i < ia_na_entry_cnt; i++) { 1973 /* Exclude invalid IA_NA entries */ 1974 if (!ia_entries[i].valid) { 1975 invalid_entries++; 1976 continue; 1977 } 1978 1979 if (ia_entries[i].t1 < l_t1) 1980 l_t1 = ia_entries[i].t1; 1981 1982 if (ia_entries[i].t2 < l_t2) 1983 l_t2 = ia_entries[i].t2; 1984 1985 if (ia_entries[i].valid > l_t3) 1986 l_t3 = ia_entries[i].valid; 1987 } 1988 1989 pd_entries = odhcp6c_get_state(STATE_IA_PD, &ia_pd_entry_cnt); 1990 ia_pd_entry_cnt /= sizeof(*pd_entries); 1991 1992 for (i = 0; i < ia_pd_entry_cnt; i++) { 1993 /* Exclude invalid IA_PD entries */ 1994 if (!pd_entries[i].valid) { 1995 invalid_entries++; 1996 continue; 1997 } 1998 1999 if (pd_entries[i].t1 < l_t1) 2000 l_t1 = pd_entries[i].t1; 2001 2002 if (pd_entries[i].t2 < l_t2) 2003 l_t2 = pd_entries[i].t2; 2004 2005 if (pd_entries[i].valid > l_t3) 2006 l_t3 = pd_entries[i].valid; 2007 } 2008 2009 if (ia_pd_entry_cnt + ia_na_entry_cnt - invalid_entries) { 2010 t1 = l_t1; 2011 t2 = l_t2; 2012 t3 = l_t3; 2013 2014 info("T1 %"PRId64"s, T2 %"PRId64"s, T3 %"PRId64"s", t1, t2, t3); 2015 } 2016 2017 return (unsigned int)(ia_pd_entry_cnt + ia_na_entry_cnt); 2018 } 2019 2020 static void dhcpv6_log_status_code(const uint16_t code, const char *scope, 2021 const void *status_msg, int len) 2022 { 2023 const char *src = status_msg; 2024 char buf[len + 3]; 2025 char *dst = buf; 2026 2027 if (len) { 2028 *dst++ = '('; 2029 while (len--) { 2030 *dst = isprint((unsigned char)*src) ? *src : '?'; 2031 src++; 2032 dst++; 2033 } 2034 *dst++ = ')'; 2035 } 2036 2037 *dst = 0; 2038 2039 warn("Server returned %s status '%s %s'", 2040 scope, dhcpv6_status_code_to_str(code), buf); 2041 } 2042 2043 static void dhcpv6_handle_status_code(const enum dhcpv6_msg orig, 2044 const uint16_t code, const void *status_msg, const int len, 2045 int *ret) 2046 { 2047 dhcpv6_log_status_code(code, "message", status_msg, len); 2048 2049 switch (code) { 2050 case DHCPV6_UnspecFail: 2051 // Generic failure 2052 *ret = 0; 2053 break; 2054 2055 case DHCPV6_UseMulticast: 2056 switch(orig) { 2057 case DHCPV6_MSG_REQUEST: 2058 case DHCPV6_MSG_RENEW: 2059 case DHCPV6_MSG_RELEASE: 2060 case DHCPV6_MSG_DECLINE: 2061 // Message needs to be retransmitted according to RFC3315 chapter 18.1.8 2062 server_addr = in6addr_any; 2063 *ret = 0; 2064 break; 2065 default: 2066 break; 2067 } 2068 break; 2069 2070 case DHCPV6_NoAddrsAvail: 2071 case DHCPV6_NoPrefixAvail: 2072 if (orig == DHCPV6_MSG_REQUEST) 2073 *ret = 0; // Failure 2074 break; 2075 2076 default: 2077 break; 2078 } 2079 } 2080 2081 static void dhcpv6_handle_ia_status_code(const enum dhcpv6_msg orig, 2082 const struct dhcpv6_ia_hdr *ia_hdr, const uint16_t code, 2083 const void *status_msg, const int len, 2084 bool handled_status_codes[_DHCPV6_Status_Max], int *ret) 2085 { 2086 dhcpv6_log_status_code(code, ntohs(ia_hdr->type) == DHCPV6_OPT_IA_NA ? 2087 "IA_NA" : "IA_PD", status_msg, len); 2088 2089 switch (code) { 2090 case DHCPV6_NoBinding: 2091 switch (orig) { 2092 case DHCPV6_MSG_RENEW: 2093 case DHCPV6_MSG_REBIND: 2094 if ((*ret > 0) && !handled_status_codes[code]) { 2095 dhcpv6_set_state(DHCPV6_REQUEST); 2096 *ret = -1; 2097 } 2098 break; 2099 2100 default: 2101 *ret = 0; 2102 break; 2103 } 2104 break; 2105 2106 case DHCPV6_NoAddrsAvail: 2107 case DHCPV6_NoPrefixAvail: 2108 break; 2109 2110 default: 2111 *ret = 0; 2112 break; 2113 } 2114 } 2115 2116 // Note this always takes ownership of cand->ia_na and cand->ia_pd 2117 static void dhcpv6_add_server_cand(const struct dhcpv6_server_cand *cand) 2118 { 2119 size_t cand_len, i; 2120 struct dhcpv6_server_cand *srv_candidates = odhcp6c_get_state(STATE_SERVER_CAND, &cand_len); 2121 2122 // Remove identical DUID server candidate 2123 for (i = 0; i < cand_len / sizeof(*srv_candidates); ++i) { 2124 if (cand->duid_len == srv_candidates[i].duid_len && 2125 !memcmp(cand->duid, srv_candidates[i].duid, cand->duid_len)) { 2126 free(srv_candidates[i].ia_na); 2127 free(srv_candidates[i].ia_pd); 2128 odhcp6c_remove_state(STATE_SERVER_CAND, i * sizeof(*srv_candidates), sizeof(*srv_candidates)); 2129 break; 2130 } 2131 } 2132 2133 for (i = 0, srv_candidates = odhcp6c_get_state(STATE_SERVER_CAND, &cand_len); 2134 i < cand_len / sizeof(*srv_candidates); ++i) { 2135 if (srv_candidates[i].preference < cand->preference) 2136 break; 2137 } 2138 2139 if (odhcp6c_insert_state(STATE_SERVER_CAND, i * sizeof(*srv_candidates), cand, sizeof(*cand))) { 2140 free(cand->ia_na); 2141 free(cand->ia_pd); 2142 } 2143 } 2144 2145 static void dhcpv6_clear_all_server_cand(void) 2146 { 2147 size_t cand_len, i; 2148 struct dhcpv6_server_cand *srv_candidates = odhcp6c_get_state(STATE_SERVER_CAND, &cand_len); 2149 2150 // Server candidates need deep delete for IA_NA/IA_PD 2151 for (i = 0; i < cand_len / sizeof(*srv_candidates); ++i) { 2152 free(srv_candidates[i].ia_na); 2153 free(srv_candidates[i].ia_pd); 2154 } 2155 odhcp6c_clear_state(STATE_SERVER_CAND); 2156 } 2157 2158 int dhcpv6_promote_server_cand(void) 2159 { 2160 size_t cand_len; 2161 struct dhcpv6_server_cand *cand = odhcp6c_get_state(STATE_SERVER_CAND, &cand_len); 2162 uint16_t hdr[2]; 2163 int ret = DHCPV6_STATELESS; 2164 bool override_ia = false; 2165 2166 // Clear lingering candidate state info 2167 odhcp6c_clear_state(STATE_SERVER_ID); 2168 odhcp6c_clear_state(STATE_IA_NA); 2169 odhcp6c_clear_state(STATE_IA_PD); 2170 2171 if (!cand_len) 2172 return -1; 2173 2174 if (config_dhcp->strict_rfc7550) { 2175 if (!cand->ia_pd_len && cand->has_noaddravail) { 2176 /* Some ISPs provide neither IA_NA nor IA_PD, so we 2177 * should fallback to SLAAC. 2178 */ 2179 2180 if (na_mode == IA_MODE_TRY) { 2181 na_mode = IA_MODE_NONE; 2182 override_ia = true; 2183 } 2184 2185 if (pd_mode == IA_MODE_TRY) { 2186 pd_mode = IA_MODE_NONE; 2187 override_ia = true; 2188 } 2189 } 2190 } else { 2191 if (cand->has_noaddravail && na_mode == IA_MODE_TRY) { 2192 /* Some broken ISPs require a new Solicit message 2193 * without IA_NA if they haven't provided an address 2194 * on the Advertise message. 2195 */ 2196 na_mode = IA_MODE_NONE; 2197 override_ia = true; 2198 } 2199 2200 if (!cand->ia_pd_len && pd_mode == IA_MODE_TRY) { 2201 /* Some broken ISPs require a new Solicit message 2202 * without IA_PD if they haven't provided a prefix 2203 * on the Advertise message. 2204 */ 2205 pd_mode = IA_MODE_NONE; 2206 override_ia = true; 2207 } 2208 } 2209 2210 if (override_ia) { 2211 dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = cand->sol_max_rt; 2212 dhcpv6_retx[DHCPV6_MSG_INFO_REQ].max_timeo = cand->inf_max_rt; 2213 2214 return -1; 2215 } 2216 2217 hdr[0] = htons(DHCPV6_OPT_SERVERID); 2218 hdr[1] = htons(cand->duid_len); 2219 odhcp6c_add_state(STATE_SERVER_ID, hdr, sizeof(hdr)); 2220 odhcp6c_add_state(STATE_SERVER_ID, cand->duid, cand->duid_len); 2221 accept_reconfig = cand->wants_reconfigure; 2222 memset(reconf_key, 0, sizeof(reconf_key)); 2223 reconf_replay = 0; 2224 reconf_replay_seen = false; 2225 2226 if (cand->ia_na_len) { 2227 odhcp6c_add_state(STATE_IA_NA, cand->ia_na, cand->ia_na_len); 2228 free(cand->ia_na); 2229 if (na_mode != IA_MODE_NONE) 2230 ret = DHCPV6_STATEFUL; 2231 } 2232 2233 if (cand->ia_pd_len) { 2234 odhcp6c_add_state(STATE_IA_PD, cand->ia_pd, cand->ia_pd_len); 2235 free(cand->ia_pd); 2236 if (pd_mode != IA_MODE_NONE) 2237 ret = DHCPV6_STATEFUL; 2238 } 2239 2240 dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = cand->sol_max_rt; 2241 dhcpv6_retx[DHCPV6_MSG_INFO_REQ].max_timeo = cand->inf_max_rt; 2242 2243 odhcp6c_remove_state(STATE_SERVER_CAND, 0, sizeof(*cand)); 2244 2245 return ret; 2246 } 2247 2248 int dhcpv6_send_request(enum dhcpv6_msg req_msg_type) 2249 { 2250 struct dhcpv6_retx *retx = &dhcpv6_retx[req_msg_type]; 2251 uint64_t current_milli_time = 0; 2252 2253 if (!retx->is_retransmit) { 2254 // Initial delay handling 2255 if (retx->max_delay) { 2256 if (retx->delay_msec == 0) { 2257 // Initial delay before starting the transaction 2258 retx->delay_msec = (dhcpv6_rand_delay((10000 * retx->max_delay) / 2) + (1000 * retx->max_delay) / 2); 2259 dhcpv6_set_state_timeout(retx->delay_msec); 2260 // Add current time to calculate absolute time 2261 retx->delay_msec += odhcp6c_get_milli_time(); 2262 return 1; 2263 } else { 2264 // Wait until delay expires 2265 current_milli_time = odhcp6c_get_milli_time(); 2266 if (current_milli_time < retx->delay_msec) { 2267 // Still waiting 2268 dhcpv6_set_state_timeout(retx->delay_msec - current_milli_time); 2269 return 1; 2270 } 2271 retx->delay_msec = 0; 2272 } 2273 } 2274 2275 retx->is_retransmit = true; 2276 retx->rc = 0; 2277 retx->timeout = UINT32_MAX; 2278 retx->reply_ret = -1; 2279 2280 if (req_msg_type == DHCPV6_MSG_UNKNOWN) 2281 retx->timeout = t1; 2282 else if (req_msg_type == DHCPV6_MSG_RENEW) 2283 retx->timeout = (t2 > t1) ? t2 - t1 : ((t1 == UINT32_MAX) ? UINT32_MAX : 0); 2284 else if (req_msg_type == DHCPV6_MSG_REBIND) 2285 retx->timeout = (t3 > t2) ? t3 - t2 : ((t2 == UINT32_MAX) ? UINT32_MAX : 0); 2286 2287 if (retx->timeout == 0) 2288 return -1; 2289 2290 notice("Starting %s transaction (timeout %"PRIu64"s, max rc %d)", 2291 retx->name, retx->timeout, retx->max_rc); 2292 2293 // Generate transaction ID 2294 if (req_msg_type != DHCPV6_MSG_UNKNOWN) { 2295 odhcp6c_random(retx->tr_id, sizeof(retx->tr_id)); 2296 } 2297 2298 // Record start time 2299 retx->start = odhcp6c_get_milli_time(); 2300 retx->round_start = retx->start; 2301 // Reset retransmission timeout initial value 2302 retx->rto = 0; 2303 } 2304 2305 if (retx->rto == 0) { 2306 int64_t delay = dhcpv6_rand_delay(retx->init_timeo * 1000); 2307 2308 // First RT MUST be strictly greater than IRT for solicit messages (RFC3313 17.1.2) 2309 while (req_msg_type == DHCPV6_MSG_SOLICIT && delay <= 0) 2310 delay = dhcpv6_rand_delay(retx->init_timeo * 1000); 2311 2312 // First timeout 2313 retx->rto = (retx->init_timeo * 1000 + delay); 2314 } else { 2315 // Exponential back-off with randomization to avoid synchronization 2316 retx->rto = (2 * retx->rto + dhcpv6_rand_delay(retx->rto)); 2317 } 2318 2319 if (retx->max_timeo && (retx->rto >= retx->max_timeo * 1000)) { 2320 // Cap to max timeout if set and exceeded 2321 retx->rto = retx->max_timeo * 1000 + 2322 dhcpv6_rand_delay(retx->max_timeo * 1000); 2323 } 2324 2325 // Calculate end for this round and elapsed time 2326 retx->round_end = retx->round_start + retx->rto; 2327 uint64_t elapsed = retx->round_start - retx->start; 2328 2329 // Don't wait too long if timeout differs from infinite 2330 if ((retx->timeout != UINT32_MAX) && (retx->round_end - retx->start > retx->timeout * 1000)) 2331 retx->round_end = retx->timeout * 1000 + retx->start; 2332 2333 dhcpv6_set_state_timeout(retx->round_end - odhcp6c_get_milli_time()); 2334 2335 // Built and send package 2336 switch (req_msg_type) { 2337 case DHCPV6_MSG_UNKNOWN: 2338 break; 2339 default: 2340 notice("Send %s message (elapsed %"PRIu64"ms, rc %d)", 2341 retx->name, elapsed, retx->rc); 2342 _o_fallthrough; 2343 case DHCPV6_MSG_SOLICIT: 2344 case DHCPV6_MSG_INFO_REQ: 2345 dhcpv6_send(req_msg_type, retx->tr_id, elapsed / 10); 2346 retx->rc++; 2347 } 2348 2349 if (dhcpv6_get_state() != DHCPV6_EXIT) 2350 dhcpv6_next_state(); 2351 2352 return 0; 2353 } 2354 2355 int dhcpv6_receive_response(enum dhcpv6_msg req_msg_type) 2356 { 2357 ssize_t len = -1; 2358 struct dhcpv6_retx *retx = &dhcpv6_retx[req_msg_type]; 2359 2360 uint8_t buf[1536]; 2361 union { 2362 struct cmsghdr hdr; 2363 uint8_t buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 2364 } cmsg_buf; 2365 2366 struct iovec iov = {buf, sizeof(buf)}; 2367 struct sockaddr_in6 addr; 2368 struct msghdr msg = {.msg_name = &addr, .msg_namelen = sizeof(addr), 2369 .msg_iov = &iov, .msg_iovlen = 1, .msg_control = cmsg_buf.buf, 2370 .msg_controllen = sizeof(cmsg_buf)}; 2371 struct in6_pktinfo *pktinfo = NULL; 2372 const struct dhcpv6_header *hdr = (const struct dhcpv6_header *)buf; 2373 2374 // Receive cycle 2375 len = recvmsg(sock, &msg, 0); 2376 if (len < 0) { 2377 error("Error occurred when reading the response of (%s) error(%s)", 2378 retx->name, strerror(errno)); 2379 return -1; 2380 } 2381 2382 for (struct cmsghdr *ch = CMSG_FIRSTHDR(&msg); ch != NULL; 2383 ch = CMSG_NXTHDR(&msg, ch)) { 2384 if (ch->cmsg_level == SOL_IPV6 && 2385 ch->cmsg_type == IPV6_PKTINFO) { 2386 pktinfo = (struct in6_pktinfo *)CMSG_DATA(ch); 2387 break; 2388 } 2389 } 2390 2391 if (pktinfo == NULL) { 2392 dhcpv6_stats.discarded_packets++; 2393 return -1; 2394 } 2395 2396 if (!dhcpv6_response_is_valid(buf, len, retx->tr_id, req_msg_type, 2397 &pktinfo->ipi6_addr)) { 2398 dhcpv6_stats.discarded_packets++; 2399 return -1; 2400 } 2401 2402 dhcpv6_inc_counter(hdr->msg_type); 2403 2404 uint8_t *opt = &buf[4]; 2405 uint8_t *opt_end = opt + len - DHCPV6_OPT_HDR_SIZE; 2406 retx->round_start = odhcp6c_get_milli_time(); 2407 uint64_t elapsed = retx->round_start - retx->start; 2408 2409 notice("Got a valid %s after %"PRIu64"ms", 2410 dhcpv6_msg_to_str(hdr->msg_type), elapsed); 2411 2412 if (retx->handler_reply) { 2413 retx->reply_ret = retx->handler_reply(req_msg_type, retx->rc, opt, opt_end, &addr); 2414 len = retx->reply_ret; 2415 } 2416 2417 // Clamp round end (Round Trip Time) to 1s max wait after receiving a valid response (in milliseconds) 2418 if (len > 0 && retx->round_end - retx->round_start > 1000) 2419 retx->round_end = 1000 + retx->round_start; 2420 2421 return retx->reply_ret; 2422 } 2423 2424 int dhcpv6_state_processing(enum dhcpv6_msg req_msg_type) 2425 { 2426 struct dhcpv6_retx *retx = &dhcpv6_retx[req_msg_type]; 2427 int ret = retx->reply_ret; 2428 retx->round_start = odhcp6c_get_milli_time(); 2429 uint64_t elapsed = retx->round_start - retx->start; 2430 2431 if (retx->round_start >= retx->round_end || ret >=0 ) { 2432 if (retx->handler_finish) 2433 ret = retx->handler_finish(); 2434 2435 if (ret < 0 && ((retx->timeout == UINT32_MAX) || (elapsed / 1000 < retx->timeout)) && 2436 (!retx->max_rc || retx->rc < retx->max_rc)) { 2437 retx->reply_ret = -1; 2438 dhcpv6_prev_state(); 2439 } else { 2440 retx->is_retransmit = false; 2441 dhcpv6_next_state(); 2442 } 2443 } else { 2444 // This sets the response polling timeout (round_end - round_start) in milliseconds 2445 dhcpv6_set_state_timeout(retx->round_end - retx->round_start); 2446 } 2447 2448 return ret; 2449 } 2450
This page was automatically generated by LXR 0.3.1. • OpenWrt