]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
DHCP6: Wait for IRT to elapse before requesting advertisments
authorRoy Marples <roy@marples.name>
Fri, 17 May 2024 22:12:26 +0000 (22:12 +0000)
committerRoy Marples <roy@marples.name>
Fri, 17 May 2024 22:12:26 +0000 (22:12 +0000)
RFC 8415 15 and 18.2.1 list this as a MUST.

Fixes #317.

src/dhcp6.c

index e187a37606eefe24b1609d1efcc3ec8faef971de..7cc51f99c788a90656fe2555af80e6a534b2d4f3 100644 (file)
@@ -181,6 +181,7 @@ static void dhcp6_bind(struct interface *, const char *, const char *);
 static void dhcp6_failinform(void *);
 static void dhcp6_recvaddr(void *, unsigned short);
 static void dhcp6_startdecline(struct interface *);
+static void dhcp6_startrequest(struct interface *);
 
 #ifdef SMALL
 #define dhcp6_hasprefixdelegation(a)   (0)
@@ -1427,11 +1428,38 @@ dhcp6_sendinform(void *arg)
        dhcp6_sendmessage(arg, dhcp6_sendinform);
 }
 
+static void
+dhcp6_senddiscover2(void *arg)
+{
+
+       dhcp6_sendmessage(arg, dhcp6_senddiscover2);
+}
+
+static void
+dhcp6_senddiscover1(void *arg)
+{
+       /*
+        * So the initial RT has elapsed.
+        * If we have any ADVERTs we can now REQUEST them.
+        * RFC 8415 15 and 18.2.1
+        */
+       struct interface *ifp = arg;
+       struct dhcp6_state *state = D6_STATE(ifp);
+
+       if (state->recv == NULL || state->recv->type != DHCP6_ADVERTISE)
+               dhcp6_sendmessage(arg, dhcp6_senddiscover2);
+       else
+               dhcp6_startrequest(ifp);
+}
+
 static void
 dhcp6_senddiscover(void *arg)
 {
+       struct interface *ifp = arg;
+       struct dhcp6_state *state = D6_STATE(ifp);
 
-       dhcp6_sendmessage(arg, dhcp6_senddiscover);
+       dhcp6_sendmessage(arg,
+           state->IMD != 0 ? dhcp6_senddiscover : dhcp6_senddiscover1);
 }
 
 static void
@@ -1890,7 +1918,6 @@ dhcp6_startrebind(void *arg)
 #endif
 }
 
-
 static void
 dhcp6_startrequest(struct interface *ifp)
 {
@@ -3461,6 +3488,16 @@ dhcp6_recvif(struct interface *ifp, const char *sfrom,
                        valid_op = false;
                        break;
                }
+               if (state->recv_len && state->recv->type == DHCP6_ADVERTISE) {
+                       /* We already have an advertismemnt.
+                        * RFC 8415 says we have to wait for the IRT to elapse.
+                        * To keep the same behaviour we won't do anything with
+                        * this. In the future we should make a lists of
+                        * ADVERTS and pick the "best" one. */
+                       logdebugx("%s: discarding ADVERTISMENT from %s",
+                           ifp->name, sfrom);
+                       return;
+               }
                /* RFC7083 */
                o = dhcp6_findmoption(r, len, D6_OPTION_SOL_MAX_RT, &ol);
                if (o && ol == sizeof(uint32_t)) {
@@ -3586,7 +3623,7 @@ dhcp6_recvif(struct interface *ifp, const char *sfrom,
                else
                        loginfox("%s: ADV %s from %s",
                            ifp->name, ia->saddr, sfrom);
-               dhcp6_startrequest(ifp);
+               // We will request when the IRT elapses
                return;
        }