dhcpv6: respect renew end point when handling reconfigure message
[project/odhcp6c.git] / src / dhcpv6.c
index 71e1cc248a8bc966a34c111b22595b505ec62aec..6dc227fe6f37f77895f21473e4059fbb85bac39d 100644 (file)
@@ -797,20 +797,31 @@ int dhcpv6_poll_reconfigure(void)
        return ret;
 }
 
-static int dhcpv6_handle_reconfigure(_unused enum dhcpv6_msg orig, const int rc,
+static int dhcpv6_handle_reconfigure(enum dhcpv6_msg orig, const int rc,
                const void *opt, const void *end, _unused const struct sockaddr_in6 *from)
 {
        uint16_t otype, olen;
-       uint8_t *odata, msg = DHCPV6_MSG_RENEW;
+       uint8_t *odata;
+       int msg = -1;
 
        dhcpv6_for_each_option(opt, end, otype, olen, odata) {
-               if (otype == DHCPV6_OPT_RECONF_MESSAGE && olen == 1 && (
-                               odata[0] == DHCPV6_MSG_RENEW ||
-                               odata[0] == DHCPV6_MSG_INFO_REQ))
-                       msg = odata[0];
+               if (otype == DHCPV6_OPT_RECONF_MESSAGE && olen == 1) {
+                       switch (odata[0]) {
+                       case DHCPV6_MSG_RENEW:
+                               if (t1 != UINT32_MAX)
+                                       t1 = 0;
+                       // Fall through
+                       case DHCPV6_MSG_INFO_REQ:
+                               msg = odata[0];
+                               break;
+
+                       default:
+                               break;
+                       }
+               }
        }
 
-       dhcpv6_handle_reply(DHCPV6_MSG_UNKNOWN, rc, NULL, NULL, NULL);
+       dhcpv6_handle_reply(orig, rc, NULL, NULL, NULL);
 
        return msg;
 }
@@ -1137,41 +1148,47 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _unused const int rc,
                }
        }
 
-       if (orig != DHCPV6_MSG_INFO_REQ) {
+       switch (orig) {
+       case DHCPV6_MSG_REQUEST:
+       case DHCPV6_MSG_REBIND:
+       case DHCPV6_MSG_RENEW:
                // Update refresh timers if no fatal status code was received
                if ((ret > 0) && (ret = dhcpv6_calc_refresh_timers())) {
-                       switch (orig) {
-                       case DHCPV6_MSG_RENEW:
+                       if (orig == DHCPV6_MSG_REQUEST) {
+                               // All server candidates can be cleared if not yet bound
+                               if (!odhcp6c_is_bound())
+                                       dhcpv6_clear_all_server_cand();
+
+                               odhcp6c_clear_state(STATE_SERVER_ADDR);
+                               odhcp6c_add_state(STATE_SERVER_ADDR, &from->sin6_addr, 16);
+                       } else if (orig == DHCPV6_MSG_RENEW) {
                                // Send further renews if T1 is not set
                                if (!t1)
                                        ret = -1;
-                               break;
-                       case DHCPV6_MSG_REBIND:
+
+                       } else if (orig == DHCPV6_MSG_REBIND) {
                                // Send further rebinds if T1 and T2 is not set
                                if (!t1 && !t2)
                                        ret = -1;
-                               break;
 
-                       case DHCPV6_MSG_REQUEST:
-                               // All server candidates can be cleared if not yet bound
-                               if (!odhcp6c_is_bound())
-                                       dhcpv6_clear_all_server_cand();
-
-                       default :
-                               break;
-                       }
-
-                       if (orig == DHCPV6_MSG_REBIND || orig == DHCPV6_MSG_REQUEST) {
                                odhcp6c_clear_state(STATE_SERVER_ADDR);
                                odhcp6c_add_state(STATE_SERVER_ADDR, &from->sin6_addr, 16);
                        }
                }
-       } else if (ret > 0) {
-               // All server candidates can be cleared if not yet bound
-               if (!odhcp6c_is_bound())
-                       dhcpv6_clear_all_server_cand();
+               break;
+
+       case DHCPV6_MSG_INFO_REQ:
+               if (ret > 0) {
+                       // All server candidates can be cleared if not yet bound
+                       if (!odhcp6c_is_bound())
+                               dhcpv6_clear_all_server_cand();
+
+                       t1 = refresh;
+               }
+               break;
 
-               t1 = refresh;
+       default:
+               break;
        }
 
        return ret;