]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: Enable ARP BPF filtering for interesting addresses
authorRoy Marples <roy@marples.name>
Tue, 10 Dec 2019 21:00:58 +0000 (21:00 +0000)
committerRoy Marples <roy@marples.name>
Tue, 10 Dec 2019 21:00:58 +0000 (21:00 +0000)
This brings parity with non privsep features.
Aside from the lack of Solaris support, but that's another day.

src/arp.c
src/arp.h
src/bpf.c
src/dhcp.c
src/dhcpcd.c
src/privsep-bpf.c
src/privsep-bpf.h
src/privsep-root.c
src/privsep.c
src/privsep.h

index 3c395035798e29f3c037911cc8dc64d304a32a63..b062704df34cddcacb23e091c9e94b7d696ca7ef 100644 (file)
--- a/src/arp.c
+++ b/src/arp.c
@@ -260,6 +260,8 @@ arp_packet(struct interface *ifp, uint8_t *data, size_t len)
        /* Match the ARP probe to our states.
         * Ignore Unicast Poll, RFC1122. */
        state = ARP_CSTATE(ifp);
+       if (state == NULL)
+               return;
        TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, astaten) {
                if (IN_ARE_ADDR_EQUAL(&arm.sip, &astate->addr) ||
                    (IN_IS_ADDR_UNSPECIFIED(&arm.sip) &&
@@ -275,16 +277,18 @@ arp_close(struct interface *ifp)
        struct dhcpcd_ctx *ctx = ifp->ctx;
        struct iarp_state *state;
 
-       if ((state = ARP_STATE(ifp)) == NULL)
-               return;
-
 #ifdef PRIVSEP
-       if ((ctx->options & (DHCPCD_PRIVSEP|DHCPCD_FORKED)) == DHCPCD_PRIVSEP) {
-               if (ps_bpf_closearp(ifp) == -1)
+       if (IN_PRIVSEP(ctx)) {
+               if (IN_PRIVSEP_SE(ctx) &&
+                   ps_bpf_closearp(ifp) == -1)
                        logerr(__func__);
+               return;
        }
 #endif
 
+       if ((state = ARP_STATE(ifp)) == NULL)
+               return;
+
        if (state->bpf_fd == -1)
                return;
        eloop_event_delete(ctx->eloop, state->bpf_fd);
@@ -307,13 +311,6 @@ arp_tryfree(struct iarp_state *state)
                        free(state);
                        ifp->if_data[IF_DATA_ARP] = NULL;
                }
-#ifdef PRIVSEP
-       } else if (ifp->ctx->options & DHCPCD_PRIVSEP) {
-#if 0
-               if (privsep_arp_bpf(state) == -1)
-                       logerr(__func__);
-#endif
-#endif
        } else if (state->bpf_fd != -1) {
                if (bpf_arp(ifp, state->bpf_fd) == -1)
                        logerr(__func__);
@@ -359,7 +356,7 @@ arp_open(struct interface *ifp)
        struct iarp_state *state;
 
 #ifdef PRIVSEP
-       if (ifp->ctx->options & DHCPCD_PRIVSEP)
+       if (IN_PRIVSEP_SE(ifp->ctx))
                return ps_bpf_openarp(ifp) == -1 ? -1 : 0;
 #endif
 
@@ -412,15 +409,6 @@ void
 arp_probe(struct arp_state *astate)
 {
 
-       if (arp_open(astate->iface) == -1) {
-               logerr(__func__);
-               return;
-       } else {
-               const struct iarp_state *state = ARP_CSTATE(astate->iface);
-
-               if (bpf_arp(astate->iface, state->bpf_fd) == -1)
-                       logerr(__func__);
-       }
        astate->probes = 0;
        logdebugx("%s: probing for %s",
            astate->iface->name, inet_ntoa(astate->addr));
@@ -428,7 +416,7 @@ arp_probe(struct arp_state *astate)
 }
 #endif /* ARP */
 
-static struct arp_state *
+struct arp_state *
 arp_find(struct interface *ifp, const struct in_addr *addr)
 {
        struct iarp_state *state;
@@ -507,7 +495,8 @@ arp_announce(struct arp_state *astate)
        struct arp_state *a2;
        int r;
 
-       if (arp_open(astate->iface) == -1) {
+       if (!(IN_PRIVSEP(astate->iface->ctx)) && arp_open(astate->iface) == -1)
+       {
                logerr(__func__);
                return;
        }
@@ -583,6 +572,38 @@ arp_announceaddr(struct dhcpcd_ctx *ctx, const struct in_addr *ia)
        arp_ifannounceaddr(iff, ia);
 }
 
+void
+arp_change(struct arp_state *astate, const struct in_addr *addr)
+{
+       struct interface *ifp = astate->iface;
+       struct iarp_state *state = ARP_STATE(ifp);
+
+#ifdef PRIVSEP
+       if (!IN_IS_ADDR_UNSPECIFIED(&astate->addr) &&
+           IN_PRIVSEP_SE(ifp->ctx))
+       {
+               if (ps_bpf_deladdr(ifp, &astate->addr) == -1)
+                       logerr(__func__);
+       }
+#endif
+
+       if (addr != NULL)
+               astate->addr = *addr;
+       else
+               astate->addr.s_addr = INADDR_ANY;
+
+#ifdef PRIVSEP
+       if (addr != NULL && IN_PRIVSEP_SE(ifp->ctx)) {
+               if (ps_bpf_addaddr(ifp, addr) == -1)
+                       logerr(__func__);
+       } else
+#endif
+       if (state->bpf_fd != -1) {
+               if (bpf_arp(ifp, state->bpf_fd) == -1)
+                       logerr(__func__); /* try and continue */
+       }
+}
+
 struct arp_state *
 arp_new(struct interface *ifp, const struct in_addr *addr)
 {
@@ -590,6 +611,13 @@ arp_new(struct interface *ifp, const struct in_addr *addr)
        struct arp_state *astate;
 
        if ((state = ARP_STATE(ifp)) == NULL) {
+#ifdef PRIVSEP
+               /* We need to ensure ARP is spawned so we can add to it. */
+               if (IN_PRIVSEP_SE(ifp->ctx) && arp_open(ifp) == -1) {
+                       logerr(__func__);
+                       return NULL;
+               }
+#endif
                ifp->if_data[IF_DATA_ARP] = malloc(sizeof(*state));
                state = ARP_STATE(ifp);
                if (state == NULL) {
@@ -610,24 +638,9 @@ arp_new(struct interface *ifp, const struct in_addr *addr)
                return NULL;
        }
        astate->iface = ifp;
-       if (addr)
-               astate->addr = *addr;
        state = ARP_STATE(ifp);
        TAILQ_INSERT_TAIL(&state->arp_states, astate, next);
-
-#ifdef PRIVSEP
-       if (ifp->ctx->options & DHCPCD_PRIVSEP) {
-#if 0
-               if (privsep_arp_bpf(state) == -1)
-                       logerr(__func__);
-#endif
-       } else
-#endif
-       if (state->bpf_fd != -1) {
-               if (bpf_arp(ifp, state->bpf_fd) == -1)
-                       logerr(__func__); /* try and continue */
-       }
-
+       arp_change(astate, addr);
        return astate;
 }
 
@@ -649,6 +662,7 @@ arp_free(struct arp_state *astate)
 
        ifp = astate->iface;
        eloop_timeout_delete(ifp->ctx->eloop, NULL, astate);
+       arp_change(astate, NULL);
        state = ARP_STATE(ifp);
        TAILQ_REMOVE(&state->arp_states, astate, next);
        if (astate->free_cb)
index a0f89f198bf507bad49caef0c0446cdc2c5d038f..01f665d4be81b3184f3760a1515118e3681f3538 100644 (file)
--- a/src/arp.h
+++ b/src/arp.h
@@ -92,11 +92,13 @@ struct iarp_state {
 #ifdef ARP
 void arp_packet(struct interface *, uint8_t *, size_t);
 struct arp_state *arp_new(struct interface *, const struct in_addr *);
+void arp_change(struct arp_state *, const struct in_addr *);
 void arp_probe(struct arp_state *);
 void arp_announce(struct arp_state *);
 void arp_announceaddr(struct dhcpcd_ctx *, const struct in_addr *);
 void arp_ifannounceaddr(struct interface *, const struct in_addr *);
 void arp_cancel(struct arp_state *);
+struct arp_state * arp_find(struct interface *, const struct in_addr *);
 void arp_free(struct arp_state *);
 void arp_freeaddr(struct interface *, const struct in_addr *);
 void arp_drop(struct interface *);
index a686cc6545d47c5d4e51b1b5e834dac2792e978f..c6b177982b79f0d3aa7baf76ef2b585b2b2a5b04 100644 (file)
--- a/src/bpf.c
+++ b/src/bpf.c
@@ -464,6 +464,8 @@ bpf_arp(struct interface *ifp, int fd)
        struct bpf_insn *bp;
        struct iarp_state *state;
        uint16_t arp_len;
+       struct arp_state *astate;
+       size_t naddrs;
 
        if (fd == -1)
                return 0;
@@ -489,68 +491,61 @@ bpf_arp(struct interface *ifp, int fd)
        bp += bpf_cmp_hwaddr(bp, BPF_CMP_HWADDR_LEN, sizeof(struct arphdr),
                             false, ifp->hwaddr, ifp->hwlen);
 
-#ifdef PRIVSEP
-       if (ifp->ctx->options & DHCPCD_PRIVSEP) {
-               /* No mech to notify of ARP states, so just accept all ARP. */
-               BPF_SET_STMT(bp, BPF_RET + BPF_K, arp_len);
-               bp++;
-               return bpf_attach(fd, bpf, (unsigned int)(bp - bpf));
-       }
-#endif
-
        state = ARP_STATE(ifp);
-       if (TAILQ_FIRST(&state->arp_states)) {
-               struct arp_state *astate;
-               size_t naddrs;
+       /* privsep may not have an initial state yet. */
+       if (state == NULL || TAILQ_FIRST(&state->arp_states) == NULL)
+               goto noaddrs;
 
-               /* Match sender protocol address */
-               BPF_SET_STMT(bp, BPF_LD + BPF_W + BPF_IND,
-                            sizeof(struct arphdr) + ifp->hwlen);
-               bp++;
-               naddrs = 0;
-               TAILQ_FOREACH(astate, &state->arp_states, next) {
-                       if (++naddrs > ARP_ADDRS_MAX) {
-                               errno = ENOBUFS;
-                               logerr(__func__);
-                               break;
-                       }
-                       BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K,
-                                    htonl(astate->addr.s_addr), 0, 1);
-                       bp++;
-                       BPF_SET_STMT(bp, BPF_RET + BPF_K, arp_len);
-                       bp++;
+       /* Match sender protocol address */
+       BPF_SET_STMT(bp, BPF_LD + BPF_W + BPF_IND,
+                    sizeof(struct arphdr) + ifp->hwlen);
+       bp++;
+       naddrs = 0;
+       TAILQ_FOREACH(astate, &state->arp_states, next) {
+               if (IN_IS_ADDR_UNSPECIFIED(&astate->addr))
+                       continue;
+               if (++naddrs > ARP_ADDRS_MAX) {
+                       errno = ENOBUFS;
+                       logerr(__func__);
+                       break;
                }
-
-               /* If we didn't match sender, then we're only interested in
-                * ARP probes to us, so check the null host sender. */
-               BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K, INADDR_ANY, 1, 0);
+               BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K,
+                            htonl(astate->addr.s_addr), 0, 1);
                bp++;
-               BPF_SET_STMT(bp, BPF_RET + BPF_K, 0);
+               BPF_SET_STMT(bp, BPF_RET + BPF_K, arp_len);
                bp++;
+       }
 
-               /* Match target protocol address */
-               BPF_SET_STMT(bp, BPF_LD + BPF_W + BPF_IND,
-                            (sizeof(struct arphdr)
-                            + (size_t)(ifp->hwlen * 2) + sizeof(in_addr_t)));
-               bp++;
-               naddrs = 0;
-               TAILQ_FOREACH(astate, &state->arp_states, next) {
-                       if (++naddrs > ARP_ADDRS_MAX) {
-                               /* Already logged error above. */
-                               break;
-                       }
-                       BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K,
-                                    htonl(astate->addr.s_addr), 0, 1);
-                       bp++;
-                       BPF_SET_STMT(bp, BPF_RET + BPF_K, arp_len);
-                       bp++;
-               }
+       /* If we didn't match sender, then we're only interested in
+        * ARP probes to us, so check the null host sender. */
+       BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K, INADDR_ANY, 1, 0);
+       bp++;
+       BPF_SET_STMT(bp, BPF_RET + BPF_K, 0);
+       bp++;
 
-               /* Return nothing, no protocol address match. */
-               BPF_SET_STMT(bp, BPF_RET + BPF_K, 0);
+       /* Match target protocol address */
+       BPF_SET_STMT(bp, BPF_LD + BPF_W + BPF_IND,
+                    (sizeof(struct arphdr)
+                    + (size_t)(ifp->hwlen * 2) + sizeof(in_addr_t)));
+       bp++;
+       naddrs = 0;
+       TAILQ_FOREACH(astate, &state->arp_states, next) {
+               if (++naddrs > ARP_ADDRS_MAX) {
+                       /* Already logged error above. */
+                       break;
+               }
+               BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K,
+                            htonl(astate->addr.s_addr), 0, 1);
+               bp++;
+               BPF_SET_STMT(bp, BPF_RET + BPF_K, arp_len);
                bp++;
        }
 
+noaddrs:
+       /* Return nothing, no protocol address match. */
+       BPF_SET_STMT(bp, BPF_RET + BPF_K, 0);
+       bp++;
+
        return bpf_attach(fd, bpf, (unsigned int)(bp - bpf));
 }
 #endif
index 621a03fed6d9a94aef93faae323e5d1618b72b29..635e524770f910cbe3b1da61fe2b1e36badd7655 100644 (file)
@@ -1527,7 +1527,7 @@ dhcp_close(struct interface *ifp)
                return;
 
 #ifdef PRIVSEP
-       if ((ctx->options & (DHCPCD_PRIVSEP|DHCPCD_FORKED)) == DHCPCD_PRIVSEP) {
+       if (IN_PRIVSEP_SE(ctx)) {
                ps_bpf_closebootp(ifp);
                if (state->addr != NULL)
                        ps_inet_closebootp(state->addr);
@@ -2090,8 +2090,11 @@ dhcp_arp_not_found(struct arp_state *astate)
                 * address or hwaddr, so move to the next
                 * arping profile */
                if (++state->arping_index < ifo->arping_len) {
-                       astate->addr.s_addr =
-                           ifo->arping[state->arping_index];
+                       struct in_addr addr = {
+                               .s_addr = ifo->arping[state->arping_index]
+                       };
+
+                       arp_change(astate, &addr);
                        arp_probe(astate);
                        return;
                }
@@ -2292,7 +2295,7 @@ dhcp_bind(struct interface *ifp)
                return;
 
 #ifdef PRIVSEP
-       if (ctx->options & DHCPCD_PRIVSEP) {
+       if (IN_PRIVSEP_SE(ctx)) {
                if (ps_inet_openbootp(state->addr) == -1)
                    logerr(__func__);
                return;
@@ -3434,7 +3437,7 @@ dhcp_packet(struct interface *ifp, uint8_t *data, size_t len)
 
 #ifdef PRIVSEP
        /* Ignore double reads */
-       if (ifp->ctx->options & DHCPCD_PRIVSEP) {
+       if (IN_PRIVSEP(ifp->ctx)) {
                switch (state->state) {
                case DHS_BOUND: /* FALLTHROUGH */
                case DHS_RENEW:
@@ -3527,7 +3530,7 @@ dhcp_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg)
                return;
        }
 #ifdef PRIVSEP
-       if (ctx->options & DHCPCD_PRIVSEP) {
+       if (IN_PRIVSEP(ctx)) {
                switch (state->state) {
                case DHS_BOUND: /* FALLTHROUGH */
                case DHS_RENEW:
@@ -3607,7 +3610,7 @@ dhcp_openbpf(struct interface *ifp)
        state = D_STATE(ifp);
 
 #ifdef PRIVSEP
-       if (ifp->ctx->options & DHCPCD_PRIVSEP) {
+       if (IN_PRIVSEP_SE(ifp->ctx)) {
                if (ps_bpf_openbootp(ifp) == -1) {
                        logerr(__func__);
                        return -1;
index fefe3c94132ad2ffff181c15a2a77f5694f9c68b..6a3b86f51e21963dfb6de96b0e1e7f0a15d4acf0 100644 (file)
@@ -1538,14 +1538,18 @@ static void
 dhcpcd_fork_cb(void *arg)
 {
        struct dhcpcd_ctx *ctx = arg;
-       int exit_code = EXIT_FAILURE;
+       int exit_code;
        ssize_t len;
 
        len = read(ctx->fork_fd, &exit_code, sizeof(exit_code));
-       if (len == -1)
+       if (len == -1) {
                logerr(__func__);
-       else if ((size_t)len < sizeof(exit_code))
-               logerr("%s: truncated read", __func__);
+               exit_code = EXIT_FAILURE;
+       } else if ((size_t)len < sizeof(exit_code)) {
+               logerrx("%s: truncated read %zd (expected %zu)",
+                   __func__, len, sizeof(exit_code));
+               exit_code = EXIT_FAILURE;
+       }
        eloop_exit(ctx->eloop, exit_code);
 }
 
index 24a2b674f79daae5142f98ad9078f184931be26f..38c479af0c0f98bd75b2c984675c222b442ba865 100644 (file)
@@ -85,11 +85,49 @@ ps_bpf_recvbpf(void *arg)
 }
 
 static ssize_t
-ps_bpf_recvmsgcb(void *arg, __unused struct ps_msghdr *psm, struct msghdr *msg)
+ps_bpf_arp_addr(uint8_t cmd, struct ps_process *psp, struct msghdr *msg)
+{
+       struct interface *ifp = &psp->psp_ifp;
+       struct iovec *iov = msg->msg_iov;
+       struct in_addr addr;
+       struct arp_state *astate;
+
+       if (psp == NULL) {
+               errno = ESRCH;
+               return -1;
+       }
+
+       assert(msg->msg_iovlen == 1);
+       assert(iov->iov_len = sizeof(addr));
+       memcpy(&addr, iov->iov_base, sizeof(addr));
+       if (cmd & PS_START) {
+               astate = arp_new(ifp, &addr);
+               if (astate == NULL)
+                       return -1;
+       } else if (cmd & PS_DELETE) {
+               astate = arp_find(ifp, &addr);
+               if (astate == NULL) {
+                       errno = ESRCH;
+                       return -1;
+               }
+               arp_free(astate);
+       } else {
+               errno = EINVAL;
+               return -1;
+       }
+
+       return bpf_arp(ifp, psp->psp_work_fd);
+}
+
+static ssize_t
+ps_bpf_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
 {
        struct ps_process *psp = arg;
        struct iovec *iov = msg->msg_iov;
 
+       if (psm->ps_cmd & (PS_START | PS_DELETE))
+               return ps_bpf_arp_addr(psm->ps_cmd, psp, msg);
+
        return bpf_send(&psp->psp_ifp, psp->psp_work_fd, psp->psp_proto,
            iov->iov_base, iov->iov_len);
 }
@@ -261,10 +299,14 @@ ps_bpf_send(const struct interface *ifp, uint8_t cmd,
                .ps_cmd = cmd,
                .ps_id = {
                        .psi_ifindex = ifp->index,
-                       .psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)),
+                       .psi_cmd = (uint8_t)(cmd &
+                           ~(PS_START | PS_STOP | PS_DELETE)),
                },
        };
 
+       if (psm.ps_id.psi_cmd == PS_BPF_ARP_ADDR)
+               psm.ps_id.psi_cmd = PS_BPF_ARP;
+
        return ps_sendpsmdata(ctx, ctx->ps_root_fd, &psm, data, len);
 }
 
@@ -276,6 +318,20 @@ ps_bpf_openarp(const struct interface *ifp)
        return ps_bpf_send(ifp, PS_BPF_ARP | PS_START, ifp, sizeof(*ifp));
 }
 
+ssize_t
+ps_bpf_addaddr(const struct interface *ifp, const struct in_addr *addr)
+{
+
+       return ps_bpf_send(ifp, PS_BPF_ARP_ADDR | PS_START, addr, sizeof(*addr));
+}
+
+ssize_t
+ps_bpf_deladdr(const struct interface *ifp, const struct in_addr *addr)
+{
+
+       return ps_bpf_send(ifp, PS_BPF_ARP_ADDR | PS_DELETE, addr, sizeof(*addr));
+}
+
 ssize_t
 ps_bpf_closearp(const struct interface *ifp)
 {
index aab0ae4cb37073996af88b1e6ac31ccb410561f2..122a2970c1953bbc9e02192392f08d5ac364ea13 100644 (file)
@@ -36,6 +36,8 @@ ssize_t ps_bpf_dispatch(struct dhcpcd_ctx *,
 
 #ifdef ARP
 ssize_t ps_bpf_openarp(const struct interface *);
+ssize_t ps_bpf_addaddr(const struct interface *, const struct in_addr *);
+ssize_t ps_bpf_deladdr(const struct interface *, const struct in_addr *);
 ssize_t ps_bpf_closearp(const struct interface *);
 ssize_t ps_bpf_sendarp(const struct interface *, const void *, size_t);
 #endif
index 10d97425e1c502c498a5d8d757e3ff51550ceb49..63045c164363a61386102090dcf422ed6622b5c8 100644 (file)
@@ -116,6 +116,10 @@ ps_root_writeerror(struct dhcpcd_ctx *ctx, ssize_t result)
                .psr_errno = errno,
        };
 
+#ifdef PRIVSEP_DEBUG
+       logdebugx("%s: result %zd errno %d", __func__, result, errno);
+#endif
+
        return write(ctx->ps_root_fd, &psr, sizeof(psr));
 }
 
@@ -194,14 +198,16 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
        size_t len = iov->iov_len;
        ssize_t err;
 
-       cmd = (uint8_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
+       cmd = (uint8_t)(psm->ps_cmd & ~(PS_START | PS_STOP | PS_DELETE));
        psp = ps_findprocess(ctx, &psm->ps_id);
 
 #ifdef PRIVSEP_DEBUG
        logerrx("%s: IN cmd %x, psp %p", __func__, psm->ps_cmd, psp);
 #endif
 
-       if (!(psm->ps_cmd & PS_START) && psp != NULL) {
+       if ((!(psm->ps_cmd & PS_START) || cmd == PS_BPF_ARP_ADDR) &&
+           psp != NULL)
+       {
                if (psm->ps_cmd & PS_STOP) {
                        int ret = ps_dostop(ctx, &psp->psp_pid, &psp->psp_fd);
 
@@ -211,7 +217,7 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
                return ps_sendpsmmsg(ctx, psp->psp_fd, psm, msg);
        }
 
-       if (psm->ps_cmd & PS_STOP && psp == NULL)
+       if (psm->ps_cmd & (PS_STOP | PS_DELETE) && psp == NULL)
                return 0;
 
        /* All these should just be PS_START */
index b1b0697124266111ba267d3144a624448915e215..c3e0f0e5276efcd726dadec9123190de8ba3821b 100644 (file)
@@ -650,6 +650,7 @@ ps_newprocess(struct dhcpcd_ctx *ctx, struct ps_id *psid)
                return NULL;
        psp->psp_ctx = ctx;
        memcpy(&psp->psp_id, psid, sizeof(psp->psp_id));
+       psp->psp_work_fd = -1;
        TAILQ_INSERT_TAIL(&ctx->ps_processes, psp, next);
        return psp;
 }
index 85804a6db50595cd42c3724ac0c6b7e205947b28..02c06c4d1b5b950188a33b514425994c198405e1 100644 (file)
@@ -40,6 +40,7 @@
 #define        PS_DHCP6                0x03
 #define        PS_BPF_BOOTP            0x04
 #define        PS_BPF_ARP              0x05
+#define        PS_BPF_ARP_ADDR         0x06
 
 #define        PS_IOCTL                0x10
 #define        PS_SCRIPT               0x11
@@ -47,6 +48,7 @@
 #define        PS_ROUTE                0x13    /* Also used for NETLINK */
 #define        PS_WRITEPATHUINT        0x14
 
+#define        PS_DELETE               0x20
 #define        PS_START                0x40
 #define        PS_STOP                 0x80
 
                                 CMSG_SPACE(sizeof(struct in6_pktinfo) + \
                                            sizeof(int)))
 
+/* Handy macro to work out if in the privsep engine or not. */
+#define        IN_PRIVSEP(ctx) \
+       ((ctx)->options & DHCPCD_PRIVSEP)
+#define        IN_PRIVSEP_SE(ctx)      \
+       (((ctx)->options & (DHCPCD_PRIVSEP | DHCPCD_FORKED)) == DHCPCD_PRIVSEP)
+
 #include "config.h"
 #include "arp.h"
 #include "dhcp.h"