summaryrefslogtreecommitdiffstats
path: root/src/if.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-01-15 14:28:24 +0000
committerRoy Marples <roy@marples.name>2020-01-15 14:28:24 +0000
commit68f04fa827830e894559ba42461d86e0d8bd7b47 (patch)
tree8bbadd0bf18d911402270bffeec30288a1635129 /src/if.c
parent727ac8afce72b12d9ace53928b2586f718d88392 (diff)
downloaddhcpcd-68f04fa827830e894559ba42461d86e0d8bd7b47.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.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/src/if.c b/src/if.c
index a96ac5c1..ff1a88bb 100644
--- a/src/if.c
+++ b/src/if.c
@@ -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)
{