summaryrefslogtreecommitdiffstats
path: root/src/privsep-bpf.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2019-12-10 21:00:58 +0000
committerRoy Marples <roy@marples.name>2019-12-10 21:00:58 +0000
commit3ac9885e95854fd82dc498fbc3871a04b5ed1c69 (patch)
treec5ea716fb398af9892c779107328c5f4b7ea5a24 /src/privsep-bpf.c
parente02016b276ef1dbd02f02ba0b1c9a0e71639f28b (diff)
downloaddhcpcd-3ac9885e95854fd82dc498fbc3871a04b5ed1c69.tar.xz
privsep: Enable ARP BPF filtering for interesting addresses
This brings parity with non privsep features. Aside from the lack of Solaris support, but that's another day.
Diffstat (limited to 'src/privsep-bpf.c')
-rw-r--r--src/privsep-bpf.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/src/privsep-bpf.c b/src/privsep-bpf.c
index 24a2b674..38c479af 100644
--- a/src/privsep-bpf.c
+++ b/src/privsep-bpf.c
@@ -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);
}
@@ -277,6 +319,20 @@ ps_bpf_openarp(const struct interface *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)
{