diff options
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/dhclient/clparse.c | 41 | ||||
-rw-r--r-- | sbin/dhclient/dhclient.c | 34 | ||||
-rw-r--r-- | sbin/dhclient/dhcpd.h | 13 | ||||
-rw-r--r-- | sbin/dhclient/kroute.c | 962 | ||||
-rw-r--r-- | sbin/dhclient/privsep.c | 86 | ||||
-rw-r--r-- | sbin/dhclient/privsep.h | 57 |
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 **); |