]> git.decadent.org.uk Git - odhcp6c.git/blobdiff - src/dhcpv6.c
Be less picky when erroring out due to strange IA status-codes
[odhcp6c.git] / src / dhcpv6.c
index 30c9fb2678f16ecd384b697a5c0635b919c7c2e3..cb2aa76f7c7ba01de307ca59f991ad2b9baf0bfc 100644 (file)
@@ -464,7 +464,8 @@ static void dhcpv6_send(enum dhcpv6_msg type, uint8_t trid[3], uint32_t ecs)
 
        struct sockaddr_in6 srv = {AF_INET6, htons(DHCPV6_SERVER_PORT),
                0, ALL_DHCPV6_RELAYS, ifindex};
-       struct msghdr msg = {&srv, sizeof(srv), iov, cnt, NULL, 0, 0};
+       struct msghdr msg = {.msg_name = &srv, .msg_namelen = sizeof(srv),
+                       .msg_iov = iov, .msg_iovlen = cnt};
 
        sendmsg(sock, &msg, 0);
 }
@@ -486,8 +487,8 @@ int dhcpv6_request(enum dhcpv6_msg type)
 
        if (retx->delay) {
                struct timespec ts = {0, 0};
-               ts.tv_nsec = dhcpv6_rand_delay(10 * DHCPV6_REQ_DELAY);
-               nanosleep(&ts, NULL);
+               ts.tv_nsec = (dhcpv6_rand_delay((10000 * DHCPV6_REQ_DELAY) / 2) + (1000 * DHCPV6_REQ_DELAY) / 2) * 1000000;
+               while (nanosleep(&ts, &ts) < 0 && errno == EINTR);
        }
 
        if (type == DHCPV6_MSG_UNKNOWN)
@@ -552,8 +553,9 @@ int dhcpv6_request(enum dhcpv6_msg type)
                        uint8_t buf[1536], cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
                        struct iovec iov = {buf, sizeof(buf)};
                        struct sockaddr_in6 addr;
-                       struct msghdr msg = {&addr, sizeof(addr), &iov, 1,
-                                       cmsg_buf, sizeof(cmsg_buf), 0};
+                       struct msghdr msg = {.msg_name = &addr, .msg_namelen = sizeof(addr),
+                                       .msg_iov = &iov, .msg_iovlen = 1, .msg_control = cmsg_buf,
+                                       .msg_controllen = sizeof(cmsg_buf)};
                        struct in6_pktinfo *pktinfo = NULL;
 
 
@@ -693,7 +695,7 @@ static bool dhcpv6_response_is_valid(const void *buf, ssize_t len,
                        rcmsg = odata[0];
                } else if ((otype == DHCPV6_OPT_IA_PD || otype == DHCPV6_OPT_IA_NA)) {
                        ia_present = true;
-                       if (olen < sizeof(struct dhcpv6_ia_hdr))
+                       if (olen < -4 + sizeof(struct dhcpv6_ia_hdr))
                                options_valid = false;
                }
                else if ((otype == DHCPV6_OPT_IA_ADDR) || (otype == DHCPV6_OPT_IA_PREFIX) ||
@@ -761,7 +763,7 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc,
        dhcpv6_for_each_option(opt, end, otype, olen, odata) {
                if (orig == DHCPV6_MSG_SOLICIT &&
                                (otype == DHCPV6_OPT_IA_PD || otype == DHCPV6_OPT_IA_NA) &&
-                               olen > sizeof(struct dhcpv6_ia_hdr)) {
+                               olen > -4 + sizeof(struct dhcpv6_ia_hdr)) {
                        struct dhcpv6_ia_hdr *ia_hdr = (void*)(&odata[-4]);
                        dhcpv6_parse_ia(ia_hdr, odata + olen + sizeof(*ia_hdr));
                }
@@ -800,8 +802,8 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc,
                        struct dhcpv6_ia_hdr *h = (struct dhcpv6_ia_hdr*)&odata[-4];
                        uint8_t *oend = odata + olen, *d;
                        dhcpv6_for_each_option(&h[1], oend, otype, olen, d) {
-                               if (otype == DHCPV6_OPT_IA_PREFIX && (olen + 4) >=
-                                               (uint16_t)sizeof(struct dhcpv6_ia_prefix)) {
+                               if (otype == DHCPV6_OPT_IA_PREFIX &&
+                                               olen >= -4 + sizeof(struct dhcpv6_ia_prefix)) {
                                        struct dhcpv6_ia_prefix *p = (struct dhcpv6_ia_prefix*)&d[-4];
                                        have_pd = p->prefix;
                                }
@@ -810,7 +812,8 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc,
                        struct dhcpv6_ia_hdr *h = (struct dhcpv6_ia_hdr*)&odata[-4];
                        uint8_t *oend = odata + olen, *d;
                        dhcpv6_for_each_option(&h[1], oend, otype, olen, d)
-                               if (otype == DHCPV6_OPT_IA_ADDR)
+                               if (otype == DHCPV6_OPT_IA_ADDR &&
+                                               olen >= -4 + sizeof(struct dhcpv6_ia_addr))
                                        have_na = true;
                }
        }
@@ -930,7 +933,7 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _unused const int rc,
                bool passthru = true;
 
                if ((otype == DHCPV6_OPT_IA_PD || otype == DHCPV6_OPT_IA_NA)
-                               && olen > sizeof(struct dhcpv6_ia_hdr)) {
+                               && olen > -4 + sizeof(struct dhcpv6_ia_hdr)) {
                        struct dhcpv6_ia_hdr *ia_hdr = (void*)(&odata[-4]);
 
                        // Test ID
@@ -1353,23 +1356,8 @@ static void dhcpv6_handle_ia_status_code(const enum dhcpv6_msg orig,
                }
                break;
 
-       case DHCPV6_NoAddrsAvail:
-       case DHCPV6_NoPrefixAvail:
-               switch (orig) {
-               case DHCPV6_MSG_REQUEST:
-                       if (*ret != 0)
-                               *ret = 0;
-                       break;
-               default:
-                       break;
-               }
-               break;
-
-       case DHCPV6_NotOnLink:
-               // TODO handle not onlink in case of confirm
-               break;
-
        default:
+               *ret = 0;
                break;
        }
 }