-/* $OpenBSD: frontend.c,v 1.65 2021/01/24 18:29:15 florian Exp $ */
+/* $OpenBSD: frontend.c,v 1.66 2021/01/27 08:30:50 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
#include <errno.h>
#include <event.h>
+#include <ifaddrs.h>
#include <imsg.h>
#include <netdb.h>
#include <pwd.h>
int bl_cmp(struct bl_node *, struct bl_node *);
void free_bl(void);
int pending_query_cnt(void);
+void check_available_af(void);
struct uw_conf *frontend_conf;
static struct imsgev *iev_main;
setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
fatal("can't drop privileges");
- if (pledge("stdio unix recvfd", NULL) == -1)
+ if (pledge("stdio dns unix recvfd", NULL) == -1)
fatal("pledge");
event_init();
event_add(&ev_route, NULL);
frontend_imsg_compose_main(IMSG_STARTUP_DONE, 0, NULL, 0);
+ check_available_af();
}
void
frontend_imsg_compose_resolver(IMSG_REPLACE_DNS, 0,
&rdns_proposal, sizeof(rdns_proposal));
break;
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ case RTM_DESYNC:
+ check_available_af();
+ break;
default:
break;
}
{
free_pending_query(arg);
}
+
+void
+check_available_af()
+{
+ static int available_af = HAVE_IPV4 | HAVE_IPV6;
+ static int rtable = -1;
+ struct ifaddrs *ifap, *ifa;
+ struct if_data *ifa_data;
+ struct sockaddr_in *sin4;
+ struct sockaddr_in6 *sin6;
+ int new_available_af = 0, ifa_rtable = -1;
+
+ if (rtable == -1)
+ rtable = getrtable();
+
+ if (getifaddrs(&ifap) != 0) {
+ log_warn("getifaddrs");
+ return;
+ }
+
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr == NULL)
+ continue;
+ switch(ifa->ifa_addr->sa_family) {
+ case AF_LINK:
+ /* AF_LINK comes before inet / inet6 on an interface */
+ ifa_data = (struct if_data *)ifa->ifa_data;
+ ifa_rtable = ifa_data->ifi_rdomain;
+ break;
+ case AF_INET:
+ if (ifa_rtable != rtable)
+ continue;
+
+ sin4 = (struct sockaddr_in *)ifa->ifa_addr;
+ if ((ntohl(sin4->sin_addr.s_addr) >> 24) ==
+ IN_LOOPBACKNET)
+ continue;
+ new_available_af |= HAVE_IPV4;
+ break;
+ case AF_INET6:
+ if (ifa_rtable != rtable)
+ continue;
+
+ sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+ if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) ||
+ IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr) ||
+ IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr))
+ continue;
+ new_available_af |= HAVE_IPV6;
+ break;
+ default:
+ break;
+ }
+ if (new_available_af == (HAVE_IPV4 | HAVE_IPV6))
+ break;
+ }
+ freeifaddrs(ifap);
+ if (new_available_af != available_af) {
+ available_af = new_available_af;
+ frontend_imsg_compose_resolver(IMSG_CHANGE_AFS, 0,
+ &available_af, sizeof(available_af));
+ }
+}
-/* $OpenBSD: frontend.h,v 1.8 2021/01/24 18:29:15 florian Exp $ */
+/* $OpenBSD: frontend.h,v 1.9 2021/01/27 08:30:50 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#define HAVE_IPV4 1
+#define HAVE_IPV6 2
+
struct trust_anchor {
TAILQ_ENTRY(trust_anchor) entry;
char *ta;
-/* $OpenBSD: resolver.c,v 1.136 2021/01/26 12:46:46 florian Exp $ */
+/* $OpenBSD: resolver.c,v 1.137 2021/01/27 08:30:50 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
struct val_neg_cache *unified_neg_cache;
int dns64_present;
+int available_afs = HAVE_IPV4 | HAVE_IPV6;
static const char * const as112_zones[] = {
/* RFC1918 */
void
resolver_dispatch_frontend(int fd, short event, void *bula)
{
- struct imsgev *iev = bula;
- struct imsgbuf *ibuf;
- struct imsg imsg;
- struct query_imsg *query_imsg;
- ssize_t n;
- int shut = 0, verbose, i;
- char *ta;
+ struct imsgev *iev = bula;
+ struct imsgbuf *ibuf;
+ struct imsg imsg;
+ struct query_imsg *query_imsg;
+ ssize_t n;
+ int shut = 0, verbose, i, new_available_afs;
+ char *ta;
ibuf = &iev->ibuf;
replace_autoconf_forwarders((struct
imsg_rdns_proposal *)imsg.data);
break;
+ case IMSG_CHANGE_AFS:
+ if (IMSG_DATA_SIZE(imsg) !=
+ sizeof(new_available_afs))
+ fatalx("%s: IMSG_CHANGE_AFS wrong length: %lu",
+ __func__, IMSG_DATA_SIZE(imsg));
+ memcpy(&new_available_afs, imsg.data,
+ sizeof(new_available_afs));
+ if (new_available_afs != available_afs) {
+ available_afs = new_available_afs;
+ restart_ub_resolvers();
+ }
+ break;
default:
log_debug("%s: unexpected imsg %d", __func__,
imsg.hdr.type);
}
}
+ if (!(available_afs & HAVE_IPV4)) {
+ if((err = ub_ctx_set_option(res->ctx, "do-ip4:",
+ "no")) != 0) {
+ ub_ctx_delete(res->ctx);
+ free(res);
+ log_warnx("error setting do-ip4: no: %s",
+ ub_strerror(err));
+ return (NULL);
+ }
+ }
+
+ if (!(available_afs & HAVE_IPV6)) {
+ if((err = ub_ctx_set_option(res->ctx, "do-ip6:",
+ "no")) != 0) {
+ ub_ctx_delete(res->ctx);
+ free(res);
+ log_warnx("error setting do-ip6: no: %s",
+ ub_strerror(err));
+ return (NULL);
+ }
+ }
+
if (!log_getdebug()) {
if((err = ub_ctx_set_option(res->ctx, "use-syslog:",
"no")) != 0) {
-/* $OpenBSD: unwind.c,v 1.56 2021/01/19 16:52:40 florian Exp $ */
+/* $OpenBSD: unwind.c,v 1.57 2021/01/27 08:30:50 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
fatal("route socket");
rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_PROPOSAL)
- | ROUTE_FILTER(RTM_IFANNOUNCE);
+ | ROUTE_FILTER(RTM_IFANNOUNCE) | ROUTE_FILTER(RTM_NEWADDR)
+ | ROUTE_FILTER(RTM_DELADDR);
if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER,
&rtfilter, sizeof(rtfilter)) == -1)
fatal("setsockopt(ROUTE_MSGFILTER)");
-/* $OpenBSD: unwind.h,v 1.52 2021/01/24 18:29:15 florian Exp $ */
+/* $OpenBSD: unwind.h,v 1.53 2021/01/27 08:30:50 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
IMSG_NEW_DNS64_PREFIXES_START,
IMSG_NEW_DNS64_PREFIX,
IMSG_NEW_DNS64_PREFIXES_DONE,
+ IMSG_CHANGE_AFS,
};
struct uw_forwarder {