summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--distrib/special/dhclient/Makefile4
-rw-r--r--sbin/dhclient/dhclient.c111
-rw-r--r--sbin/dhclient/dhcpd.h10
-rw-r--r--sbin/dhclient/dispatch.c14
-rw-r--r--sbin/dhclient/kroute.c184
-rw-r--r--sbin/dhclient/privsep.c361
-rw-r--r--sbin/dhclient/privsep.h54
7 files changed, 251 insertions, 487 deletions
diff --git a/distrib/special/dhclient/Makefile b/distrib/special/dhclient/Makefile
index fc5a3014d75..e8cc7af8524 100644
--- a/distrib/special/dhclient/Makefile
+++ b/distrib/special/dhclient/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.12 2012/11/09 18:51:56 krw Exp $
+# $OpenBSD: Makefile,v 1.13 2012/11/23 15:25:47 krw Exp $
.include <bsd.own.mk>
@@ -10,6 +10,8 @@ SRCS= dhclient.c clparse.c dispatch.c bpf.c options.c \
conflex.c errwarn.c kroute.c packet.c convert.c \
tables.c parse.c privsep.c
PROG= dhclient
+LDADD+= -lutil
+DPADD+= ${LIBUTIL}
.include <bsd.prog.mk>
.include <bsd.subdir.mk>
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index fc2bfcc1d83..038b74dfed6 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.178 2012/11/16 16:46:18 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.179 2012/11/23 15:25:47 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -69,7 +69,6 @@ char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
char *path_dhclient_db = NULL;
int log_perror = 1;
-int privfd;
int nullfd = -1;
int no_daemon;
int unknown_ok = 1;
@@ -84,6 +83,7 @@ struct sockaddr_in sockaddr_broadcast;
struct interface_info *ifi;
struct client_state *client;
struct client_config *config;
+struct imsgbuf *unpriv_ibuf;
int findproto(char *, int);
struct sockaddr *get_ifa(char *, int);
@@ -97,6 +97,7 @@ void get_ifname(char *, char *);
void new_resolv_conf(char *, char *, char *);
struct client_lease *apply_defaults(struct client_lease *);
struct client_lease *clone_lease(struct client_lease *);
+void socket_nonblockmode(int);
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
@@ -259,7 +260,7 @@ die:
int
main(int argc, char *argv[])
{
- int ch, fd, quiet = 0, i = 0, pipe_fd[2];
+ int ch, fd, quiet = 0, i = 0, socket_fd[2];
extern char *__progname;
struct passwd *pw;
int rtfilter;
@@ -356,16 +357,20 @@ main(int argc, char *argv[])
if ((pw = getpwnam("_dhcp")) == NULL)
error("no such user: _dhcp");
- if (pipe(pipe_fd) == -1)
- error("pipe");
-
/* set up the interface */
discover_interface();
- fork_privchld(pipe_fd[0], pipe_fd[1]);
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socket_fd) == -1)
+ error("socketpair: %m");
+ socket_nonblockmode(socket_fd[0]);
+ socket_nonblockmode(socket_fd[1]);
+
+ fork_privchld(socket_fd[0], socket_fd[1]);
- close(pipe_fd[0]);
- privfd = pipe_fd[1];
+ close(socket_fd[0]);
+ if ((unpriv_ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
+ error("no memory for unpriv_ibuf");
+ imsg_init(unpriv_ibuf, socket_fd[1]);
if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
error("can't open and lock %s: %m", path_dhclient_db);
@@ -1688,6 +1693,8 @@ int
fork_privchld(int fd, int fd2)
{
struct pollfd pfd[1];
+ struct imsgbuf *priv_ibuf;
+ ssize_t n;
int nfds;
switch (fork()) {
@@ -1714,17 +1721,29 @@ fork_privchld(int fd, int fd2)
close(nullfd);
close(fd2);
+ if ((priv_ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
+ error("no memory for priv_ibuf");
+
+ imsg_init(priv_ibuf, fd);
+
for (;;) {
- pfd[0].fd = fd;
+ pfd[0].fd = priv_ibuf->fd;
pfd[0].events = POLLIN;
- if ((nfds = poll(pfd, 1, INFTIM)) == -1)
+ if ((nfds = poll(pfd, 1, INFTIM)) == -1) {
if (errno != EINTR)
- error("poll error");
+ error("poll error: %m");
+ }
if (nfds == 0 || !(pfd[0].revents & POLLIN))
continue;
- dispatch_imsg(fd);
+ if ((n = imsg_read(priv_ibuf)) == -1)
+ error("imsg_read(priv_ibuf): %m");
+
+ if (n == 0) /* connection closed */
+ error("dispatch_imsg in main: pipe closed");
+
+ dispatch_imsg(priv_ibuf);
}
}
@@ -1774,52 +1793,40 @@ get_ifname(char *ifname, char *arg)
* Update resolv.conf.
*/
-#define MAXRESOLVCONFSIZE 2048
-
void
new_resolv_conf(char *ifname, char *domainname, char *nameservers)
{
- size_t len;
- struct imsg_hdr hdr;
- struct buf *buf;
- char *contents, *p;
+ struct imsg_resolv_conf imsg;
+ char *p;
+ int rslt;
- contents = calloc(1, MAXRESOLVCONFSIZE);
+ memset(&imsg, 0, sizeof(imsg));
/* Build string of contents of new resolv.conf. */
if (domainname && strlen(domainname)) {
- strlcat(contents, "search ", MAXRESOLVCONFSIZE);
- strlcat(contents, domainname, MAXRESOLVCONFSIZE);
- strlcat(contents, "\n", MAXRESOLVCONFSIZE);
+ strlcat(imsg.contents, "search ", MAXRESOLVCONFSIZE);
+ strlcat(imsg.contents, domainname, MAXRESOLVCONFSIZE);
+ strlcat(imsg.contents, "\n", MAXRESOLVCONFSIZE);
}
for (p = strsep(&nameservers, " "); p != NULL;
p = strsep(&nameservers, " ")) {
if (*p == '\0')
continue;
- strlcat(contents, "nameserver ", MAXRESOLVCONFSIZE);
- strlcat(contents, p, MAXRESOLVCONFSIZE);
- strlcat(contents, "\n", MAXRESOLVCONFSIZE);
+ strlcat(imsg.contents, "nameserver ", MAXRESOLVCONFSIZE);
+ strlcat(imsg.contents, p, MAXRESOLVCONFSIZE);
+ strlcat(imsg.contents, "\n", MAXRESOLVCONFSIZE);
}
- hdr.code = IMSG_NEW_RESOLV_CONF;
- hdr.len = sizeof(hdr) +
- sizeof(len) + strlen(contents);
-
- buf = buf_open(hdr.len);
- buf_add(buf, &hdr, sizeof(hdr));
+ rslt = imsg_compose(unpriv_ibuf, IMSG_NEW_RESOLV_CONF, 0, 0, -1, &imsg,
+ sizeof(imsg));
- len = strlen(contents);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, contents, len);
-
- buf_close(privfd, buf);
-
- free(contents);
+ if (rslt == -1)
+ warning("new_resolv_conf: imsg_compose: %m");
}
void
-priv_resolv_conf(char *contents)
+priv_resolv_conf(struct imsg_resolv_conf *imsg)
{
ssize_t n;
int conffd, tailfd, tailn;
@@ -1833,15 +1840,15 @@ priv_resolv_conf(char *contents)
return;
}
- if (contents) {
- n = write(conffd, contents, strlen(contents));
+ if (strlen(imsg->contents)) {
+ n = write(conffd, imsg->contents, strlen(imsg->contents));
if (n == -1)
note("Couldn't write contents to resolv.conf: %m");
else if (n == 0)
note("Couldn't write contents to resolv.conf");
- else if (n < strlen(contents))
+ else if (n < strlen(imsg->contents))
note("Short contents write to resolv.conf (%zd vs %zd)",
- n, strlen(contents));
+ n, strlen(imsg->contents));
}
tailfd = open("/etc/resolv.conf.tail", O_RDONLY);
@@ -1871,7 +1878,7 @@ priv_resolv_conf(char *contents)
free(buf);
}
- if ((!contents || strlen(contents) == 0) && (tailn < 1 || n < 1)) {
+ if ((strlen(imsg->contents) == 0) && (tailn < 1 || n < 1)) {
note("No contents for resolv.conf");
unlink("/etc/resolv.conf");
close(conffd);
@@ -1988,3 +1995,17 @@ clone_lease(struct client_lease *oldlease)
return (newlease);
}
+
+void
+socket_nonblockmode(int fd)
+{
+ int flags;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ error("fcntl F_GETF: %m");
+
+ flags |= O_NONBLOCK;
+
+ if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
+ error("fcntl F_SETFL: %m");
+}
diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h
index 4a34af62311..a3b2bcdb1b2 100644
--- a/sbin/dhclient/dhcpd.h
+++ b/sbin/dhclient/dhcpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcpd.h,v 1.92 2012/11/14 15:47:41 krw Exp $ */
+/* $OpenBSD: dhcpd.h,v 1.93 2012/11/23 15:25:47 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -191,7 +191,7 @@ struct dhcp_timeout {
extern struct interface_info *ifi;
extern struct client_state *client;
extern struct client_config *config;
-extern int privfd;
+extern struct imsgbuf *unpriv_ibuf;
extern struct in_addr deleting;
extern struct in_addr adding;
@@ -295,8 +295,6 @@ void go_daemon(void);
void routehandler(void);
-void priv_resolv_conf(char *);
-
/* packet.c */
void assemble_hw_header(unsigned char *, int *, struct hardware *);
void assemble_udp_ip_header(unsigned char *, int *, u_int32_t, u_int32_t,
@@ -320,13 +318,9 @@ void parse_reject_statement(FILE *);
/* kroute.c */
void delete_addresses(char *, int);
void delete_address(char *, int, struct in_addr);
-void priv_delete_address(char *, int, struct in_addr);
void add_address(char *, int, struct in_addr, struct in_addr);
-void priv_add_address(char *, int, struct in_addr, struct in_addr);
void flush_routes_and_arp_cache(int);
-void priv_flush_routes_and_arp_cache(int);
void add_default_route(int, struct in_addr, struct in_addr);
-void priv_add_default_route(int, struct in_addr, struct in_addr);
diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c
index 3b0d17128f9..cd73f79d7d1 100644
--- a/sbin/dhclient/dispatch.c
+++ b/sbin/dhclient/dispatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dispatch.c,v 1.65 2012/11/08 21:32:55 krw Exp $ */
+/* $OpenBSD: dispatch.c,v 1.66 2012/11/23 15:25:47 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -40,6 +40,7 @@
*/
#include "dhcpd.h"
+#include "privsep.h"
#include <sys/ioctl.h>
@@ -154,10 +155,13 @@ another:
fds[0].fd = ifi->rfdesc;
fds[1].fd = routefd; /* Could be -1, which will be ignored. */
- fds[2].fd = privfd;
+ fds[2].fd = unpriv_ibuf->fd;
fds[0].events = fds[1].events = fds[2].events = POLLIN;
- /* Wait for a packet or a timeout or privfd ... XXX */
+ if (unpriv_ibuf->w.queued)
+ fds[2].events |= POLLOUT;
+
+ /* Wait for a packet or a timeout or unpriv_ibuf->fd ... XXX */
count = poll(fds, 3, to_msec);
/* Not likely to be transitory... */
@@ -176,6 +180,10 @@ another:
if (ifi)
routehandler();
}
+ if (fds[2].revents & POLLOUT) {
+ if (msgbuf_write(&unpriv_ibuf->w) == -1)
+ error("pipe write error to [priv]");
+ }
if ((fds[2].revents & (POLLIN | POLLHUP))) {
error("lost connection to [priv]");
}
diff --git a/sbin/dhclient/kroute.c b/sbin/dhclient/kroute.c
index a991f7574c2..03b201cebda 100644
--- a/sbin/dhclient/kroute.c
+++ b/sbin/dhclient/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.18 2012/11/17 10:39:24 krw Exp $ */
+/* $OpenBSD: kroute.c,v 1.19 2012/11/23 15:25:47 krw Exp $ */
/*
* Copyright 2012 Kenneth R Westerback <krw@openbsd.org>
@@ -36,26 +36,26 @@
void
flush_routes_and_arp_cache(int rdomain)
{
- size_t len;
- struct imsg_hdr hdr;
- struct buf *buf;
+ struct imsg_flush_routes imsg;
+ int rslt;
- hdr.code = IMSG_FLUSH_ROUTES;
- hdr.len = sizeof(hdr) +
- sizeof(len) + sizeof(rdomain);
+ memset(&imsg, 0, sizeof(imsg));
- buf = buf_open(hdr.len);
- buf_add(buf, &hdr, sizeof(hdr));
+ imsg.rdomain = rdomain;
- len = sizeof(rdomain);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, &rdomain, len);
+ rslt = imsg_compose(unpriv_ibuf, IMSG_FLUSH_ROUTES, 0, 0, -1,
+ &imsg, sizeof(imsg));
+ if (rslt == -1)
+ warning("flush_routes_and_arp_cache: imsg_compose: %m");
- buf_close(privfd, buf);
+ /* Do flush to maximize chances of cleaning up routes on exit. */
+ rslt = imsg_flush(unpriv_ibuf);
+ if (rslt == -1)
+ warning("flush_routes_and_arp_cache: imsg_flush: %m");
}
void
-priv_flush_routes_and_arp_cache(int rdomain)
+priv_flush_routes_and_arp_cache(struct imsg_flush_routes *imsg)
{
struct sockaddr *rti_info[RTAX_MAX];
int mib[7];
@@ -74,10 +74,10 @@ priv_flush_routes_and_arp_cache(int rdomain)
mib[3] = 0;
mib[4] = NET_RT_DUMP;
mib[5] = 0;
- mib[6] = rdomain;
+ mib[6] = imsg->rdomain;
if (sysctl(mib, 7, NULL, &needed, NULL, 0) == -1) {
- if (rdomain != 0 && errno == EINVAL)
+ if (imsg->rdomain != 0 && errno == EINVAL)
return;
error("could not get routes");
}
@@ -155,7 +155,7 @@ priv_flush_routes_and_arp_cache(int rdomain)
rtm->rtm_type = RTM_DELETE;
rtm->rtm_seq = seqno;
- rtm->rtm_tableid = rdomain;
+ rtm->rtm_tableid = imsg->rdomain;
rlen = write(s, next, rtm->rtm_msglen);
if (rlen == -1) {
@@ -185,40 +185,26 @@ priv_flush_routes_and_arp_cache(int rdomain)
* depending on the contents of the gateway parameter.
*/
void
-add_default_route(int rdomain, struct in_addr addr,
- struct in_addr gateway)
+add_default_route(int rdomain, struct in_addr addr, struct in_addr gateway)
{
- size_t len;
- struct imsg_hdr hdr;
- struct buf *buf;
+ struct imsg_add_default_route imsg;
+ int rslt;
- hdr.code = IMSG_ADD_DEFAULT_ROUTE;
- hdr.len = sizeof(hdr) +
- sizeof(len) + sizeof(rdomain) +
- sizeof(len) + sizeof(addr) +
- sizeof(len) + sizeof(gateway);
+ memset(&imsg, 0, sizeof(imsg));
- buf = buf_open(hdr.len);
- buf_add(buf, &hdr, sizeof(hdr));
+ imsg.rdomain = rdomain;
+ imsg.addr = addr;
+ imsg.gateway = gateway;
- len = sizeof(rdomain);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, &rdomain, len);
+ rslt = imsg_compose(unpriv_ibuf, IMSG_ADD_DEFAULT_ROUTE, 0, 0, -1,
+ &imsg, sizeof(imsg));
- len = sizeof(addr);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, &addr, len);
-
- len = sizeof(gateway);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, &gateway, len);
-
- buf_close(privfd, buf);
+ if (rslt == -1)
+ warning("add_default_route: imsg_compose: %m");
}
void
-priv_add_default_route(int rdomain, struct in_addr addr,
- struct in_addr router)
+priv_add_default_route(struct imsg_add_default_route *imsg)
{
struct rt_msghdr rtm;
struct sockaddr_in dest, gateway, mask;
@@ -239,7 +225,7 @@ priv_add_default_route(int rdomain, struct in_addr addr,
rtm.rtm_version = RTM_VERSION;
rtm.rtm_type = RTM_ADD;
- rtm.rtm_tableid = rdomain;
+ rtm.rtm_tableid = imsg->rdomain;
rtm.rtm_priority = 0;
rtm.rtm_msglen = sizeof(rtm);
@@ -265,10 +251,10 @@ priv_add_default_route(int rdomain, struct in_addr addr,
*/
memset(&gateway, 0, sizeof(gateway));
- if (bcmp(&router, &addr, sizeof(addr)) != 0) {
+ if (bcmp(&imsg->gateway, &imsg->addr, sizeof(imsg->addr)) != 0) {
gateway.sin_len = sizeof(gateway);
gateway.sin_family = AF_INET;
- gateway.sin_addr.s_addr = router.s_addr;
+ gateway.sin_addr.s_addr = imsg->gateway.s_addr;
rtm.rtm_flags |= RTF_GATEWAY | RTF_STATIC;
rtm.rtm_addrs |= RTA_GATEWAY;
@@ -360,39 +346,27 @@ delete_addresses(char *ifname, int rdomain)
void
delete_address(char *ifname, int rdomain, struct in_addr addr)
{
- size_t len;
- struct imsg_hdr hdr;
- struct buf *buf;
+ struct imsg_delete_address imsg;
+ int rslt;
+
+ memset(&imsg, 0, sizeof(imsg));
/* Note the address we are deleting for RTM_DELADDR filtering! */
deleting.s_addr = addr.s_addr;
- hdr.code = IMSG_DELETE_ADDRESS;
- hdr.len = sizeof(hdr) +
- sizeof(len) + strlen(ifname) +
- sizeof(len) + sizeof(rdomain) +
- sizeof(len) + sizeof(addr);
-
- buf = buf_open(hdr.len);
- buf_add(buf, &hdr, sizeof(hdr));
-
- len = strlen(ifname);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, ifname, len);
-
- len = sizeof(rdomain);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, &rdomain, len);
+ strlcpy(imsg.ifname, ifname, sizeof(imsg.ifname));
+ imsg.rdomain = rdomain;
+ imsg.addr = addr;
- len = sizeof(addr);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, &addr, len);
+ rslt = imsg_compose(unpriv_ibuf, IMSG_DELETE_ADDRESS, 0, 0 , -1, &imsg,
+ sizeof(imsg));
- buf_close(privfd, buf);
+ if (rslt == -1)
+ warning("delete_address: imsg_compose: %m");
}
void
-priv_delete_address(char *ifname, int rdomain, struct in_addr addr)
+priv_delete_address(struct imsg_delete_address *imsg)
{
struct ifaliasreq ifaliasreq;
struct rt_msghdr rtm;
@@ -409,16 +383,17 @@ priv_delete_address(char *ifname, int rdomain, struct in_addr addr)
error("socket open failed: %m");
memset(&ifaliasreq, 0, sizeof(ifaliasreq));
- strncpy(ifaliasreq.ifra_name, ifname, sizeof(ifaliasreq.ifra_name));
+ strncpy(ifaliasreq.ifra_name, imsg->ifname,
+ sizeof(ifaliasreq.ifra_name));
in = (struct sockaddr_in *)&ifaliasreq.ifra_addr;
in->sin_family = AF_INET;
in->sin_len = sizeof(ifaliasreq.ifra_addr);
- in->sin_addr.s_addr = addr.s_addr;
+ in->sin_addr.s_addr = imsg->addr.s_addr;
/* SIOCDIFADDR will result in a RTM_DELADDR message we must catch! */
if (ioctl(s, SIOCDIFADDR, &ifaliasreq) == -1) {
- warning("SIOCDIFADDR failed (%s): %m", inet_ntoa(addr));
+ warning("SIOCDIFADDR failed (%s): %m", inet_ntoa(imsg->addr));
close(s);
return;
}
@@ -438,7 +413,7 @@ priv_delete_address(char *ifname, int rdomain, struct in_addr addr)
rtm.rtm_version = RTM_VERSION;
rtm.rtm_type = RTM_DELETE;
- rtm.rtm_tableid = rdomain;
+ rtm.rtm_tableid = imsg->rdomain;
rtm.rtm_priority = 0;
rtm.rtm_msglen = sizeof(rtm);
@@ -451,7 +426,7 @@ priv_delete_address(char *ifname, int rdomain, struct in_addr addr)
dest.sin_len = sizeof(dest);
dest.sin_family = AF_INET;
- dest.sin_addr.s_addr = addr.s_addr;
+ dest.sin_addr.s_addr = imsg->addr.s_addr;
rtm.rtm_addrs |= RTA_DST;
rtm.rtm_msglen += sizeof(dest);
@@ -491,44 +466,28 @@ void
add_address(char *ifname, int rdomain, struct in_addr addr,
struct in_addr mask)
{
- struct buf *buf;
- size_t len;
- struct imsg_hdr hdr;
+ struct imsg_add_address imsg;
+ int rslt;
+
+ memset(&imsg, 0, sizeof(imsg));
+ /* Note the address we are adding for RTM_NEWADDR filtering! */
adding = addr;
- hdr.code = IMSG_ADD_ADDRESS;
- hdr.len = sizeof(hdr) +
- sizeof(len) + strlen(ifname) +
- sizeof(len) + sizeof(rdomain) +
- sizeof(len) + sizeof(addr) +
- sizeof(len) + sizeof(mask);
+ strlcpy(imsg.ifname, ifname, sizeof(imsg.ifname));
+ imsg.rdomain = rdomain;
+ imsg.addr = addr;
+ imsg.mask = mask;
+
+ rslt = imsg_compose(unpriv_ibuf, IMSG_ADD_ADDRESS, 0, 0, -1, &imsg,
+ sizeof(imsg));
- buf = buf_open(hdr.len);
- buf_add(buf, &hdr, sizeof(hdr));
-
- len = strlen(ifname);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, ifname, len);
-
- len = sizeof(rdomain);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, &rdomain, len);
-
- len = sizeof(addr);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, &addr, len);
-
- len = sizeof(mask);
- buf_add(buf, &len, sizeof(len));
- buf_add(buf, &mask, len);
-
- buf_close(privfd, buf);
+ if (rslt == -1)
+ warning("add_address: imsg_compose: %m");
}
void
-priv_add_address(char *ifname, int rdomain, struct in_addr addr,
- struct in_addr mask)
+priv_add_address(struct imsg_add_address *imsg)
{
struct ifaliasreq ifaliasreq;
struct rt_msghdr rtm;
@@ -546,24 +505,25 @@ priv_add_address(char *ifname, int rdomain, struct in_addr addr,
error("socket open failed: %m");
memset(&ifaliasreq, 0, sizeof(ifaliasreq));
- strncpy(ifaliasreq.ifra_name, ifname, sizeof(ifaliasreq.ifra_name));
+ strncpy(ifaliasreq.ifra_name, imsg->ifname,
+ sizeof(ifaliasreq.ifra_name));
/* The actual address in ifra_addr. */
in = (struct sockaddr_in *)&ifaliasreq.ifra_addr;
in->sin_family = AF_INET;
in->sin_len = sizeof(ifaliasreq.ifra_addr);
- in->sin_addr.s_addr = addr.s_addr;
+ in->sin_addr.s_addr = imsg->addr.s_addr;
/* And the netmask in ifra_mask. */
in = (struct sockaddr_in *)&ifaliasreq.ifra_mask;
in->sin_family = AF_INET;
in->sin_len = sizeof(ifaliasreq.ifra_mask);
- memcpy(&in->sin_addr.s_addr, &mask, sizeof(mask));
+ memcpy(&in->sin_addr.s_addr, &imsg->mask, sizeof(imsg->mask));
/* No need to set broadcast address. Kernel can figure it out. */
if (ioctl(s, SIOCAIFADDR, &ifaliasreq) == -1)
- warning("SIOCAIFADDR failed (%s): %m", inet_ntoa(addr));
+ warning("SIOCAIFADDR failed (%s): %m", inet_ntoa(imsg->addr));
close(s);
@@ -580,7 +540,7 @@ priv_add_address(char *ifname, int rdomain, struct in_addr addr,
rtm.rtm_version = RTM_VERSION;
rtm.rtm_type = RTM_ADD;
- rtm.rtm_tableid = rdomain;
+ rtm.rtm_tableid = imsg->rdomain;
rtm.rtm_priority = 0;
rtm.rtm_msglen = sizeof(rtm);
@@ -593,7 +553,7 @@ priv_add_address(char *ifname, int rdomain, struct in_addr addr,
dest.sin_len = sizeof(dest);
dest.sin_family = AF_INET;
- dest.sin_addr.s_addr = addr.s_addr;
+ dest.sin_addr.s_addr = imsg->addr.s_addr;
rtm.rtm_addrs |= RTA_DST;
rtm.rtm_msglen += sizeof(dest);
diff --git a/sbin/dhclient/privsep.c b/sbin/dhclient/privsep.c
index 5ab2c2a6759..e6f6dd0fb86 100644
--- a/sbin/dhclient/privsep.c
+++ b/sbin/dhclient/privsep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: privsep.c,v 1.23 2012/11/14 15:47:41 krw Exp $ */
+/* $OpenBSD: privsep.c,v 1.24 2012/11/23 15:25:47 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -19,311 +19,68 @@
#include "dhcpd.h"
#include "privsep.h"
-struct buf *
-buf_open(size_t len)
-{
- struct buf *buf;
-
- if ((buf = calloc(1, sizeof(struct buf))) == NULL)
- error("buf_open: %m");
- if ((buf->buf = malloc(len)) == NULL) {
- free(buf);
- error("buf_open: %m");
- }
- buf->size = len;
-
- return (buf);
-}
-
-void
-buf_add(struct buf *buf, void *data, size_t len)
-{
- if (len == 0)
- return;
-
- if (buf->wpos + len > buf->size)
- error("buf_add: %m");
-
- memcpy(buf->buf + buf->wpos, data, len);
- buf->wpos += len;
-}
-
-void
-buf_close(int sock, struct buf *buf)
-{
- ssize_t n;
-
- do {
- n = write(sock, buf->buf + buf->rpos, buf->size - buf->rpos);
- if (n == 0) /* connection closed */
- error("buf_close (connection closed)");
- if (n != -1 && n < buf->size - buf->rpos)
- error("buf_close (short write): %m");
-
- } while (n == -1 && (errno == EAGAIN || errno == EINTR));
-
- if (n == -1)
- error("buf_close: %m");
-
- free(buf->buf);
- free(buf);
-}
-
-void
-buf_read(int sock, void *buf, size_t nbytes)
-{
- ssize_t n;
-
- do {
- n = read(sock, buf, nbytes);
- if (n == 0) { /* connection closed */
-#ifdef DEBUG
- debug("buf_read (connection closed)");
-#endif
- exit(1);
- }
- if (n != -1 && n < nbytes)
- error("buf_read (short read): %m");
- } while (n == -1 && (errno == EINTR || errno == EAGAIN));
-
- if (n == -1)
- error("buf_read: %m");
-}
+#include <sys/queue.h>
+#include <sys/uio.h>
void
-dispatch_imsg(int fd)
+dispatch_imsg(struct imsgbuf *ibuf)
{
- struct imsg_hdr hdr;
- struct in_addr *addr, *mask, *gateway;
- char *ifname, *contents;
- size_t totlen, len;
- int rdomain;
-
- buf_read(fd, &hdr, sizeof(hdr));
-
- switch (hdr.code) {
- case IMSG_DELETE_ADDRESS:
- totlen = sizeof(hdr);
- ifname = NULL;
- addr = NULL;
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_DELETE_ADDRESS missing ifname length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_DELETE_ADDRESS invalid ifname length");
- } else if (len > 0) {
- if (hdr.len < totlen + len)
- error("IMSG_DELETE_ADDRESS short ifname");
- if ((ifname = calloc(1, len + 1)) == NULL)
- error("%m");
- buf_read(fd, ifname, len);
- totlen += len;
- } else
- error("IMSG_DELETE_ADDRESS ifname missing");
-
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_DELETE_ADDRESS missing rdomain length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_DELETE_ADDRESS invalid rdomain length");
- } else if (len > 0) {
- if (hdr.len < totlen + len)
- error("IMSG_DELETE_ADDRESS short rdomain");
- buf_read(fd, &rdomain, len);
- totlen += len;
- } else
- error("IMSG_DELETE_ADDRESS rdomain missing");
-
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_DELETE_ADDRESS missing addr length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_DELETE_ADDRESS invalid addr");
- } else if (len == sizeof(*addr)) {
- if ((addr = calloc(1, len)) == NULL)
- error("%m");
- buf_read(fd, addr, len);
- totlen += len;
- } else {
- error("IMSG_DELETE_ADDRESS addr missing %zu", len);
- }
-
- priv_delete_address(ifname, rdomain, *addr);
- free(ifname);
- free(addr);
- break;
-
- case IMSG_ADD_ADDRESS:
- totlen = sizeof(hdr);
- ifname = NULL;
- addr = NULL;
- mask = NULL;
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_ADD_ADDRESS missing ifname length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_ADD_ADDRESS invalid ifname length");
- } else if (len > 0) {
- if (hdr.len < totlen + len)
- error("IMSG_ADD_ADDRESS short ifname");
- if ((ifname = calloc(1, len + 1)) == NULL)
- error("%m");
- buf_read(fd, ifname, len);
- totlen += len;
- } else
- error("IMSG_ADD_ADDRESS ifname missing");
-
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_ADD_ADDRESS missing rdomain length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_ADD_ADDRESS invalid rdomain length");
- } else if (len > 0) {
- if (hdr.len < totlen + len)
- error("IMSG_ADD_ADDRESS short rdomain");
- buf_read(fd, &rdomain, len);
- totlen += len;
- } else
- error("IMSG_ADD_ADDRESS rdomain missing");
-
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_ADD_ADDRESS missing addr length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_ADD_ADDRESS invalid addr");
- } else if (len == sizeof(*addr)) {
- if ((addr = calloc(1, len)) == NULL)
- error("%m");
- buf_read(fd, addr, len);
- totlen += len;
- } else {
- error("IMSG_ADD_ADDRESS addr missing %zu", len);
- }
-
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_ADD_ADDRESS missing mask length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- mask = NULL;
- if (len == SIZE_T_MAX) {
- error("IMSG_ADD_ADDRESS invalid mask");
- } else if (len == sizeof(*mask)) {
- if ((mask = calloc(1, len)) == NULL)
- error("%m");
- buf_read(fd, mask, len);
- totlen += len;
- } else {
- error("IMSG_ADD_ADDRESS mask missing %zu", len);
- }
-
- priv_add_address(ifname, rdomain, *addr, *mask);
- free(ifname);
- free(addr);
- free(mask);
- break;
-
- case IMSG_FLUSH_ROUTES:
- totlen = sizeof(hdr);
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_FLUSH_ROUTES missing rdomain length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_FLUSH_ROUTES invalid rdomain length");
- } else if (len > 0) {
- if (hdr.len < totlen + len)
- error("IMSG_FLUSH_ROUTES short rdomain");
- buf_read(fd, &rdomain, len);
- totlen += len;
- } else
- error("IMSG_FLUSH_ROUTES rdomain missing");
-
- priv_flush_routes_and_arp_cache(rdomain);
- break;
-
- case IMSG_ADD_DEFAULT_ROUTE:
- totlen = sizeof(hdr);
- addr = NULL;
- gateway = NULL;
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_ADD_DEFAULT_ROUTE missing rdomain length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_ADD_DEFAULT_ROUTE invalid rdomain length");
- } else if (len > 0) {
- if (hdr.len < totlen + len)
- error("IMSG_FLUSH_ROUTES short rdomain");
- buf_read(fd, &rdomain, len);
- totlen += len;
- } else
- error("IMSG_ADD_DEFAULT_ROUTE rdomain missing");
-
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_ADD_DEFAULT_ROUTE missing addr length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_ADD_DEFAULT_ROUTE invalid addr");
- } else if (len == sizeof(*addr)) {
- if ((addr = calloc(1, len)) == NULL)
- error("%m");
- buf_read(fd, addr, len);
- totlen += len;
- } else {
- error("IMSG_ADD_DEFAULT_ROUTE addr missing %zu",
- len);
- }
-
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_ADD_DEFAULT_ROUTE missing gateway length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_ADD_DEFAULT_ROUTE invalid gateway");
- } else if (len == sizeof(*gateway)) {
- if ((gateway = calloc(1, len)) == NULL)
- error("%m");
- buf_read(fd, gateway, len);
- totlen += len;
- } else {
- error("IMSG_ADD_DEFAULT_ROUTE gateway missing %zu",
- len);
- }
-
- priv_add_default_route(rdomain, *addr, *gateway);
- free(addr);
- free(gateway);
- break;
- case IMSG_NEW_RESOLV_CONF:
- totlen = sizeof(hdr);
- contents = NULL;
-
- if (hdr.len < totlen + sizeof(len))
- error("IMSG_NEW_RESOLV_CONF missing contents length");
- buf_read(fd, &len, sizeof(len));
- totlen += sizeof(len);
- if (len == SIZE_T_MAX) {
- error("IMSG_NEW_RESOLV_CONF invalid contents length");
- } else if (len > 0) {
- if (hdr.len < totlen + len)
- error("IMSG_NEW_RESOLV_CONF short contents");
- if ((contents = calloc(1, len + 1)) == NULL)
- error("%m");
- buf_read(fd, contents, len);
- totlen += len;
+ struct imsg imsg;
+ ssize_t n;
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ error("dispatch_imsg: imsg_get failure: %m");
+
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ case IMSG_DELETE_ADDRESS:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct imsg_delete_address))
+ warning("bad IMSG_DELETE_ADDRESS");
+ else
+ priv_delete_address(imsg.data);
+ break;
+
+ case IMSG_ADD_ADDRESS:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct imsg_add_address))
+ warning("bad IMSG_ADD_ADDRESS");
+ else
+ priv_add_address(imsg.data);
+ break;
+
+ case IMSG_FLUSH_ROUTES:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct imsg_flush_routes))
+ warning("bad IMSG_FLUSH_ROUTES");
+ else
+ priv_flush_routes_and_arp_cache(imsg.data);
+ break;
+
+ case IMSG_ADD_DEFAULT_ROUTE:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct imsg_add_default_route))
+ warning("bad IMSG_ADD_DEFAULT_ROUTE");
+ else
+ priv_add_default_route(imsg.data);
+ break;
+
+ case IMSG_NEW_RESOLV_CONF:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct imsg_resolv_conf))
+ warning("bad IMSG_NEW_RESOLV_CONF");
+ else
+ priv_resolv_conf(imsg.data);
+ break;
+
+ default:
+ warning("received unknown message, code %d",
+ imsg.hdr.type);
}
- priv_resolv_conf(contents);
- free(contents);
- break;
- default:
- error("received unknown message, code %d", hdr.code);
+ imsg_free(&imsg);
}
}
diff --git a/sbin/dhclient/privsep.h b/sbin/dhclient/privsep.h
index 59300e00f53..a72294bb910 100644
--- a/sbin/dhclient/privsep.h
+++ b/sbin/dhclient/privsep.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: privsep.h,v 1.6 2012/10/30 18:39:44 krw Exp $ */
+/* $OpenBSD: privsep.h,v 1.7 2012/11/23 15:25:47 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -16,14 +16,13 @@
* OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/types.h>
+#include <arpa/inet.h>
-struct buf {
- u_char *buf;
- size_t size;
- size_t wpos;
- size_t rpos;
-};
+#include <imsg.h>
+
+#define MAXRESOLVCONFSIZE 2048
+
+extern struct imsgbuf *ibuf;
enum imsg_code {
IMSG_NONE,
@@ -34,13 +33,36 @@ enum imsg_code {
IMSG_NEW_RESOLV_CONF
};
-struct imsg_hdr {
- enum imsg_code code;
- size_t len;
+struct imsg_delete_address {
+ char ifname[IFNAMSIZ];
+ int rdomain;
+ struct in_addr addr;
+};
+
+struct imsg_add_address {
+ char ifname[IFNAMSIZ];
+ int rdomain;
+ struct in_addr addr;
+ struct in_addr mask;
+};
+
+struct imsg_flush_routes {
+ int rdomain;
+};
+
+struct imsg_add_default_route {
+ int rdomain;
+ struct in_addr addr;
+ struct in_addr gateway;
+};
+
+struct imsg_resolv_conf {
+ char contents[MAXRESOLVCONFSIZE];
};
-struct buf *buf_open(size_t);
-void buf_add(struct buf *, void *, size_t);
-void buf_close(int, struct buf *);
-void buf_read(int, void *, size_t);
-void dispatch_imsg(int);
+void dispatch_imsg(struct imsgbuf *);
+void priv_resolv_conf(struct imsg_resolv_conf *);
+void priv_delete_address(struct imsg_delete_address *);
+void priv_add_address(struct imsg_add_address *);
+void priv_flush_routes_and_arp_cache(struct imsg_flush_routes *);
+void priv_add_default_route(struct imsg_add_default_route *);