Skip to content
313 changes: 198 additions & 115 deletions src/control.c

Large diffs are not rendered by default.

13 changes: 8 additions & 5 deletions src/control.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,19 @@ struct fd_list {
TAILQ_HEAD(fd_list_head, fd_list);

#define FD_LISTEN 0x01U
#define FD_UNPRIV 0x02U
#define FD_SENDLEN 0x04U
#define FD_COMMAND 0x02U
#define FD_PRIV 0x04U
#define FD_SENDLEN 0x08U

int control_start(struct dhcpcd_ctx *, const char *, sa_family_t);
int control_stop(struct dhcpcd_ctx *);
int control_open(const char *, sa_family_t, bool);
int control_open(const char *, sa_family_t);
ssize_t control_send(struct dhcpcd_ctx *, int, char *const *);
struct fd_list *control_find(struct dhcpcd_ctx *, int);
struct fd_list *control_new(struct dhcpcd_ctx *, int, unsigned int);
void control_free(struct fd_list *);
void control_delete(struct fd_list *);
int control_queue(struct fd_list *, void *, size_t);
int control_recvdata(struct fd_list *fd, char *, size_t);
int control_queue(struct fd_list *, const void *, size_t);
int control_recvmsg(struct fd_list *, struct msghdr *, size_t);
int control_user_ispriv(struct dhcpcd_ctx *ctx, uid_t uid, gid_t gid);
#endif
2 changes: 1 addition & 1 deletion src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#define DEFS_H

#define PACKAGE "dhcpcd"
#define VERSION "10.3.2"
#define VERSION "10.5.0"

#ifndef PRIVSEP_USER
#define PRIVSEP_USER "_" PACKAGE
Expand Down
6 changes: 1 addition & 5 deletions src/dhcpcd.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd May 8, 2025
.Dd July 5, 2026
.Dt DHCPCD 8
.Os
.Sh NAME
Expand Down Expand Up @@ -861,12 +861,8 @@ running on the
.Ar interface .
.It Pa @RUNDIR@/sock
Control socket to the manager daemon.
.It Pa @RUNDIR@/unpriv.sock
Unprivileged socket to the manager daemon, only allows state retrieval.
.It Pa @RUNDIR@/ Ns Ar interface Ns .sock
Control socket to per interface daemon.
.It Pa @RUNDIR@/ Ns Ar interface Ns .unpriv.sock
Unprivileged socket to per interface daemon, only allows state retrieval.
.El
.Sh SEE ALSO
.Xr fnmatch 3 ,
Expand Down
63 changes: 31 additions & 32 deletions src/dhcpcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1587,24 +1587,6 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd, int argc,
size_t len, l, nifaces;
char *tmp, *p;

/* Special commands for our control socket
* as the other end should be blocking until it gets the
* expected reply we should be safely able just to change the
* write callback on the fd */
/* Make any change here in privsep-control.c as well. */
if (strcmp(*argv, "--version") == 0) {
return control_queue(fd, UNCONST(VERSION), strlen(VERSION) + 1);
} else if (strcmp(*argv, "--getconfigfile") == 0) {
return control_queue(fd, UNCONST(fd->ctx->cffile),
strlen(fd->ctx->cffile) + 1);
} else if (strcmp(*argv, "--getinterfaces") == 0) {
oifind = argc = 0;
goto dumplease;
} else if (strcmp(*argv, "--listen") == 0) {
fd->flags |= FD_LISTEN;
return 0;
}

/* Log the command */
len = 1;
for (opt = 0; opt < argc; opt++)
Expand All @@ -1624,6 +1606,27 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd, int argc,
loginfox("control command: %s", tmp);
free(tmp);

/* Special commands for our control socket
* as the other end should be blocking until it gets the
* expected reply we should be safely able just to change the
* write callback on the fd */
/* Make any change here in privsep-control.c as well. */
if (strcmp(*argv, "--version") == 0) {
return control_queue(fd, VERSION, strlen(VERSION) + 1);
} else if (strcmp(*argv, "--getconfigfile") == 0) {
return control_queue(fd, fd->ctx->cffile,
strlen(fd->ctx->cffile) + 1);
} else if (strcmp(*argv, "--getinterfaces") == 0) {
oifind = argc = 0;
goto dumplease;
} else if (strcmp(*argv, "--isprivileged") == 0) {
const char *ret = fd->flags & FD_PRIV ? "true" : "false";
return control_queue(fd, ret, strlen(ret) + 1);
} else if (strcmp(*argv, "--listen") == 0) {
fd->flags |= FD_LISTEN;
return 0;
}

optind = 0;
oi = 0;
opts = 0;
Expand Down Expand Up @@ -1682,8 +1685,10 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd, int argc,
nifaces += (size_t)opt;
}
}
if (write(fd->fd, &nifaces, sizeof(nifaces)) != sizeof(nifaces))
fd->flags &= ~FD_SENDLEN;
if (control_queue(fd, &nifaces, sizeof(nifaces)) == -1)
goto dumperr;
fd->flags |= FD_SENDLEN;
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
if (!ifp->active)
continue;
Expand All @@ -1704,7 +1709,7 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd, int argc,
}

