diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2019-11-19 14:35:09 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2019-11-19 14:35:09 +0000 |
commit | 90b5e0d082fb0fb74528924ee00ba140aac7f659 (patch) | |
tree | aa18746e36e6eb776986c65da8069ca8b073a6a7 /sbin | |
parent | 9e75536a66870cccf86a12c56bb673b7f033e616 (diff) |
Inform unwind about DNS servers it finds in leases.
ok florian@
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/dhclient/dhclient.c | 79 | ||||
-rw-r--r-- | sbin/dhclient/dhcpd.h | 5 | ||||
-rw-r--r-- | sbin/dhclient/dispatch.c | 5 | ||||
-rw-r--r-- | sbin/dhclient/kroute.c | 71 | ||||
-rw-r--r-- | sbin/dhclient/privsep.c | 12 | ||||
-rw-r--r-- | sbin/dhclient/privsep.h | 17 |
6 files changed, 178 insertions, 11 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index a2cff25f53f..1e78194af2e 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhclient.c,v 1.652 2019/11/06 12:14:19 krw Exp $ */ +/* $OpenBSD: dhclient.c,v 1.653 2019/11/19 14:35:07 krw Exp $ */ /* * Copyright 2004 Henning Brauer <henning@openbsd.org> @@ -154,6 +154,7 @@ void write_lease_db(struct client_lease_tq *); void write_option_db(struct client_lease *, struct client_lease *); char *lease_as_string(char *, struct client_lease *); struct proposal *lease_as_proposal(struct client_lease *); +struct unwind_info *lease_as_unwind_info(struct client_lease *); void append_statement(char *, size_t, char *, char *); time_t lease_expiry(struct client_lease *); time_t lease_renewal(struct client_lease *); @@ -348,6 +349,11 @@ rtm_dispatch(struct interface_info *ifi, struct rt_msghdr *rtm) switch (rtm->rtm_type) { case RTM_PROPOSAL: + if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT) { + if (quit == 0 && ifi->active != NULL) + tell_unwind(ifi->unwind_info, RTF_UP, ifi->flags); + return; + } if (rtm->rtm_index != ifi->index || rtm->rtm_priority != RTP_PROPOSAL_DHCLIENT) return; @@ -379,10 +385,14 @@ rtm_dispatch(struct interface_info *ifi, struct rt_msghdr *rtm) if ((rtm->rtm_flags & RTF_UP) == 0) fatalx("down"); - if ((ifm->ifm_xflags & IFXF_AUTOCONF4) == 0) - ifi->flags &= ~IFI_AUTOCONF; - else if ((ifi->flags & IFI_AUTOCONF) == 0) { - /* Get new lease when AUTOCONF4 gets set. */ + if ((ifm->ifm_xflags & IFXF_AUTOCONF4) == 0 && + (ifi->flags & IFI_AUTOCONF) != 0) { + /* Tell unwind when IFI_AUTOCONF is cleared. */ + tell_unwind(ifi->unwind_info, 0, ifi->flags); + ifi->flags &= ~IFI_AUTOCONF; + } else if ((ifm->ifm_xflags & IFXF_AUTOCONF4) != 0 && + (ifi->flags & IFI_AUTOCONF) == 0) { + /* Get new lease when IFI_AUTOCONF is set. */ ifi->flags |= IFI_AUTOCONF; quit = RESTART; break; @@ -926,6 +936,8 @@ dhcpnak(struct interface_info *ifi, const char *src) ifi->active = NULL; free(ifi->configured); ifi->configured = NULL; + free(ifi->unwind_info); + ifi->unwind_info = NULL; /* Stop sending DHCPREQUEST packets. */ cancel_timeout(ifi); @@ -939,6 +951,7 @@ bind_lease(struct interface_info *ifi) { struct client_lease *lease, *pl, *ll; struct proposal *effective_proposal = NULL; + struct unwind_info *unwind_info; char *msg = NULL; time_t cur_time, renewal; int rslt, seen; @@ -968,6 +981,27 @@ bind_lease(struct interface_info *ifi) ifi->active = ifi->offer; ifi->offer = NULL; + /* + * Supply unwind with updated info. + */ + unwind_info = lease_as_unwind_info(ifi->active); + if (ifi->unwind_info == NULL && unwind_info != NULL) { + ifi->unwind_info = unwind_info; + tell_unwind(ifi->unwind_info, RTF_UP, ifi->flags); + } else if (ifi->unwind_info != NULL && unwind_info == NULL) { + tell_unwind(ifi->unwind_info, 0, ifi->flags); + free(ifi->unwind_info); + ifi->unwind_info = NULL; + } else if (ifi->unwind_info != NULL && unwind_info != NULL) { + if (memcmp(ifi->unwind_info, unwind_info, + sizeof(*ifi->unwind_info)) != 0) { + tell_unwind(ifi->unwind_info, 0, ifi->flags); + free(ifi->unwind_info); + ifi->unwind_info = unwind_info; + tell_unwind(ifi->unwind_info, RTF_UP, ifi->flags); + } + } + effective_proposal = lease_as_proposal(lease); if (ifi->configured != NULL) { if (memcmp(ifi->configured, effective_proposal, @@ -1880,6 +1914,37 @@ append_statement(char *string, size_t sz, char *s1, char *s2) strlcat(string, ";\n", sz); } +struct unwind_info * +lease_as_unwind_info(struct client_lease *lease) +{ + struct unwind_info *unwind_info; + struct option_data *opt; + unsigned int servers; + + unwind_info = calloc(1, sizeof(*unwind_info)); + if (unwind_info == NULL) + fatal("unwind_info"); + + opt = &lease->options[DHO_DOMAIN_NAME_SERVERS]; + if (opt->len != 0) { + servers = opt->len / sizeof(in_addr_t); + if (servers > MAXNS) + servers = MAXNS; + if (servers > 0) { + unwind_info->count = servers; + memcpy(unwind_info->ns, opt->data, servers * + sizeof(in_addr_t)); + } + } + + if (unwind_info->count == 0) { + free(unwind_info); + unwind_info = NULL; + } + + return unwind_info; +} + struct proposal * lease_as_proposal(struct client_lease *lease) { @@ -2697,6 +2762,8 @@ release_lease(struct interface_info *ifi) make_release(ifi, ifi->active); send_release(ifi); + tell_unwind(ifi->unwind_info, 0, ifi->flags); + revoke_proposal(ifi->configured); imsg_flush(unpriv_ibuf); @@ -2713,6 +2780,8 @@ release_lease(struct interface_info *ifi) ifi->active = NULL; free(ifi->configured); ifi->configured = NULL; + free(ifi->unwind_info); + ifi->unwind_info = NULL; log_warnx("%s: %s RELEASED to %s", log_procname, ifabuf, destbuf); } diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 8ea427236c7..3328e17b63a 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcpd.h,v 1.282 2019/07/30 12:48:27 krw Exp $ */ +/* $OpenBSD: dhcpd.h,v 1.283 2019/11/19 14:35:08 krw Exp $ */ /* * Copyright (c) 2004 Henning Brauer <henning@openbsd.org> @@ -149,6 +149,7 @@ struct interface_info { struct client_lease *offer; char *offer_src; struct proposal *configured; + struct unwind_info *unwind_info; struct client_lease_tq lease_db; }; @@ -248,3 +249,5 @@ void write_resolv_conf(void); void propose(struct proposal *); void revoke_proposal(struct proposal *); + +void tell_unwind(struct unwind_info *, int, int); diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c index 0b43f190519..93c024989ee 100644 --- a/sbin/dhclient/dispatch.c +++ b/sbin/dhclient/dispatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.c,v 1.165 2019/05/10 01:29:31 guenther Exp $ */ +/* $OpenBSD: dispatch.c,v 1.166 2019/11/19 14:35:08 krw Exp $ */ /* * Copyright 2004 Henning Brauer <henning@openbsd.org> @@ -58,6 +58,7 @@ #include <imsg.h> #include <limits.h> #include <poll.h> +#include <resolv.h> #include <signal.h> #include <stdio.h> #include <stdint.h> @@ -93,6 +94,8 @@ dispatch(struct interface_info *ifi, int routefd) time(&ifi->startup_time); free(ifi->configured); ifi->configured = NULL; + free(ifi->unwind_info); + ifi->unwind_info = NULL; ifi->state = S_PREBOOT; state_preboot(ifi); } diff --git a/sbin/dhclient/kroute.c b/sbin/dhclient/kroute.c index fab02e06613..b77ec287b9b 100644 --- a/sbin/dhclient/kroute.c +++ b/sbin/dhclient/kroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.169 2019/11/06 11:34:37 krw Exp $ */ +/* $OpenBSD: kroute.c,v 1.170 2019/11/19 14:35:08 krw Exp $ */ /* * Copyright 2012 Kenneth R Westerback <krw@openbsd.org> @@ -1007,3 +1007,72 @@ priv_revoke_proposal(char *name, int ioctlfd, struct imsg_revoke *imsg, delete_address(name, ioctlfd, proposal->ifa); } + +/* + * [priv_]tell_unwind sends out inforation unwind may be intereted in. + */ +void +tell_unwind(struct unwind_info *unwind_info, int rtm_flags, int ifi_flags) +{ + struct imsg_tell_unwind imsg; + int rslt; + + if (unwind_info == NULL || + (ifi_flags & IFI_AUTOCONF) == 0 || + (ifi_flags & IFI_IN_CHARGE) == 0) + return; + + memset(&imsg, 0, sizeof(imsg)); + + imsg.rtm_flags = rtm_flags; + memcpy(&imsg.unwind_info, unwind_info, sizeof(imsg.unwind_info)); + + rslt = imsg_compose(unpriv_ibuf, IMSG_TELL_UNWIND, 0, 0, -1, &imsg, + sizeof(imsg)); + if (rslt == -1) + log_warn("%s: imsg_compose(IMSG_TELL_UNWIND)", log_procname); +} + +void +priv_tell_unwind(int index, int routefd, int rdomain, struct imsg_tell_unwind *imsg) +{ + struct rt_msghdr rtm; + struct sockaddr_rtdns rtdns; + struct iovec iov[3]; + long pad = 0; + int iovcnt = 0, padlen; + + memset(&rtm, 0, sizeof(rtm)); + + rtm.rtm_version = RTM_VERSION; + rtm.rtm_type = RTM_PROPOSAL; + rtm.rtm_msglen = sizeof(rtm); + rtm.rtm_tableid = rdomain; + rtm.rtm_index = index; + rtm.rtm_seq = arc4random(); + rtm.rtm_priority = RTP_PROPOSAL_DHCLIENT; + rtm.rtm_addrs = RTA_DNS; + rtm.rtm_flags = imsg->rtm_flags; + + iov[iovcnt].iov_base = &rtm; + iov[iovcnt++].iov_len = sizeof(rtm); + + memset(&rtdns, 0, sizeof(rtdns)); + rtdns.sr_family = AF_INET; + rtdns.sr_len = 2 + imsg->unwind_info.count * sizeof(in_addr_t); + memcpy(rtdns.sr_dns, imsg->unwind_info.ns, imsg->unwind_info.count * + sizeof(in_addr_t)); + + iov[iovcnt].iov_base = &rtdns; + iov[iovcnt++].iov_len = sizeof(rtdns); + rtm.rtm_msglen += sizeof(rtdns); + padlen = ROUNDUP(sizeof(rtdns)) - sizeof(rtdns); + if (padlen > 0) { + iov[iovcnt].iov_base = &pad; + iov[iovcnt++].iov_len = padlen; + rtm.rtm_msglen += padlen; + } + + if (writev(routefd, iov, iovcnt) == -1) + log_warn("failed to tell unwind"); +} diff --git a/sbin/dhclient/privsep.c b/sbin/dhclient/privsep.c index 9d22916e0e3..1a2d7250b70 100644 --- a/sbin/dhclient/privsep.c +++ b/sbin/dhclient/privsep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: privsep.c,v 1.75 2019/02/12 16:50:44 krw Exp $ */ +/* $OpenBSD: privsep.c,v 1.76 2019/11/19 14:35:08 krw Exp $ */ /* * Copyright (c) 2004 Henning Brauer <henning@openbsd.org> @@ -27,6 +27,7 @@ #include <errno.h> #include <imsg.h> +#include <resolv.h> #include <signal.h> #include <stdio.h> #include <stdint.h> @@ -94,6 +95,15 @@ dispatch_imsg(char *name, int rdomain, int ioctlfd, int routefd, resolv_conf, &lastidx); break; + case IMSG_TELL_UNWIND: + if (imsg.hdr.len != IMSG_HEADER_SIZE + + sizeof(struct imsg_tell_unwind)) + log_warnx("%s: bad IMSG_TELL_UNWIND", + log_procname); + else + priv_tell_unwind(index, routefd, rdomain, imsg.data); + break; + default: log_warnx("%s: received unknown message, code %u", log_procname, imsg.hdr.type); diff --git a/sbin/dhclient/privsep.h b/sbin/dhclient/privsep.h index 0ef4032f620..b2e0a74d5ee 100644 --- a/sbin/dhclient/privsep.h +++ b/sbin/dhclient/privsep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: privsep.h,v 1.59 2019/02/12 16:50:44 krw Exp $ */ +/* $OpenBSD: privsep.h,v 1.60 2019/11/19 14:35:08 krw Exp $ */ /* * Copyright (c) 2004 Henning Brauer <henning@openbsd.org> @@ -20,7 +20,8 @@ enum imsg_code { IMSG_NONE, IMSG_REVOKE, IMSG_WRITE_RESOLV_CONF, - IMSG_PROPOSE + IMSG_PROPOSE, + IMSG_TELL_UNWIND }; #define RTLEN 128 @@ -39,6 +40,11 @@ struct proposal { int inits; }; +struct unwind_info { + in_addr_t ns[MAXNS]; + unsigned int count; +}; + struct imsg_propose { struct proposal proposal; }; @@ -47,9 +53,16 @@ struct imsg_revoke { struct proposal proposal; }; +struct imsg_tell_unwind { + struct unwind_info unwind_info; + uint8_t rtm_flags; +}; + void dispatch_imsg(char *, int, int, int, struct imsgbuf *); void priv_write_resolv_conf(int, int, int, char *, int *); void priv_propose(char *, int, struct imsg_propose *, char **, int, int, int); void priv_revoke_proposal(char *, int, struct imsg_revoke *, char **); + +void priv_tell_unwind(int, int, int, struct imsg_tell_unwind *); |