summaryrefslogtreecommitdiff
path: root/sbin/dhclient
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2019-02-12 16:50:45 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2019-02-12 16:50:45 +0000
commit7a0d01dae60b2c447992a75f8d980fbe8d553e07 (patch)
treeb2bd1b9f6750c07c138ddb257476ce72bbe9d7ee /sbin/dhclient
parent534078fcd0dd34526a5c00b7ccf9ca553b63070c (diff)
Restructure code to simplifiy imsg communications, further separating
DHCP knowledge and interface manipulation. Unprivileged process now sends proposal derived from the accepted lease to the privileged process rather than individual interface manipulation requests. The only intended functional change is that /etc/resolv.conf.tail is not re-read each time a new proposal is implemented, rather than once at dhclient startup.
Diffstat (limited to 'sbin/dhclient')
-rw-r--r--sbin/dhclient/clparse.c41
-rw-r--r--sbin/dhclient/dhclient.c34
-rw-r--r--sbin/dhclient/dhcpd.h13
-rw-r--r--sbin/dhclient/kroute.c962
-rw-r--r--sbin/dhclient/privsep.c86
-rw-r--r--sbin/dhclient/privsep.h57
6 files changed, 562 insertions, 631 deletions
diff --git a/sbin/dhclient/clparse.c b/sbin/dhclient/clparse.c
index 80ce22da5d0..24ee95634fa 100644
--- a/sbin/dhclient/clparse.c
+++ b/sbin/dhclient/clparse.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clparse.c,v 1.182 2019/01/26 23:26:20 krw Exp $ */
+/* $OpenBSD: clparse.c,v 1.183 2019/02/12 16:50:44 krw Exp $ */
/* Parser for dhclient config and lease files. */
@@ -79,7 +79,6 @@ int parse_reject_statement(FILE *);
void apply_ignore_list(char *);
void set_default_client_identifier(struct ether_addr *);
void set_default_hostname(void);
-void read_resolv_conf_tail(void);
void
init_config(void)
@@ -174,7 +173,6 @@ read_conf(char *name, char *ignore_list, struct ether_addr *hwaddr)
set_default_client_identifier(hwaddr);
set_default_hostname();
apply_ignore_list(ignore_list);
- read_resolv_conf_tail();
}
/*
@@ -983,40 +981,3 @@ set_default_hostname(void)
opt->len = strlen(opt->data);
}
}
-
-void
-read_resolv_conf_tail(void)
-{
- struct stat sb;
- const char *tail_path = "/etc/resolv.conf.tail";
- ssize_t tailn;
- int tailfd;
-
- if (config->resolv_tail != NULL) {
- free(config->resolv_tail);
- config->resolv_tail = NULL;
- }
-
- tailfd = open(tail_path, O_RDONLY);
- if (tailfd == -1) {
- if (errno != ENOENT)
- fatal("open(%s)", tail_path);
- } else if (fstat(tailfd, &sb) == -1) {
- fatal("fstat(%s)", tail_path);
- } else {
- if (sb.st_size > 0 && sb.st_size < LLONG_MAX) {
- config->resolv_tail = calloc(1, sb.st_size + 1);
- if (config->resolv_tail == NULL) {
- fatal("%s contents", tail_path);
- }
- tailn = read(tailfd, config->resolv_tail, sb.st_size);
- if (tailn == -1)
- fatal("read(%s)", tail_path);
- else if (tailn == 0)
- fatalx("got no data from %s", tail_path);
- else if (tailn != sb.st_size)
- fatalx("short read of %s", tail_path);
- }
- close(tailfd);
- }
-}
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index 21aba6c7972..6eb540c1e14 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.622 2019/01/22 03:48:24 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.623 2019/02/12 16:50:44 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -110,20 +110,6 @@ const struct in_addr inaddr_broadcast = { INADDR_BROADCAST };
struct client_config *config;
struct imsgbuf *unpriv_ibuf;
-struct proposal {
- uint8_t rtstatic[RTSTATIC_LEN];
- uint8_t rtsearch[RTSEARCH_LEN];
- uint8_t rtdns[RTDNS_LEN];
- struct in_addr ifa;
- struct in_addr netmask;
- unsigned int rtstatic_len;
- unsigned int rtsearch_len;
- unsigned int rtdns_len;
- int mtu;
- int addrs;
- int inits;
-};
-
void usage(void);
int res_hnok_list(const char *);
int addressinuse(char *, struct in_addr, char *);
@@ -913,7 +899,7 @@ dhcpnak(struct interface_info *ifi, const char *src)
}
log_debug("%s: DHCPNAK from %s", log_procname, src);
- delete_address(ifi->active->address);
+ revoke_proposal(ifi->configured);
/* XXX Do we really want to remove a NAK'd lease from the database? */
TAILQ_REMOVE(&ifi->lease_db, ifi->active, next);
@@ -975,19 +961,7 @@ bind_lease(struct interface_info *ifi)
ifi->configured = effective_proposal;
effective_proposal = NULL;
- set_resolv_conf(ifi->name,
- ifi->configured->rtsearch,
- ifi->configured->rtsearch_len,
- ifi->configured->rtdns,
- ifi->configured->rtdns_len);
-
- set_mtu(ifi->configured->inits, ifi->configured->mtu);
-
- set_address(ifi->name, ifi->configured->ifa, ifi->configured->netmask);
-
- set_routes(ifi->configured->ifa, ifi->configured->netmask,
- ifi->configured->rtstatic, ifi->configured->rtstatic_len);
-
+ propose(ifi->configured);
rslt = asprintf(&msg, "bound to %s from %s",
inet_ntoa(ifi->active->address),
(ifi->offer_src == NULL) ? "<unknown>" : ifi->offer_src);
@@ -2678,7 +2652,7 @@ release_lease(struct interface_info *ifi)
make_release(ifi, ifi->active);
send_release(ifi);
- delete_address(ifi->configured->ifa);
+ revoke_proposal(ifi->configured);
imsg_flush(unpriv_ibuf);
TAILQ_REMOVE(&ifi->lease_db, ifi->active, next);
diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h
index a1b0af7864f..5021e707239 100644
--- a/sbin/dhclient/dhcpd.h
+++ b/sbin/dhclient/dhcpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcpd.h,v 1.272 2019/01/26 23:26:20 krw Exp $ */
+/* $OpenBSD: dhcpd.h,v 1.273 2019/02/12 16:50:44 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -109,7 +109,6 @@ struct client_config {
time_t reboot_timeout;
time_t backoff_cutoff;
TAILQ_HEAD(, reject_elem) reject_list;
- char *resolv_tail;
char *filename;
char *server_name;
};
@@ -242,11 +241,7 @@ void read_lease_db(char *, struct client_lease_tq *);
/* kroute.c */
unsigned int extract_classless_route(uint8_t *, unsigned int,
in_addr_t *, in_addr_t *, in_addr_t *);
-void delete_address(struct in_addr);
-void set_resolv_conf(char *, uint8_t *, unsigned int,
- uint8_t *, unsigned int);
void write_resolv_conf(void);
-void set_mtu(int, uint16_t);
-void set_address(char *, struct in_addr, struct in_addr);
-void set_routes(struct in_addr, struct in_addr, uint8_t *,
- unsigned int);
+
+void propose(struct proposal *);
+void revoke_proposal(struct proposal *);
diff --git a/sbin/dhclient/kroute.c b/sbin/dhclient/kroute.c
index c8c52ff80b4..c2d4699a060 100644
--- a/sbin/dhclient/kroute.c
+++ b/sbin/dhclient/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.158 2019/01/26 23:14:36 krw Exp $ */
+/* $OpenBSD: kroute.c,v 1.159 2019/02/12 16:50:44 krw Exp $ */
/*
* Copyright 2012 Kenneth R Westerback <krw@openbsd.org>
@@ -51,13 +51,136 @@
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
-void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
-void add_route(struct in_addr, struct in_addr, struct in_addr, int);
-void flush_routes(uint8_t *, unsigned int);
-int delete_addresses(char *, struct in_addr, struct in_addr);
+int find_address(char *, struct in_addr, struct in_addr);
+void set_address(char *, int, struct in_addr, struct in_addr);
+void delete_address(char *, int, struct in_addr);
+
char *get_routes(int, size_t *);
+void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
unsigned int route_in_rtstatic(struct rt_msghdr *, uint8_t *, unsigned int);
+void flush_routes(int, int, int, uint8_t *, unsigned int);
+void add_route(char *, int, int, struct in_addr, struct in_addr,
+ struct in_addr, int);
+void set_routes(char *, int, int, int, struct in_addr,
+ struct in_addr, uint8_t *, unsigned int);
+
+int default_route_index(int, int);
+char *resolv_conf_tail(void);
+char *set_resolv_conf(char *, uint8_t *, unsigned int,
+ uint8_t *, unsigned int);
+
+void set_mtu(char *, int, uint16_t);
+
+/*
+ * find_address() attempts to find newaddr/newmask in the addresses configured
+ * on the named interface.
+ *
+ * If the new addr/mask is already present, return 0, else 1.
+ */
+int
+find_address(char *name, struct in_addr newaddr, struct in_addr newnetmask)
+{
+ struct in_addr addr, netmask;
+ struct ifaddrs *ifap, *ifa;
+
+ if (getifaddrs(&ifap) != 0)
+ fatal("getifaddrs");
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if ((ifa->ifa_flags & IFF_LOOPBACK) != 0 ||
+ (ifa->ifa_flags & IFF_POINTOPOINT) != 0 ||
+ ((ifa->ifa_flags & IFF_UP) == 0) ||
+ (ifa->ifa_addr->sa_family != AF_INET) ||
+ (strcmp(name, ifa->ifa_name) != 0))
+ continue;
+
+ memcpy(&addr,
+ &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
+ sizeof(addr));
+ memcpy(&netmask,
+ &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr,
+ sizeof(netmask));
+
+ if (addr.s_addr == newaddr.s_addr &&
+ netmask.s_addr == newnetmask.s_addr) {
+ freeifaddrs(ifap);
+ return 0;
+ }
+ }
+
+ freeifaddrs(ifap);
+ return 1;
+}
+
+/*
+ * set_address() is the equivalent of
+ *
+ * ifconfig <if> inet <addr> netmask <mask> broadcast <addr>
+ */
+void
+set_address(char *name, int ioctlfd, struct in_addr addr,
+ struct in_addr netmask)
+{
+ struct ifaliasreq ifaliasreq;
+ struct sockaddr_in *in;
+
+ if (find_address(name, addr, netmask) == 0)
+ return;
+
+ memset(&ifaliasreq, 0, sizeof(ifaliasreq));
+ strncpy(ifaliasreq.ifra_name, name, 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;
+
+ /* 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);
+ in->sin_addr.s_addr = netmask.s_addr;
+ /* No need to set broadcast address. Kernel can figure it out. */
+
+ if (ioctl(ioctlfd, SIOCAIFADDR, &ifaliasreq) == -1)
+ log_warn("%s: SIOCAIFADDR %s", log_procname,
+ inet_ntoa(addr));
+}
+
+void
+delete_address(char *name, int ioctlfd, struct in_addr addr)
+{
+ struct ifaliasreq ifaliasreq;
+ struct sockaddr_in *in;
+
+ /*
+ * Delete specified address on specified interface.
+ *
+ * Deleting the address also clears out arp entries.
+ */
+
+ memset(&ifaliasreq, 0, sizeof(ifaliasreq));
+ strncpy(ifaliasreq.ifra_name, name, 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;
+
+ /* SIOCDIFADDR will result in a RTM_DELADDR message we must catch! */
+ if (ioctl(ioctlfd, SIOCDIFADDR, &ifaliasreq) == -1) {
+ if (errno != EADDRNOTAVAIL)
+ log_warn("%s: SIOCDIFADDR %s", log_procname,
+ inet_ntoa(addr));
+ }
+}
+
+/*
+ * get_routes() returns all relevant routes currently configured, and the
+ * length of the buffer being returned.
+ */
char *
get_routes(int rdomain, size_t *len)
{
@@ -110,35 +233,91 @@ get_routes(int rdomain, size_t *len)
}
/*
- * [priv_]flush_routes do the equivalent of
- *
- * route -q -T $rdomain -n flush -inet -iface $interface
- * arp -dan
+ * get_rtaddrs() populates rti_info with pointers to the
+ * sockaddr's contained in a rtm message.
*/
void
-flush_routes(uint8_t *rtstatic, unsigned int rtstatic_len)
+get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
{
- struct imsg_flush_routes imsg;
- int rslt;
+ int i;
- if (rtstatic_len > sizeof(imsg.rtstatic))
- return;
+ for (i = 0; i < RTAX_MAX; i++) {
+ if (addrs & (1 << i)) {
+ rti_info[i] = sa;
+ sa = (struct sockaddr *)((char *)(sa) +
+ ROUNDUP(sa->sa_len));
+ } else
+ rti_info[i] = NULL;
+ }
+}
+/*
+ * route_in_rtstatic() finds the position of the route in *rtm withing
+ * the list of routes in rtstatic.
+ *
+ * If the route is not contained in rtstatic, return rtstatic_len.
+ */
+unsigned int
+route_in_rtstatic(struct rt_msghdr *rtm, uint8_t *rtstatic,
+ unsigned int rtstatic_len)
+{
+ struct sockaddr *rti_info[RTAX_MAX];
+ struct sockaddr *dst, *netmask, *gateway;
+ in_addr_t dstaddr, netmaskaddr, gatewayaddr;
+ in_addr_t rtstaticdstaddr, rtstaticnetmaskaddr;
+ in_addr_t rtstaticgatewayaddr;
+ unsigned int i, len;
- imsg.rtstatic_len = rtstatic_len;
- memcpy(&imsg.rtstatic, rtstatic, rtstatic_len);
+ get_rtaddrs(rtm->rtm_addrs,
+ (struct sockaddr *)((char *)(rtm) + rtm->rtm_hdrlen),
+ rti_info);
- rslt = imsg_compose(unpriv_ibuf, IMSG_FLUSH_ROUTES, 0, 0, -1, &imsg,
- sizeof(imsg));
- if (rslt == -1)
- log_warn("%s: imsg_compose(IMSG_FLUSH_ROUTES)", log_procname);
+ dst = rti_info[RTAX_DST];
+ netmask = rti_info[RTAX_NETMASK];
+ gateway = rti_info[RTAX_GATEWAY];
+
+ if (dst == NULL || netmask == NULL || gateway == NULL)
+ return rtstatic_len;
+
+ if (dst->sa_family != AF_INET || netmask->sa_family != AF_INET ||
+ gateway->sa_family != AF_INET)
+ return rtstatic_len;
+
+ dstaddr = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
+ netmaskaddr = ((struct sockaddr_in *)netmask)->sin_addr.s_addr;
+ gatewayaddr = ((struct sockaddr_in *)gateway)->sin_addr.s_addr;
+
+ dstaddr &= netmaskaddr;
+ i = 0;
+ while (i < rtstatic_len) {
+ len = extract_classless_route(&rtstatic[i], rtstatic_len - i,
+ &rtstaticdstaddr, &rtstaticnetmaskaddr,
+ &rtstaticgatewayaddr);
+ if (len == 0)
+ break;
+
+ if (dstaddr == rtstaticdstaddr &&
+ netmaskaddr == rtstaticnetmaskaddr &&
+ gatewayaddr == rtstaticgatewayaddr)
+ return i;
+
+ i += len;
+ }
+
+ return rtstatic_len;
}
+/*
+ * flush_routes() does the equivalent of
+ *
+ * route -q -T $rdomain -n flush -inet -iface $interface
+ * arp -dan
+ */
void
-priv_flush_routes(int index, int routefd, int rdomain,
- struct imsg_flush_routes *imsg)
+flush_routes(int index, int routefd, int rdomain,
+ uint8_t *rtstatic, unsigned int rtstatic_len)
{
static int seqno;
- char *lim, *buf = NULL, *next;
+ char *lim, *buf, *next;
struct rt_msghdr *rtm;
size_t len;
ssize_t rlen;
@@ -163,9 +342,8 @@ priv_flush_routes(int index, int routefd, int rdomain,
continue;
/* Don't bother deleting a route we're going to add. */
- pos = route_in_rtstatic(rtm, imsg->rtstatic,
- imsg->rtstatic_len);
- if (pos < imsg->rtstatic_len)
+ pos = route_in_rtstatic(rtm, rtstatic, rtstatic_len);
+ if (pos < rtstatic_len)
continue;
rtm->rtm_type = RTM_DELETE;
@@ -183,42 +361,88 @@ priv_flush_routes(int index, int routefd, int rdomain,
free(buf);
}
-unsigned int
-extract_classless_route(uint8_t *rtstatic, unsigned int rtstatic_len,
- in_addr_t *dest, in_addr_t *netmask, in_addr_t *gateway)
+/*
+ * add_route() adds a single route to the routing table.
+ */
+void
+add_route(char *name, int rdomain, int routefd, struct in_addr dest,
+ struct in_addr netmask, struct in_addr gateway, int flags)
{
- unsigned int bits, bytes, len;
+ char destbuf[INET_ADDRSTRLEN];
+ char maskbuf[INET_ADDRSTRLEN];
+ struct iovec iov[5];
+ struct rt_msghdr rtm;
+ struct sockaddr_in sadest, sagateway, samask;
+ int index, iovcnt = 0;
- if (rtstatic[0] > 32)
- return 0;
+ index = if_nametoindex(name);
+ if (index == 0)
+ return;
- bits = rtstatic[0];
- bytes = (bits + 7) / 8;
- len = 1 + bytes + sizeof(*gateway);
- if (len > rtstatic_len)
- return 0;
+ /* Build RTM header */
- if (dest != NULL)
- memcpy(dest, &rtstatic[1], bytes);
+ memset(&rtm, 0, sizeof(rtm));
- if (netmask != NULL) {
- if (bits == 0)
- *netmask = INADDR_ANY;
- else
- *netmask = htonl(0xffffffff << (32 - bits));
- if (dest != NULL)
- *dest &= *netmask;
- }
+ rtm.rtm_version = RTM_VERSION;
+ rtm.rtm_type = RTM_ADD;
+ rtm.rtm_index = index;
+ rtm.rtm_tableid = rdomain;
+ rtm.rtm_priority = RTP_NONE;
+ rtm.rtm_addrs = RTA_DST | RTA_NETMASK | RTA_GATEWAY;
+ rtm.rtm_flags = flags;
- if (gateway != NULL)
- memcpy(gateway, &rtstatic[1 + bytes], sizeof(*gateway));
+ rtm.rtm_msglen = sizeof(rtm);
+ iov[iovcnt].iov_base = &rtm;
+ iov[iovcnt++].iov_len = sizeof(rtm);
- return len;
+ /* Add the destination address. */
+ memset(&sadest, 0, sizeof(sadest));
+ sadest.sin_len = sizeof(sadest);
+ sadest.sin_family = AF_INET;
+ sadest.sin_addr.s_addr = dest.s_addr;
+
+ rtm.rtm_msglen += sizeof(sadest);
+ iov[iovcnt].iov_base = &sadest;
+ iov[iovcnt++].iov_len = sizeof(sadest);
+
+ /* Add the gateways address. */
+ memset(&sagateway, 0, sizeof(sagateway));
+ sagateway.sin_len = sizeof(sagateway);
+ sagateway.sin_family = AF_INET;
+ sagateway.sin_addr.s_addr = gateway.s_addr;
+
+ rtm.rtm_msglen += sizeof(sagateway);
+ iov[iovcnt].iov_base = &sagateway;
+ iov[iovcnt++].iov_len = sizeof(sagateway);
+
+ /* Add the network mask. */
+ memset(&samask, 0, sizeof(samask));
+ samask.sin_len = sizeof(samask);
+ samask.sin_family = AF_INET;
+ samask.sin_addr.s_addr = netmask.s_addr;
+
+ rtm.rtm_msglen += sizeof(samask);
+ iov[iovcnt].iov_base = &samask;
+ iov[iovcnt++].iov_len = sizeof(samask);
+
+ if (writev(routefd, iov, iovcnt) == -1) {
+ if (errno != EEXIST || log_getverbose() != 0) {
+ strlcpy(destbuf, inet_ntoa(dest),
+ sizeof(destbuf));
+ strlcpy(maskbuf, inet_ntoa(netmask),
+ sizeof(maskbuf));
+ log_warn("%s: add route %s/%s via %s", log_procname,
+ destbuf, maskbuf, inet_ntoa(gateway));
+ }
+ }
}
+/*
+ * set_routes() adds the routes contained in rtstatic to the routing table.
+ */
void
-set_routes(struct in_addr addr, struct in_addr addrmask, uint8_t *rtstatic,
- unsigned int rtstatic_len)
+set_routes(char *name, int index, int rdomain, int routefd, struct in_addr addr,
+ struct in_addr addrmask, uint8_t *rtstatic, unsigned int rtstatic_len)
{
const struct in_addr any = { INADDR_ANY };
const struct in_addr broadcast = { INADDR_BROADCAST };
@@ -226,7 +450,8 @@ set_routes(struct in_addr addr, struct in_addr addrmask, uint8_t *rtstatic,
in_addr_t addrnet, gatewaynet;
unsigned int i, len;
- flush_routes(rtstatic, rtstatic_len);
+ if (rtstatic_len <= RTLEN)
+ flush_routes(index, routefd, rdomain, rtstatic, rtstatic_len);
addrnet = addr.s_addr & addrmask.s_addr;
@@ -246,8 +471,8 @@ set_routes(struct in_addr addr, struct in_addr addrmask, uint8_t *rtstatic,
* route add -net $dest -netmask $netmask -cloning
* -iface $addr
*/
- add_route(dest, netmask, addr,
- RTF_STATIC | RTF_CLONING);
+ add_route(name, rdomain, routefd, dest, netmask,
+ addr, RTF_STATIC | RTF_CLONING);
} else if (netmask.s_addr == INADDR_ANY) {
/*
* DEFAULT ROUTE
@@ -271,8 +496,8 @@ set_routes(struct in_addr addr, struct in_addr addrmask, uint8_t *rtstatic,
* work".
*
*/
- add_route(gateway, broadcast, addr,
- RTF_STATIC | RTF_CLONING);
+ add_route(name, rdomain, routefd, gateway,
+ broadcast, addr, RTF_STATIC | RTF_CLONING);
}
if (memcmp(&gateway, &addr, sizeof(addr)) == 0) {
@@ -281,15 +506,16 @@ set_routes(struct in_addr addr, struct in_addr addrmask, uint8_t *rtstatic,
*
* route add default -iface $addr
*/
- add_route(any, any, gateway, RTF_STATIC);
+ add_route(name, rdomain, routefd, any, any,
+ gateway, RTF_STATIC);
} else {
/*
* DEFAULT ROUTE IS VIA GATEWAY
*
* route add default $gateway
*/
- add_route(any, any, gateway,
- RTF_STATIC | RTF_GATEWAY);
+ add_route(name, rdomain, routefd, any, any,
+ gateway, RTF_STATIC | RTF_GATEWAY);
}
} else {
/*
@@ -297,333 +523,15 @@ set_routes(struct in_addr addr, struct in_addr addrmask, uint8_t *rtstatic,
*
* route add -net $dest -netmask $netmask $gateway
*/
- add_route(dest, netmask, gateway,
- RTF_STATIC | RTF_GATEWAY);
- }
- }
-}
-
-/*
- * [priv_]add_route() add a single route to the routing table.
- */
-void
-add_route(struct in_addr dest, struct in_addr netmask, struct in_addr gateway,
- int flags)
-{
- struct imsg_add_route imsg;
- int rslt;
-
- imsg.dest = dest;
- imsg.gateway = gateway;
- imsg.netmask = netmask;
- imsg.flags = flags;
-
- rslt = imsg_compose(unpriv_ibuf, IMSG_ADD_ROUTE, 0, 0, -1,
- &imsg, sizeof(imsg));
- if (rslt == -1)
- log_warn("%s: imsg_compose(IMSG_ADD_ROUTE)", log_procname);
-}
-
-void
-priv_add_route(char *name, int rdomain, int routefd,
- struct imsg_add_route *imsg)
-{
- char destbuf[INET_ADDRSTRLEN];
- char maskbuf[INET_ADDRSTRLEN];
- struct iovec iov[5];
- struct rt_msghdr rtm;
- struct sockaddr_in dest, gateway, mask;
- int index, iovcnt = 0;
-
- index = if_nametoindex(name);
- if (index == 0)
- return;
-
- /* Build RTM header */
-
- memset(&rtm, 0, sizeof(rtm));
-
- rtm.rtm_version = RTM_VERSION;
- rtm.rtm_type = RTM_ADD;
- rtm.rtm_index = index;
- rtm.rtm_tableid = rdomain;
- rtm.rtm_priority = RTP_NONE;
- rtm.rtm_addrs = RTA_DST | RTA_NETMASK | RTA_GATEWAY;
- rtm.rtm_flags = imsg->flags;
-
- rtm.rtm_msglen = sizeof(rtm);
- iov[iovcnt].iov_base = &rtm;
- iov[iovcnt++].iov_len = sizeof(rtm);
-
- /* Add the destination address. */
- memset(&dest, 0, sizeof(dest));
- dest.sin_len = sizeof(dest);
- dest.sin_family = AF_INET;
- dest.sin_addr.s_addr = imsg->dest.s_addr;
-
- rtm.rtm_msglen += sizeof(dest);
- iov[iovcnt].iov_base = &dest;
- iov[iovcnt++].iov_len = sizeof(dest);
-
- /* Add the gateways address. */
- memset(&gateway, 0, sizeof(gateway));
- gateway.sin_len = sizeof(gateway);
- gateway.sin_family = AF_INET;
- gateway.sin_addr.s_addr = imsg->gateway.s_addr;
-
- rtm.rtm_msglen += sizeof(gateway);
- iov[iovcnt].iov_base = &gateway;
- iov[iovcnt++].iov_len = sizeof(gateway);
-
- /* Add the network mask. */
- memset(&mask, 0, sizeof(mask));
- mask.sin_len = sizeof(mask);
- mask.sin_family = AF_INET;
- mask.sin_addr.s_addr = imsg->netmask.s_addr;
-
- rtm.rtm_msglen += sizeof(mask);
- iov[iovcnt].iov_base = &mask;
- iov[iovcnt++].iov_len = sizeof(mask);
-
- if (writev(routefd, iov, iovcnt) == -1) {
- if (errno != EEXIST || log_getverbose() != 0) {
- strlcpy(destbuf, inet_ntoa(imsg->dest),
- sizeof(destbuf));
- strlcpy(maskbuf, inet_ntoa(imsg->netmask),
- sizeof(maskbuf));
- log_warn("%s: add route %s/%s via %s", log_procname,
- destbuf, maskbuf, inet_ntoa(imsg->gateway));
+ add_route(name, rdomain, routefd, dest, netmask,
+ gateway, RTF_STATIC | RTF_GATEWAY);
}
}
}
/*
- * delete_addresses() deletes existing inet addresses on the named interface,
- * leaving in place newaddr/newnetmask.
- *
- * Return 1 if newaddr/newnetmask is seen while deleting addresses, 0 otherwise.
- */
-int
-delete_addresses(char *name, struct in_addr newaddr, struct in_addr newnetmask)
-{
- struct in_addr addr, netmask;
- struct ifaddrs *ifap, *ifa;
- int found = 0;
-
- if (getifaddrs(&ifap) != 0)
- fatal("getifaddrs");
-
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if ((ifa->ifa_flags & IFF_LOOPBACK) != 0 ||
- (ifa->ifa_flags & IFF_POINTOPOINT) != 0 ||
- ((ifa->ifa_flags & IFF_UP) == 0) ||
- (ifa->ifa_addr->sa_family != AF_INET) ||
- (strcmp(name, ifa->ifa_name) != 0))
- continue;
-
- memcpy(&addr,
- &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
- sizeof(addr));
- memcpy(&netmask,
- &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr,
- sizeof(netmask));
-
- if (addr.s_addr == newaddr.s_addr &&
- netmask.s_addr == newnetmask.s_addr)
- found = 1;
- else
- delete_address(addr);
- }
-
- freeifaddrs(ifap);
- return (found);
-}
-
-/*
- * [priv_]delete_address is the equivalent of
- *
- * ifconfig <ifname> inet <addr> delete
- */
-void
-delete_address(struct in_addr addr)
-{
- struct imsg_delete_address imsg;
- int rslt;
-
- imsg.addr = addr;
-
- rslt = imsg_compose(unpriv_ibuf, IMSG_DELETE_ADDRESS, 0, 0 , -1, &imsg,
- sizeof(imsg));
- if (rslt == -1)
- log_warn("%s: imsg_compose(IMSG_DELETE_ADDRESS)", log_procname);
-}
-
-void
-priv_delete_address(char *name, int ioctlfd, struct imsg_delete_address *imsg)
-{
- struct ifaliasreq ifaliasreq;
- struct sockaddr_in *in;
-
- /*
- * Delete specified address on specified interface.
- */
-
- memset(&ifaliasreq, 0, sizeof(ifaliasreq));
- strncpy(ifaliasreq.ifra_name, name, 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 = imsg->addr.s_addr;
-
- /* SIOCDIFADDR will result in a RTM_DELADDR message we must catch! */
- if (ioctl(ioctlfd, SIOCDIFADDR, &ifaliasreq) == -1) {
- if (errno != EADDRNOTAVAIL)
- log_warn("%s: SIOCDIFADDR %s", log_procname,
- inet_ntoa(imsg->addr));
- }
-}
-
-/*
- * [priv_]set_mtu is the equivalent of
- *
- * ifconfig <if> mtu <mtu>
- */
-void
-set_mtu(int inits, uint16_t mtu)
-{
- struct imsg_set_mtu imsg;
- int rslt;
-
- if ((inits & RTV_MTU) == 0)
- return;
-
- if (mtu < 68) {
- log_warnx("%s: mtu size %u < 68: ignored", log_procname, mtu);
- return;
- }
- imsg.mtu = mtu;
-
- rslt = imsg_compose(unpriv_ibuf, IMSG_SET_MTU, 0, 0, -1,
- &imsg, sizeof(imsg));
- if (rslt == -1)
- log_warn("%s: imsg_compose(IMSG_SET_MTU)", log_procname);
-}
-
-void
-priv_set_mtu(char *name, int ioctlfd, struct imsg_set_mtu *imsg)
-{
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(ifr));
-
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- ifr.ifr_mtu = imsg->mtu;
-
- if (ioctl(ioctlfd, SIOCSIFMTU, &ifr) == -1)
- log_warn("%s: SIOCSIFMTU %d", log_procname, imsg->mtu);
-}
-
-/*
- * [priv_]set_address is the equivalent of
- *
- * ifconfig <if> inet <addr> netmask <mask> broadcast <addr>
- */
-void
-set_address(char *name, struct in_addr addr, struct in_addr netmask)
-{
- struct imsg_set_address imsg;
- int rslt;
-
- /* Deleting the addresses also clears out arp entries. */
- if (delete_addresses(name, addr, netmask) != 0)
- return;
-
- imsg.addr = addr;
- imsg.mask = netmask;
-
- rslt = imsg_compose(unpriv_ibuf, IMSG_SET_ADDRESS, 0, 0, -1, &imsg,
- sizeof(imsg));
- if (rslt == -1)
- log_warn("%s: imsg_compose(IMSG_SET_ADDRESS)", log_procname);
-}
-
-void
-priv_set_address(char *name, int ioctlfd, struct imsg_set_address *imsg)
-{
- struct ifaliasreq ifaliasreq;
- struct sockaddr_in *in;
-
- memset(&ifaliasreq, 0, sizeof(ifaliasreq));
- strncpy(ifaliasreq.ifra_name, name, 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 = 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, &imsg->mask, sizeof(in->sin_addr));
-
- /* No need to set broadcast address. Kernel can figure it out. */
-
- if (ioctl(ioctlfd, SIOCAIFADDR, &ifaliasreq) == -1)
- log_warn("%s: SIOCAIFADDR %s", log_procname,
- inet_ntoa(imsg->addr));
-}
-
-/*
- * [priv_]write_resolv_conf write out a new resolv.conf.
- */
-void
-write_resolv_conf(void)
-{
- int rslt;
-
- rslt = imsg_compose(unpriv_ibuf, IMSG_WRITE_RESOLV_CONF,
- 0, 0, -1, NULL, 0);
- if (rslt == -1)
- log_warn("%s: imsg_compose(IMSG_WRITE_RESOLV_CONF)",
- log_procname);
-}
-
-void
-priv_write_resolv_conf(char *contents)
-{
- const char *path = "/etc/resolv.conf";
- ssize_t n;
- size_t sz;
- int fd;
-
- if (contents == NULL)
- return;
-
- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
- if (fd == -1) {
- log_warn("%s: open(%s)", log_procname, path);
- return;
- }
-
- sz = strlen(contents);
- n = write(fd, contents, sz);
- if (n == -1)
- log_warn("%s: write(%s)", log_procname, path);
- else if ((size_t)n < sz)
- log_warnx("%s: write(%s): %zd of %zu bytes", log_procname,
- path, n, sz);
-
- close(fd);
-}
-
-/*
- * default_route_index returns the index of the interface which the
- * default route (a.k.a. 0.0.0.0/0) is on.
+ * default_route_index() returns the interface index of the current
+ * default route (a.k.a. 0.0.0.0/0).
*/
int
default_route_index(int rdomain, int routefd)
@@ -719,15 +627,60 @@ default_route_index(int rdomain, int routefd)
}
/*
- * set_resolv_conf creates a string that are the resolv.conf contents
- * that should be used when the interface is determined to be the one to
- * create /etc/resolv.conf
+ * resolv_conf_tail() returns the contents of /etc/resolv.conf.tail, if
+ * any. NULL is returned if there is no such file, the file is emtpy
+ * or any errors are encounted in reading the file.
*/
-void
+char *
+resolv_conf_tail(void)
+{
+ struct stat sb;
+ const char *tail_path = "/etc/resolv.conf.tail";
+ char *tailcontents = NULL;
+ ssize_t tailn;
+ int tailfd;
+
+ tailfd = open(tail_path, O_RDONLY);
+ if (tailfd == -1) {
+ if (errno != ENOENT)
+ log_warn("%s: open(%s)", log_procname, tail_path);
+ } else if (fstat(tailfd, &sb) == -1) {
+ log_warn("%s: fstat(%s)", log_procname, tail_path);
+ } else if (sb.st_size > 0 && sb.st_size < LLONG_MAX) {
+ tailcontents = calloc(1, sb.st_size + 1);
+ if (tailcontents == NULL)
+ fatal("%s contents", tail_path);
+ tailn = read(tailfd, tailcontents, sb.st_size);
+ if (tailn == -1)
+ log_warn("%s: read(%s)", log_procname,
+ tail_path);
+ else if (tailn == 0)
+ log_warnx("%s: got no data from %s",
+ log_procname,tail_path);
+ else if (tailn != sb.st_size)
+ log_warnx("%s: short read of %s",
+ log_procname, tail_path);
+ else {
+ close(tailfd);
+ return tailcontents;
+ }
+
+ close(tailfd);
+ free(tailcontents);
+ }
+
+ return NULL;
+}
+
+/*
+ * set_resolv_conf() creates a string that are the resolv.conf contents
+ * that should be used when IMSG_WRITE_RESOLV_CONF messages are received.
+ */
+char *
set_resolv_conf(char *name, uint8_t *rtsearch, unsigned int rtsearch_len,
uint8_t *rtdns, unsigned int rtdns_len)
{
- char *dn, *nss[MAXNS], *contents, *courtesy;
+ char *dn, *nss[MAXNS], *contents, *courtesy, *resolv_tail;
struct in_addr *addr;
size_t len;
unsigned int i, servers;
@@ -767,13 +720,14 @@ set_resolv_conf(char *name, uint8_t *rtsearch, unsigned int rtsearch_len,
* resolv.conf when neither search nor dns info
* was provided. Is that really what we want?
*/
- if (len > 0 && config->resolv_tail != NULL)
- len += strlen(config->resolv_tail);
-
+ if (len > 0) {
+ resolv_tail = resolv_conf_tail();
+ if (resolv_tail != NULL)
+ len += strlen(resolv_tail);
+ }
if (len == 0) {
free(dn);
- contents = NULL;
- goto done;
+ return NULL;
}
rslt = asprintf(&courtesy, "# Generated by %s dhclient\n", name);
@@ -799,82 +753,194 @@ set_resolv_conf(char *name, uint8_t *rtsearch, unsigned int rtsearch_len,
}
}
- if (config->resolv_tail != NULL)
- strlcat(contents, config->resolv_tail, len);
+ if (resolv_tail != NULL) {
+ strlcat(contents, resolv_tail, len);
+ free(resolv_tail);
+ }
-done:
- rslt = imsg_compose(unpriv_ibuf, IMSG_SET_RESOLV_CONF,
- 0, 0, -1, contents, len);
- if (rslt == -1)
- log_warn("%s: imsg_compose(IMSG_SET_RESOLV_CONF)",
- log_procname);
+ return contents;
}
/*
- * get_rtaddrs populates the rti_info with pointers to the
- * sockaddr's contained in a rtm message.
+ * set_mtu() is the equivalent of
+ *
+ * ifconfig <if> mtu <mtu>
*/
void
-get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
+set_mtu(char *name, int ioctlfd, uint16_t mtu)
{
- int i;
+ struct ifreq ifr;
- for (i = 0; i < RTAX_MAX; i++) {
- if (addrs & (1 << i)) {
- rti_info[i] = sa;
- sa = (struct sockaddr *)((char *)(sa) +
- ROUNDUP(sa->sa_len));
- } else
- rti_info[i] = NULL;
- }
+ memset(&ifr, 0, sizeof(ifr));
+
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_mtu = mtu;
+
+ if (ioctl(ioctlfd, SIOCSIFMTU, &ifr) == -1)
+ log_warn("%s: SIOCSIFMTU %d", log_procname, mtu);
}
+/*
+ * extract_classless_route() extracts the encoded route pointed to by rtstatic.
+ */
unsigned int
-route_in_rtstatic(struct rt_msghdr *rtm, uint8_t *rtstatic,
- unsigned int rtstatic_len)
+extract_classless_route(uint8_t *rtstatic, unsigned int rtstatic_len,
+ in_addr_t *dest, in_addr_t *netmask, in_addr_t *gateway)
{
- struct sockaddr *rti_info[RTAX_MAX];
- struct sockaddr *dst, *netmask, *gateway;
- in_addr_t dstaddr, netmaskaddr, gatewayaddr;
- in_addr_t rtstaticdstaddr, rtstaticnetmaskaddr;
- in_addr_t rtstaticgatewayaddr;
- unsigned int i, len;
+ unsigned int bits, bytes, len;
- get_rtaddrs(rtm->rtm_addrs,
- (struct sockaddr *)((char *)(rtm) + rtm->rtm_hdrlen),
- rti_info);
+ if (rtstatic[0] > 32)
+ return 0;
- dst = rti_info[RTAX_DST];
- netmask = rti_info[RTAX_NETMASK];
- gateway = rti_info[RTAX_GATEWAY];
+ bits = rtstatic[0];
+ bytes = (bits + 7) / 8;
+ len = 1 + bytes + sizeof(*gateway);
+ if (len > rtstatic_len)
+ return 0;
- if (dst == NULL || netmask == NULL || gateway == NULL)
- return rtstatic_len;
+ if (dest != NULL)
+ memcpy(dest, &rtstatic[1], bytes);
- if (dst->sa_family != AF_INET || netmask->sa_family != AF_INET ||
- gateway->sa_family != AF_INET)
- return rtstatic_len;
+ if (netmask != NULL) {
+ if (bits == 0)
+ *netmask = INADDR_ANY;
+ else
+ *netmask = htonl(0xffffffff << (32 - bits));
+ if (dest != NULL)
+ *dest &= *netmask;
+ }
- dstaddr = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
- netmaskaddr = ((struct sockaddr_in *)netmask)->sin_addr.s_addr;
- gatewayaddr = ((struct sockaddr_in *)gateway)->sin_addr.s_addr;
+ if (gateway != NULL)
+ memcpy(gateway, &rtstatic[1 + bytes], sizeof(*gateway));
- dstaddr &= netmaskaddr;
- i = 0;
- while (i < rtstatic_len) {
- len = extract_classless_route(&rtstatic[i], rtstatic_len - i,
- &rtstaticdstaddr, &rtstaticnetmaskaddr,
- &rtstaticgatewayaddr);
- if (len == 0)
- break;
+ return len;
+}
- if (dstaddr == rtstaticdstaddr &&
- netmaskaddr == rtstaticnetmaskaddr &&
- gatewayaddr == rtstaticgatewayaddr)
- return i;
+/*
+ * [priv_]write_resolv_conf write out a new resolv.conf.
+ */
+void
+write_resolv_conf(void)
+{
+ int rslt;
- i += len;
+ rslt = imsg_compose(unpriv_ibuf, IMSG_WRITE_RESOLV_CONF,
+ 0, 0, -1, NULL, 0);
+ if (rslt == -1)
+ log_warn("%s: imsg_compose(IMSG_WRITE_RESOLV_CONF)",
+ log_procname);
+}
+
+void
+priv_write_resolv_conf(int index, int routefd, int rdomain, char *contents,
+ int *lastidx)
+{
+ const char *path = "/etc/resolv.conf";
+ ssize_t n;
+ size_t sz;
+ int fd, retries, newidx;
+
+ if (contents == NULL)
+ return;
+
+ retries = 0;
+ do {
+ newidx = default_route_index(rdomain, routefd);
+ retries++;
+ } while (newidx == 0 && retries < 3);
+ if (newidx != index || newidx == *lastidx)
+ return;
+ *lastidx = newidx;
+
+ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ if (fd == -1) {
+ log_warn("%s: open(%s)", log_procname, path);
+ return;
}
- return rtstatic_len;
+ sz = strlen(contents);
+ n = write(fd, contents, sz);
+ if (n == -1)
+ log_warn("%s: write(%s)", log_procname, path);
+ else if ((size_t)n < sz)
+ log_warnx("%s: write(%s): %zd of %zu bytes", log_procname,
+ path, n, sz);
+
+ close(fd);
+}
+
+/*
+ * [priv_]propose implements a proposal.
+ */
+void
+propose(struct proposal *proposal)
+{
+ struct imsg_propose imsg;
+ int rslt;
+
+ memcpy(&imsg.proposal, proposal, sizeof(imsg.proposal));
+
+ rslt = imsg_compose(unpriv_ibuf, IMSG_PROPOSE, 0, 0, -1, &imsg,
+ sizeof(imsg));
+ if (rslt == -1)
+ log_warn("%s: imsg_compose(IMSG_PROPOSE)", log_procname);
+}
+
+void
+priv_propose(char *name, int ioctlfd, struct imsg_propose *imsg,
+ char **resolv_conf, int routefd, int rdomain, int index)
+{
+ struct proposal *proposal = &imsg->proposal;
+
+ *resolv_conf = set_resolv_conf(name,
+ proposal->rtsearch,
+ proposal->rtsearch_len,
+ proposal->rtdns,
+ proposal->rtdns_len);
+
+ if ((proposal->inits & RTV_MTU) != 0) {
+ if (proposal->mtu < 68)
+ log_warnx("%s: mtu size %u < 68: ignored", log_procname,
+ proposal->mtu);
+ else
+ set_mtu(name, ioctlfd, proposal->mtu);
+ }
+
+ set_address(name, ioctlfd, proposal->ifa, proposal->netmask);
+
+ set_routes(name, index, rdomain, routefd, proposal->ifa, proposal->netmask,
+ proposal->rtstatic, proposal->rtstatic_len);
+}
+/*
+ * [priv_]revoke_proposal de-configures a proposal.
+ */
+void
+revoke_proposal(struct proposal *proposal)
+{
+ struct imsg_revoke imsg;
+ int rslt;
+
+ if (proposal == NULL)
+ return;
+
+ memcpy(&imsg.proposal, proposal, sizeof(imsg.proposal));
+
+ rslt = imsg_compose(unpriv_ibuf, IMSG_REVOKE, 0, 0, -1, &imsg,
+ sizeof(imsg));
+ if (rslt == -1)
+ log_warn("%s: imsg_compose(IMSG_REVOKE)", log_procname);
+}
+
+void
+priv_revoke_proposal(char *name, int ioctlfd, struct imsg_revoke *imsg,
+ char **resolv_conf)
+{
+ struct proposal *proposal = &imsg->proposal;
+
+ free(*resolv_conf);
+ *resolv_conf = NULL;
+
+ delete_address(name, ioctlfd, proposal->ifa);
}
diff --git a/sbin/dhclient/privsep.c b/sbin/dhclient/privsep.c
index b63aa1ca051..9d22916e0e3 100644
--- a/sbin/dhclient/privsep.c
+++ b/sbin/dhclient/privsep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: privsep.c,v 1.74 2019/01/19 21:07:13 krw Exp $ */
+/* $OpenBSD: privsep.c,v 1.75 2019/02/12 16:50:44 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -46,8 +46,7 @@ dispatch_imsg(char *name, int rdomain, int ioctlfd, int routefd,
static int lastidx;
struct imsg imsg;
ssize_t n;
- size_t sz;
- int index, newidx, retries;
+ int index;
index = if_nametoindex(name);
if (index == 0) {
@@ -64,70 +63,25 @@ dispatch_imsg(char *name, int rdomain, int ioctlfd, int routefd,
break;
switch (imsg.hdr.type) {
- case IMSG_DELETE_ADDRESS:
+ case IMSG_REVOKE:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct imsg_delete_address))
- log_warnx("%s: bad IMSG_DELETE_ADDRESS",
+ sizeof(struct imsg_revoke))
+ log_warnx("%s: bad IMSG_REVOKE",
log_procname);
else
- priv_delete_address(name, ioctlfd, imsg.data);
+ priv_revoke_proposal(name, ioctlfd, imsg.data,
+ &resolv_conf);
break;
- case IMSG_SET_ADDRESS:
+ case IMSG_PROPOSE:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct imsg_set_address))
- log_warnx("%s: bad IMSG_SET_ADDRESS",
- log_procname);
- else
- priv_set_address(name, ioctlfd, imsg.data);
- break;
-
- case IMSG_FLUSH_ROUTES:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct imsg_flush_routes))
- log_warnx("%s: bad IMSG_FLUSH_ROUTES",
- log_procname);
- else
- priv_flush_routes(index, routefd, rdomain,
- imsg.data);
- break;
-
- case IMSG_ADD_ROUTE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct imsg_add_route))
- log_warnx("%s: bad IMSG_ADD_ROUTE",
- log_procname);
- else
- priv_add_route(name, rdomain, routefd,
- imsg.data);
- break;
-
- case IMSG_SET_MTU:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct imsg_set_mtu))
- log_warnx("%s: bad IMSG_SET_MTU", log_procname);
- else
- priv_set_mtu(name, ioctlfd, imsg.data);
- break;
-
- case IMSG_SET_RESOLV_CONF:
- if (imsg.hdr.len < IMSG_HEADER_SIZE)
- log_warnx("%s: bad IMSG_SET_RESOLV_CONF",
+ sizeof(struct imsg_propose))
+ log_warnx("%s: bad IMSG_PROPOSE",
log_procname);
else {
- free(resolv_conf);
- resolv_conf = NULL;
- sz = imsg.hdr.len - IMSG_HEADER_SIZE;
- if (sz > 0) {
- resolv_conf = malloc(sz);
- if (resolv_conf == NULL)
- log_warn("%s: resolv_conf",
- log_procname);
- else
- strlcpy(resolv_conf,
- imsg.data, sz);
- }
- lastidx = 0;
+ priv_propose(name, ioctlfd, imsg.data,
+ &resolv_conf, routefd, rdomain, index);
+ lastidx = 0; /* Next IMSG_WRITE_RESOLV_CONF */
}
break;
@@ -135,17 +89,9 @@ dispatch_imsg(char *name, int rdomain, int ioctlfd, int routefd,
if (imsg.hdr.len != IMSG_HEADER_SIZE)
log_warnx("%s: bad IMSG_WRITE_RESOLV_CONF",
log_procname);
- else {
- retries = 0;
- do {
- newidx = default_route_index(rdomain,
- routefd);
- retries++;
- } while (newidx == 0 && retries < 3);
- if (newidx == index && newidx != lastidx)
- priv_write_resolv_conf(resolv_conf);
- lastidx = newidx;
- }
+ else
+ priv_write_resolv_conf(index, routefd, rdomain,
+ resolv_conf, &lastidx);
break;
default:
diff --git a/sbin/dhclient/privsep.h b/sbin/dhclient/privsep.h
index 7b4c7c86300..0ef4032f620 100644
--- a/sbin/dhclient/privsep.h
+++ b/sbin/dhclient/privsep.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: privsep.h,v 1.58 2019/01/19 21:07:13 krw Exp $ */
+/* $OpenBSD: privsep.h,v 1.59 2019/02/12 16:50:44 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -18,49 +18,38 @@
enum imsg_code {
IMSG_NONE,
- IMSG_DELETE_ADDRESS,
- IMSG_SET_ADDRESS,
- IMSG_FLUSH_ROUTES,
- IMSG_ADD_ROUTE,
- IMSG_SET_MTU,
- IMSG_SET_RESOLV_CONF,
- IMSG_WRITE_RESOLV_CONF
+ IMSG_REVOKE,
+ IMSG_WRITE_RESOLV_CONF,
+ IMSG_PROPOSE
};
-struct imsg_delete_address {
- struct in_addr addr;
-};
-
-struct imsg_set_address {
- struct in_addr addr;
- struct in_addr mask;
-};
+#define RTLEN 128
-struct imsg_flush_routes {
- uint8_t rtstatic[RTSTATIC_LEN];
+struct proposal {
+ uint8_t rtstatic[RTLEN];
+ uint8_t rtsearch[RTLEN];
+ uint8_t rtdns[RTLEN];
+ struct in_addr ifa;
+ struct in_addr netmask;
unsigned int rtstatic_len;
+ unsigned int rtsearch_len;
+ unsigned int rtdns_len;
+ int mtu;
+ int addrs;
+ int inits;
};
-struct imsg_add_route {
- struct in_addr dest;
- struct in_addr netmask;
- struct in_addr gateway;
- int flags;
+struct imsg_propose {
+ struct proposal proposal;
};
-struct imsg_set_mtu {
- int mtu;
+struct imsg_revoke {
+ struct proposal proposal;
};
void dispatch_imsg(char *, int, int, int, struct imsgbuf *);
-int default_route_index(int, int);
-
-void priv_add_route(char *, int, int, struct imsg_add_route *);
-void priv_flush_routes(int, int, int, struct imsg_flush_routes *);
-
-void priv_write_resolv_conf(char *);
-void priv_delete_address(char *, int, struct imsg_delete_address *);
-void priv_set_address(char *, int, struct imsg_set_address *);
+void priv_write_resolv_conf(int, int, int, char *, int *);
+void priv_propose(char *, int, struct imsg_propose *, char **, int, int, int);
-void priv_set_mtu(char *, int, struct imsg_set_mtu *);
+void priv_revoke_proposal(char *, int, struct imsg_revoke *, char **);