]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Ensure that xid is unique across all interfaces.
authorRoy Marples <roy@marples.name>
Mon, 6 Nov 2017 12:10:02 +0000 (12:10 +0000)
committerRoy Marples <roy@marples.name>
Mon, 6 Nov 2017 12:10:02 +0000 (12:10 +0000)
src/dhcp.c
src/dhcp6.c

index 55a6d69dbab4aa322415317aaff228b511415e31..2e0341d52263388d307426d258012f1cc994b69b 100644 (file)
@@ -1518,6 +1518,8 @@ static void
 dhcp_new_xid(struct interface *ifp)
 {
        struct dhcp_state *state;
+       const struct interface *ifp1;
+       const struct dhcp_state *state1;
 
        state = D_STATE(ifp);
        if (ifp->options->options & DHCPCD_XID_HWADDR &&
@@ -1526,8 +1528,30 @@ dhcp_new_xid(struct interface *ifp)
                memcpy(&state->xid,
                    (ifp->hwaddr + ifp->hwlen) - sizeof(state->xid),
                    sizeof(state->xid));
-       else
+       else {
+again:
                state->xid = arc4random();
+       }
+
+       /* Ensure it's unique */
+       TAILQ_FOREACH(ifp1, ifp->ctx->ifaces, next) {
+               if (ifp == ifp1)
+                       continue;
+               if ((state1 = D_CSTATE(ifp1)) == NULL)
+                       continue;
+               if (state1->xid == state->xid)
+                       break;
+       }
+       if (ifp1 != NULL) {
+               if (ifp->options->options & DHCPCD_XID_HWADDR &&
+                   ifp->hwlen >= sizeof(state->xid))
+               {
+                       logerrx("%s: duplicate xid on %s",
+                           ifp->name, ifp1->name);
+                           return;
+               }
+               goto again;
+       }
 
        /* We can't do this when sharing leases across interfaes */
 #if 0
index 206d2fa3dd03bd386853809400ea4e1ce85a5ef6..b4805771e1d63b6b1c8e9f391a86ee14aba464d4 100644 (file)
@@ -392,6 +392,8 @@ dhcp6_updateelapsed(struct interface *ifp, struct dhcp6_message *m, size_t len)
 static void
 dhcp6_newxid(const struct interface *ifp, struct dhcp6_message *m)
 {
+       const struct interface *ifp1;
+       const struct dhcp6_state *state1;
        uint32_t xid;
 
        if (ifp->options->options & DHCPCD_XID_HWADDR &&
@@ -399,12 +401,38 @@ dhcp6_newxid(const struct interface *ifp, struct dhcp6_message *m)
                /* The lower bits are probably more unique on the network */
                memcpy(&xid, (ifp->hwaddr + ifp->hwlen) - sizeof(xid),
                    sizeof(xid));
-       else
+       else {
+again:
                xid = arc4random();
+       }
 
        m->xid[0] = (xid >> 16) & 0xff;
        m->xid[1] = (xid >> 8) & 0xff;
        m->xid[2] = xid & 0xff;
+
+       /* Ensure it's unique */
+       TAILQ_FOREACH(ifp1, ifp->ctx->ifaces, next) {
+               if (ifp == ifp1)
+                       continue;
+               if ((state1 = D6_CSTATE(ifp1)) == NULL)
+                       continue;
+               if (state1->send != NULL &&
+                   state1->send->xid[0] == m->xid[0] &&
+                   state1->send->xid[1] == m->xid[1] &&
+                   state1->send->xid[2] == m->xid[2])
+                       break;
+       }
+
+       if (ifp1 != NULL) {
+               if (ifp->options->options & DHCPCD_XID_HWADDR &&
+                   ifp->hwlen >= sizeof(xid))
+               {
+                       logerrx("%s: duplicate xid on %s",
+                           ifp->name, ifp1->name);
+                           return;
+               }
+               goto again;
+       }
 }
 
 #ifndef SMALL