Mercurial > hg > dhcpcd
changeset 4177:bce060648873 draft
Ensure that xid is unique across all interfaces.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Mon, 06 Nov 2017 12:10:02 +0000 |
| parents | 612d80156afd |
| children | ffc26bed14d2 |
| files | src/dhcp.c src/dhcp6.c |
| diffstat | 2 files changed, 54 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dhcp.c Fri Nov 03 16:38:18 2017 +0000 +++ b/src/dhcp.c Mon Nov 06 12:10:02 2017 +0000 @@ -1518,6 +1518,8 @@ 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 @@ 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
--- a/src/dhcp6.c Fri Nov 03 16:38:18 2017 +0000 +++ b/src/dhcp6.c Mon Nov 06 12:10:02 2017 +0000 @@ -392,6 +392,8 @@ 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 @@ /* 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
