summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
Diffstat (limited to 'sbin')
-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 **);