diff options
| author | Roy Marples <roy@marples.name> | 2020-01-15 14:28:24 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2020-01-15 14:28:24 +0000 |
| commit | 4dcd539c2259273ae89a364069378ca7327cd428 (patch) | |
| tree | 8bbadd0bf18d911402270bffeec30288a1635129 /src/if.c | |
| parent | dbf19b104503e4dea1616e03fa472f60d2cdfd4e (diff) | |
| download | dhcpcd-4dcd539c2259273ae89a364069378ca7327cd428.tar.xz | |
Implement Anonymity Profiles for DHCP Clients, RFC 7844
This works by randomising the hardware address when carrier is down
and using this to construct a DUID LL which is used over any saved
DUID. IAID is defaulted to zero and hostname + FQDN are disabled.
Then every possible option is masked out except for essential ones.
It's possible to request options *after* anonymous option which
will enable it. This is RFC compliant and allows 100% flexability
in letting the user decide what, if any, details leek out.
This is disabled by default.
Only works on NetBSD, other OS coming shortly.
Diffstat (limited to 'src/if.c')
| -rw-r--r-- | src/if.c | 47 |
1 files changed, 44 insertions, 3 deletions
@@ -156,7 +156,7 @@ if_getflags(struct interface *ifp) } int -if_setflag(struct interface *ifp, short flag) +if_setflag(struct interface *ifp, short setflag, short unsetflag) { struct ifreq ifr = { .ifr_flags = 0 }; short f; @@ -165,11 +165,12 @@ if_setflag(struct interface *ifp, short flag) return -1; f = (short)ifp->flags; - if ((f & flag) == flag) + if ((f & setflag) == setflag && (f & unsetflag) == 0) return 0; strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); - ifr.ifr_flags = f | flag; + ifr.ifr_flags |= setflag; + ifr.ifr_flags &= (short)~unsetflag; if (if_ioctl(ifp->ctx, SIOCSIFFLAGS, &ifr, sizeof(ifr)) == -1) return -1; @@ -177,6 +178,46 @@ if_setflag(struct interface *ifp, short flag) return 0; } +int +if_randomisemac(struct interface *ifp) +{ + uint32_t randnum; + size_t hwlen = ifp->hwlen, rlen = 0; + uint8_t buf[hwlen], *bp = buf, *rp = (uint8_t *)&randnum; + char sbuf[hwlen * 3]; + int retval; + + if (hwlen == 0) { + errno = ENOTSUP; + return -1; + } + + for (; hwlen != 0; hwlen--) { + if (rlen == 0) { + randnum = arc4random(); + rp = (uint8_t *)&randnum; + rlen = sizeof(randnum); + } + if (bp == buf) { + /* First octet is special. We need to preserve + * bit 8 (unicast/multicast) and set + * bit 7 (locally administered address) */ + *bp = *rp++ & 0xFC; + *bp++ |= 2; + } else + *bp++ = *rp++; + rlen--; + } + + logdebugx("%s: hardware address randomised to %s", + ifp->name, + hwaddr_ntoa(buf, sizeof(buf), sbuf, sizeof(sbuf))); + retval = if_setmac(ifp, buf, ifp->hwlen); + if (retval == 0) + memcpy(ifp->hwaddr, buf, sizeof(ifp->hwaddr)); + return retval; +} + static int if_hasconf(struct dhcpcd_ctx *ctx, const char *ifname) { |
