summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2019-11-19 14:35:09 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2019-11-19 14:35:09 +0000
commit90b5e0d082fb0fb74528924ee00ba140aac7f659 (patch)
treeaa18746e36e6eb776986c65da8069ca8b073a6a7 /sbin
parent9e75536a66870cccf86a12c56bb673b7f033e616 (diff)
Inform unwind about DNS servers it finds in leases.
ok florian@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/dhclient/dhclient.c79
-rw-r--r--sbin/dhclient/dhcpd.h5
-rw-r--r--sbin/dhclient/dispatch.c5
-rw-r--r--sbin/dhclient/kroute.c71
-rw-r--r--sbin/dhclient/privsep.c12
-rw-r--r--sbin/dhclient/privsep.h17
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 *);