/* Only privileged users can control dhcpcd via the socket. */
if (fd->flags & FD_UNPRIV) {
if (!(fd->flags & FD_PRIV)) {
errno = EPERM;
return -1;
}
Expand Down Expand Up @@ -2078,7 +2083,7 @@ main(int argc, char **argv, char **envp)
ifo = NULL;
ctx.cffile = CONFIG;
ctx.script = UNCONST(dhcpcd_default_script);
ctx.control_fd = ctx.control_unpriv_fd = ctx.link_fd = -1;
ctx.control_fd = ctx.link_fd = -1;
ctx.pf_inet_fd = -1;
#ifdef PF_LINK
ctx.pf_link_fd = -1;
Expand Down Expand Up @@ -2421,20 +2426,12 @@ main(int argc, char **argv, char **envp)
if (!(ctx.options & DHCPCD_TEST)) {
ctx.options |= DHCPCD_FORKED; /* avoid socket unlink */
if (!(ctx.options & DHCPCD_MANAGER))
ctx.control_fd = control_open(argv[optind], family,
ctx.options & DHCPCD_DUMPLEASE);
ctx.control_fd = control_open(argv[optind], family);
if (!(ctx.options & DHCPCD_MANAGER) && ctx.control_fd == -1)
ctx.control_fd = control_open(argv[optind], AF_UNSPEC,
ctx.options & DHCPCD_DUMPLEASE);
ctx.control_fd = control_open(argv[optind], AF_UNSPEC);
if (ctx.control_fd == -1)
ctx.control_fd = control_open(NULL, AF_UNSPEC,
ctx.options & DHCPCD_DUMPLEASE);
ctx.control_fd = control_open(NULL, AF_UNSPEC);
if (ctx.control_fd != -1) {
#ifdef PRIVSEP
if (IN_PRIVSEP(&ctx) &&
ps_managersandbox(&ctx, NULL) == -1)
goto exit_failure;
#endif
if (!(ctx.options & DHCPCD_DUMPLEASE))
loginfox("sending commands to dhcpcd process");
len = control_send(&ctx, argc, argv);
Expand Down Expand Up @@ -2580,6 +2577,8 @@ main(int argc, char **argv, char **envp)
logdebugx("spawned manager process on PID %d", (int)getpid());

start_manager:

logdebugx("spawned manager process on PID %d", (int)getpid());
ctx.options |= DHCPCD_STARTED;
if ((pid = pidfile_lock(ctx.pidfile)) != 0) {
logerr("%s: pidfile_lock %d", __func__, (int)pid);
Expand Down
15 changes: 6 additions & 9 deletions src/dhcpcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,8 @@ struct dhcpcd_ctx {
size_t io_buflen;

int control_fd;
int control_unpriv_fd;
struct fd_list_head control_fds;
char control_sock[sizeof(CONTROLSOCKET) + IF_NAMESIZE];
char control_sock_unpriv[sizeof(CONTROLSOCKET) + IF_NAMESIZE + 7];
gid_t control_group;

/* DHCP Enterprise options, RFC3925 */
Expand All @@ -199,13 +197,12 @@ struct dhcpcd_ctx {
struct ps_process *ps_root;
struct ps_process *ps_inet;
struct ps_process *ps_ctl;
int ps_data_fd; /* data returned from processes */
int ps_log_fd; /* chroot logging */
int ps_log_root_fd; /* outside chroot log reader */
struct fd_list *ps_control; /* Queue for the above */
struct fd_list *ps_control_client; /* Queue for the above */
void *ps_buf; /* IPC buffer */
size_t ps_buflen; /* IPC buffer length */
int ps_data_fd; /* data returned from processes */
int ps_log_fd; /* chroot logging */
int ps_log_root_fd; /* outside chroot log reader */
struct fd_list *ps_control; /* Queue for the above */
void *ps_buf; /* IPC buffer */
size_t ps_buflen; /* IPC buffer length */
#endif

#ifdef INET
Expand Down
Loading