aboutsummaryrefslogtreecommitdiff
path: root/src/privsep-inet.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/privsep-inet.c')
-rw-r--r--src/privsep-inet.c168
1 files changed, 96 insertions, 72 deletions
diff --git a/src/privsep-inet.c b/src/privsep-inet.c
index 3a192ee0c461..919fe9540b0a 100644
--- a/src/privsep-inet.c
+++ b/src/privsep-inet.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Privilege Separation for dhcpcd, network proxy
- * Copyright (c) 2006-2021 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2023 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -47,32 +47,37 @@
#include "logerr.h"
#include "privsep.h"
+/* We expect to have open 2 SEQPACKET, 1 udp, 1 udp6 and 1 raw6 fds */
+
#ifdef INET
static void
-ps_inet_recvbootp(void *arg)
+ps_inet_recvbootp(void *arg, unsigned short events)
{
struct dhcpcd_ctx *ctx = arg;
- if (ps_recvmsg(ctx, ctx->udp_rfd, PS_BOOTP, ctx->ps_inet_fd) == -1)
+ if (ps_recvmsg(ctx->udp_rfd, events,
+ PS_BOOTP, ctx->ps_inet->psp_fd) == -1)
logerr(__func__);
}
#endif
#ifdef INET6
static void
-ps_inet_recvra(void *arg)
+ps_inet_recvra(void *arg, unsigned short events)
{
#ifdef __sun
struct interface *ifp = arg;
struct rs_state *state = RS_STATE(ifp);
struct dhcpcd_ctx *ctx = ifp->ctx;
- if (ps_recvmsg(ctx, state->nd_fd, PS_ND, ctx->ps_inet_fd) == -1)
+ if (ps_recvmsg(state->nd_fd, events,
+ PS_ND, ctx->ps_inet->psp_fd) == -1)
logerr(__func__);
#else
struct dhcpcd_ctx *ctx = arg;
- if (ps_recvmsg(ctx, ctx->nd_fd, PS_ND, ctx->ps_inet_fd) == -1)
+ if (ps_recvmsg(ctx->nd_fd, events,
+ PS_ND, ctx->ps_inet->psp_fd) == -1)
logerr(__func__);
#endif
}
@@ -80,11 +85,12 @@ ps_inet_recvra(void *arg)
#ifdef DHCP6
static void
-ps_inet_recvdhcp6(void *arg)
+ps_inet_recvdhcp6(void *arg, unsigned short events)
{
struct dhcpcd_ctx *ctx = arg;
- if (ps_recvmsg(ctx, ctx->dhcp6_rfd, PS_DHCP6, ctx->ps_inet_fd) == -1)
+ if (ps_recvmsg(ctx->dhcp6_rfd, events,
+ PS_DHCP6, ctx->ps_inet->psp_fd) == -1)
logerr(__func__);
}
#endif
@@ -112,16 +118,16 @@ ps_inet_canstart(const struct dhcpcd_ctx *ctx)
}
static int
-ps_inet_startcb(void *arg)
+ps_inet_startcb(struct ps_process *psp)
{
- struct dhcpcd_ctx *ctx = arg;
+ struct dhcpcd_ctx *ctx = psp->psp_ctx;
int ret = 0;
if (ctx->options & DHCPCD_MANAGER)
setproctitle("[network proxy]");
else
setproctitle("[network proxy] %s%s%s",
- ctx->ifv[0],
+ ctx->ifc != 0 ? ctx->ifv[0] : "",
ctx->options & DHCPCD_IPV4 ? " [ip4]" : "",
ctx->options & DHCPCD_IPV6 ? " [ip6]" : "");
@@ -145,7 +151,7 @@ ps_inet_startcb(void *arg)
ctx->udp_rfd = -1;
}
#endif
- else if (eloop_event_add(ctx->eloop, ctx->udp_rfd,
+ else if (eloop_event_add(ctx->eloop, ctx->udp_rfd, ELE_READ,
ps_inet_recvbootp, ctx) == -1)
{
logerr("%s: eloop_event_add DHCP", __func__);
@@ -167,7 +173,7 @@ ps_inet_startcb(void *arg)
ctx->nd_fd = -1;
}
#endif
- else if (eloop_event_add(ctx->eloop, ctx->nd_fd,
+ else if (eloop_event_add(ctx->eloop, ctx->nd_fd, ELE_READ,
ps_inet_recvra, ctx) == -1)
{
logerr("%s: eloop_event_add RA", __func__);
@@ -191,7 +197,7 @@ ps_inet_startcb(void *arg)
ctx->dhcp6_rfd = -1;
}
#endif
- else if (eloop_event_add(ctx->eloop, ctx->dhcp6_rfd,
+ else if (eloop_event_add(ctx->eloop, ctx->dhcp6_rfd, ELE_READ,
ps_inet_recvdhcp6, ctx) == -1)
{
logerr("%s: eloop_event_add DHCP6", __func__);
@@ -299,12 +305,12 @@ dosend:
}
static void
-ps_inet_recvmsg(void *arg)
+ps_inet_recvmsg(void *arg, unsigned short events)
{
- struct dhcpcd_ctx *ctx = arg;
+ struct ps_process *psp = arg;
/* Receive shutdown */
- if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, NULL, NULL) == -1)
+ if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events, NULL, NULL) == -1)
logerr(__func__);
}
@@ -337,23 +343,32 @@ ps_inet_dispatch(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
}
static void
-ps_inet_dodispatch(void *arg)
+ps_inet_dodispatch(void *arg, unsigned short events)
{
- struct dhcpcd_ctx *ctx = arg;
+ struct ps_process *psp = arg;
- if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, ps_inet_dispatch, ctx) == -1)
+ if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events,
+ ps_inet_dispatch, psp->psp_ctx) == -1)
logerr(__func__);
}
pid_t
ps_inet_start(struct dhcpcd_ctx *ctx)
{
+ struct ps_id id = {
+ .psi_ifindex = 0,
+ .psi_cmd = PS_INET,
+ };
+ struct ps_process *psp;
pid_t pid;
- pid = ps_dostart(ctx, &ctx->ps_inet_pid, &ctx->ps_inet_fd,
- ps_inet_recvmsg, ps_inet_dodispatch, ctx,
- ps_inet_startcb, NULL,
- PSF_DROPPRIVS);
+ psp = ctx->ps_inet = ps_newprocess(ctx, &id);
+ if (psp == NULL)
+ return -1;
+
+ strlcpy(psp->psp_name, "network proxy", sizeof(psp->psp_name));
+ pid = ps_startprocess(psp, ps_inet_recvmsg, ps_inet_dodispatch,
+ ps_inet_startcb, NULL, PSF_DROPPRIVS);
if (pid == 0)
ps_entersandbox("stdio", NULL);
@@ -365,29 +380,28 @@ int
ps_inet_stop(struct dhcpcd_ctx *ctx)
{
- return ps_dostop(ctx, &ctx->ps_inet_pid, &ctx->ps_inet_fd);
+ return ps_stopprocess(ctx->ps_inet);
}
#ifdef INET
static void
-ps_inet_recvinbootp(void *arg)
+ps_inet_recvinbootp(void *arg, unsigned short events)
{
struct ps_process *psp = arg;
- if (ps_recvmsg(psp->psp_ctx, psp->psp_work_fd,
+ if (ps_recvmsg(psp->psp_work_fd, events,
PS_BOOTP, psp->psp_ctx->ps_data_fd) == -1)
logerr(__func__);
}
static int
-ps_inet_listenin(void *arg)
+ps_inet_listenin(struct ps_process *psp)
{
- struct ps_process *psp = arg;
struct in_addr *ia = &psp->psp_id.psi_addr.psa_in_addr;
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, ia, buf, sizeof(buf));
- setproctitle("[network proxy] %s", buf);
+ setproctitle("[%s proxy] %s", psp->psp_protostr, buf);
psp->psp_work_fd = dhcp_openudp(ia);
if (psp->psp_work_fd == -1) {
@@ -402,14 +416,12 @@ ps_inet_listenin(void *arg)
}
#endif
- if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd,
+ if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, ELE_READ,
ps_inet_recvinbootp, psp) == -1)
{
logerr("%s: eloop_event_add DHCP", __func__);
return -1;
}
-
- logdebugx("spawned listener %s on PID %d", buf, getpid());
return 0;
}
#endif
@@ -420,15 +432,14 @@ ps_inet_recvin6nd(void *arg)
{
struct ps_process *psp = arg;
- if (ps_recvmsg(psp->psp_ctx, psp->psp_work_fd,
+ if (ps_recvmsg(psp->psp_work_fd,
PS_ND, psp->psp_ctx->ps_data_fd) == -1)
logerr(__func__);
}
static int
-ps_inet_listennd(void *arg)
+ps_inet_listennd(struct ps_process *psp)
{
- struct ps_process *psp = arg;
setproctitle("[ND network proxy]");
@@ -451,32 +462,29 @@ ps_inet_listennd(void *arg)
logerr(__func__);
return -1;
}
-
- logdebugx("spawned ND listener on PID %d", getpid());
return 0;
}
#endif
#ifdef DHCP6
static void
-ps_inet_recvin6dhcp6(void *arg)
+ps_inet_recvin6dhcp6(void *arg, unsigned short events)
{
struct ps_process *psp = arg;
- if (ps_recvmsg(psp->psp_ctx, psp->psp_work_fd,
+ if (ps_recvmsg(psp->psp_work_fd, events,
PS_DHCP6, psp->psp_ctx->ps_data_fd) == -1)
logerr(__func__);
}
static int
-ps_inet_listenin6(void *arg)
+ps_inet_listenin6(struct ps_process *psp)
{
- struct ps_process *psp = arg;
struct in6_addr *ia = &psp->psp_id.psi_addr.psa_in6_addr;
char buf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, ia, buf, sizeof(buf));
- setproctitle("[network proxy] %s", buf);
+ setproctitle("[%s proxy] %s", psp->psp_protostr, buf);
psp->psp_work_fd = dhcp6_openudp(psp->psp_id.psi_ifindex, ia);
if (psp->psp_work_fd == -1) {
@@ -491,25 +499,23 @@ ps_inet_listenin6(void *arg)
}
#endif
- if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd,
+ if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, ELE_READ,
ps_inet_recvin6dhcp6, psp) == -1)
{
logerr("%s: eloop_event_add DHCP", __func__);
return -1;
}
-
- logdebugx("spawned listener %s on PID %d", buf, getpid());
return 0;
}
#endif
static void
-ps_inet_recvmsgpsp(void *arg)
+ps_inet_recvmsgpsp(void *arg, unsigned short events)
{
struct ps_process *psp = arg;
/* Receive shutdown. */
- if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, NULL, NULL) == -1)
+ if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events, NULL, NULL) == -1)
logerr(__func__);
}
@@ -518,8 +524,11 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
{
uint16_t cmd;
struct ps_process *psp;
- int (*start_func)(void *);
+ int (*start_func)(struct ps_process *);
pid_t start;
+ struct ps_addr *psa = &psm->ps_id.psi_addr;
+ void *ia;
+ char buf[INET_MAX_ADDRSTRLEN];
cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
if (cmd == psm->ps_cmd)
@@ -536,21 +545,40 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
return 0;
}
+ if (!(psm->ps_cmd & PS_START)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (psp != NULL)
+ return 1;
+
+ psp = ps_newprocess(ctx, &psm->ps_id);
+ if (psp == NULL)
+ return -1;
+
+
switch (cmd) {
#ifdef INET
case PS_BOOTP:
start_func = ps_inet_listenin;
+ psp->psp_protostr = "BOOTP";
+ ia = &psa->psa_in_addr;
break;
#endif
#ifdef INET6
#ifdef __sun
case PS_ND:
start_func = ps_inet_listennd;
+ psp->psp_protostr = "ND";
+ ia = &psa->psa_in6_addr;
break;
#endif
#ifdef DHCP6
case PS_DHCP6:
start_func = ps_inet_listenin6;
+ psp->psp_protostr = "DHCP6";
+ ia = &psa->psa_in6_addr;
break;
#endif
#endif
@@ -560,23 +588,11 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
return -1;
}
- if (!(psm->ps_cmd & PS_START)) {
- errno = EINVAL;
- return -1;
- }
-
- if (psp != NULL)
- return 1;
-
- psp = ps_newprocess(ctx, &psm->ps_id);
- if (psp == NULL)
- return -1;
-
- start = ps_dostart(ctx,
- &psp->psp_pid, &psp->psp_fd,
- ps_inet_recvmsgpsp, NULL, psp,
- start_func, NULL,
- PSF_DROPPRIVS);
+ snprintf(psp->psp_name, sizeof(psp->psp_name),
+ "%s proxy %s", psp->psp_protostr,
+ inet_ntop(psa->psa_family, ia, buf, sizeof(buf)));
+ start = ps_startprocess(psp, ps_inet_recvmsgpsp, NULL,
+ start_func, NULL, PSF_DROPPRIVS);
switch (start) {
case -1:
ps_freeprocess(psp);
@@ -585,6 +601,8 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
ps_entersandbox("stdio", NULL);
break;
default:
+ logdebugx("%s: spawned %s on PID %d",
+ psp->psp_ifname, psp->psp_name, psp->psp_pid);
break;
}
return start;
@@ -601,11 +619,12 @@ ps_inet_in_docmd(struct ipv4_addr *ia, uint16_t cmd, const struct msghdr *msg)
.ps_id = {
.psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)),
.psi_ifindex = ia->iface->index,
+ .psi_addr.psa_family = AF_INET,
.psi_addr.psa_in_addr = ia->addr,
},
};
- return ps_sendpsmmsg(ctx, ctx->ps_root_fd, &psm, msg);
+ return ps_sendpsmmsg(ctx, PS_ROOT_FD(ctx), &psm, msg);
}
ssize_t
@@ -625,8 +644,9 @@ ps_inet_closebootp(struct ipv4_addr *ia)
ssize_t
ps_inet_sendbootp(struct interface *ifp, const struct msghdr *msg)
{
+ struct dhcpcd_ctx *ctx = ifp->ctx;
- return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_BOOTP, 0, msg);
+ return ps_sendmsg(ctx, PS_ROOT_FD(ctx), PS_BOOTP, 0, msg);
}
#endif /* INET */
@@ -641,10 +661,11 @@ ps_inet_ifp_docmd(struct interface *ifp, uint16_t cmd, const struct msghdr *msg)
.ps_id = {
.psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)),
.psi_ifindex = ifp->index,
+ .psi_addr.psa_family = AF_INET6,
},
};
- return ps_sendpsmmsg(ctx, ctx->ps_root_fd, &psm, msg);
+ return ps_sendpsmmsg(ctx, PS_ROOT_FD(ctx), &psm, msg);
}
ssize_t
@@ -671,8 +692,9 @@ ps_inet_sendnd(struct interface *ifp, const struct msghdr *msg)
ssize_t
ps_inet_sendnd(struct interface *ifp, const struct msghdr *msg)
{
+ struct dhcpcd_ctx *ctx = ifp->ctx;
- return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_ND, 0, msg);
+ return ps_sendmsg(ctx, PS_ROOT_FD(ctx), PS_ND, 0, msg);
}
#endif
@@ -686,11 +708,12 @@ ps_inet_in6_docmd(struct ipv6_addr *ia, uint16_t cmd, const struct msghdr *msg)
.ps_id = {
.psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)),
.psi_ifindex = ia->iface->index,
+ .psi_addr.psa_family = AF_INET6,
.psi_addr.psa_in6_addr = ia->addr,
},
};
- return ps_sendpsmmsg(ctx, ctx->ps_root_fd, &psm, msg);
+ return ps_sendpsmmsg(ctx, PS_ROOT_FD(ctx), &psm, msg);
}
ssize_t
@@ -710,8 +733,9 @@ ps_inet_closedhcp6(struct ipv6_addr *ia)
ssize_t
ps_inet_senddhcp6(struct interface *ifp, const struct msghdr *msg)
{
+ struct dhcpcd_ctx *ctx = ifp->ctx;
- return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_DHCP6, 0, msg);
+ return ps_sendmsg(ctx, PS_ROOT_FD(ctx), PS_DHCP6, 0, msg);
}
#endif /* DHCP6 */
#endif /* INET6 */