• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/odhcp6c/src/dhcpv6.c

  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