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 &&
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
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 &&
/* 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