diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2019-03-30 12:52:04 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2019-03-30 12:52:04 +0000 |
commit | 32c306389b4ce7e905ca1cb52854e7887491abf3 (patch) | |
tree | ad0ea37bcbbbd12c8978a8509f545c8e930e563a /sbin | |
parent | e19792ea63b4b8088fe00575bd0d8c591decb817 (diff) |
Shuffle captive portal detection around.
While we are behind a captive portal we have to ask the dhcp provided
resolvers. However it is possible that those resolvers do not like
to talk to unwind because of EDNS0.
Unwind handles this case by closing its listening socket and hands
over to asr. Except for the resolving of the captive portal host which
it still tries to resolve via libunbound.
Turns out there is no need for this we can just use getaddrinfo_async
from asr which then either hits unwind which does the right thing or
unwind closed its listening socket and asr moves on to talk directly
to the dhcp resolvers.
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/unwind/resolver.c | 85 | ||||
-rw-r--r-- | sbin/unwind/unwind.c | 90 | ||||
-rw-r--r-- | sbin/unwind/unwind.h | 4 |
3 files changed, 70 insertions, 109 deletions
diff --git a/sbin/unwind/resolver.c b/sbin/unwind/resolver.c index 9d81b2dcdd5..62623cc58e1 100644 --- a/sbin/unwind/resolver.c +++ b/sbin/unwind/resolver.c @@ -1,4 +1,4 @@ -/* $OpenBSD: resolver.c,v 1.28 2019/03/30 02:12:45 florian Exp $ */ +/* $OpenBSD: resolver.c,v 1.29 2019/03/30 12:52:03 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -126,8 +126,6 @@ void send_resolver_histogram_info(struct uw_resolver *, pid_t); void check_captive_portal(int); void check_captive_portal_timo(int, short, void *); -void check_captive_portal_resolve_done(void *, int, void *, - int, int, char *, int); int check_captive_portal_changed(struct uw_conf *, struct uw_conf *); void trust_anchor_resolve(void); @@ -1423,9 +1421,6 @@ check_captive_portal_timo(int fd, short events, void *arg) void check_captive_portal(int timer_reset) { - struct uw_resolver *res; - int err; - log_debug("%s", __func__); if (resolver_conf->captive_portal_host == NULL) { @@ -1445,83 +1440,7 @@ check_captive_portal(int timer_reset) captive_portal_state = PORTAL_UNKNOWN; - res = forwarder; - - resolver_ref(res); - - if ((err = ub_resolve_event(res->ctx, - resolver_conf->captive_portal_host, LDNS_RR_TYPE_A, - LDNS_RR_CLASS_IN, res, check_captive_portal_resolve_done, - NULL)) != 0) { - log_warn("%s: ub_resolve_async: err: %d, %s", __func__, err, - ub_strerror(err)); - resolver_unref(res); - } -} - -void -check_captive_portal_resolve_done(void *arg, int rcode, void *answer_packet, - int answer_len, int sec, char *why_bogus, int was_ratelimited) -{ - struct uw_resolver *res; - struct ub_result *result; - sldns_buffer *buf; - struct regional *region; - struct sockaddr_in sin; - int i; - char *str, rdata_buf[sizeof("XXX.XXX.XXX.XXX")]; - - res = (struct uw_resolver *)arg; - - if ((result = calloc(1, sizeof(*result))) == NULL) - goto out; - - memset(&sin, 0, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_port = htons(80); - - log_debug("%s: %d", __func__, rcode); - - if ((str = sldns_wire2str_pkt(answer_packet, answer_len)) != NULL) { - log_debug("%s", str); - free(str); - } - - buf = sldns_buffer_new(answer_len); - region = regional_create(); - result->rcode = LDNS_RCODE_SERVFAIL; - if(region && buf) { - sldns_buffer_clear(buf); - sldns_buffer_write(buf, answer_packet, answer_len); - sldns_buffer_flip(buf); - libworker_enter_result(result, buf, region, sec); - result->answer_packet = NULL; - result->answer_len = 0; - sldns_buffer_free(buf); - regional_destroy(region); - - i = 0; - while(result->data[i] != NULL) { - sldns_wire2str_rdata_buf(result->data[i], - result->len[i], rdata_buf, sizeof(rdata_buf), - LDNS_RR_TYPE_A); - log_debug("%s: result[%d] = %d: %s", __func__, i, - result->len[i], rdata_buf); - - memcpy(&sin.sin_addr.s_addr, result->data[i], - sizeof(sin.sin_addr.s_addr)); - log_debug("%s: ip_port: %s", __func__, - ip_port((struct sockaddr *)&sin)); - - resolver_imsg_compose_main(IMSG_OPEN_HTTP_PORT, 0, - &sin, sizeof(sin)); - i++; - } - } -out: - ub_resolve_free(result); - resolver_unref(res); + resolver_imsg_compose_main(IMSG_RESOLVE_CAPTIVE_PORTAL, 0, NULL, 0); } int diff --git a/sbin/unwind/unwind.c b/sbin/unwind/unwind.c index 310cc811a74..23c100dcdb2 100644 --- a/sbin/unwind/unwind.c +++ b/sbin/unwind/unwind.c @@ -1,4 +1,4 @@ -/* $OpenBSD: unwind.c,v 1.19 2019/03/22 10:42:26 jca Exp $ */ +/* $OpenBSD: unwind.c,v 1.20 2019/03/30 12:52:03 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -34,6 +34,7 @@ #include <fcntl.h> #include <imsg.h> #include <netdb.h> +#include <asr.h> #include <pwd.h> #include <stdio.h> #include <stdlib.h> @@ -72,6 +73,8 @@ int main_reload(void); int main_sendall(enum imsg_type, void *, uint16_t); void open_dhcp_lease(int); void open_ports(void); +void resolve_captive_portal(void); +void resolve_captive_portal_done(struct asr_result *, void *); struct uw_conf *main_conf; struct imsgev *iev_frontend; @@ -477,9 +480,8 @@ main_dispatch_resolver(int fd, short event, void *bula) struct imsgev *iev = bula; struct imsgbuf *ibuf; struct imsg imsg; - struct sockaddr_in sin; ssize_t n; - int shut = 0, httpsock; + int shut = 0; ibuf = &iev->ibuf; @@ -503,27 +505,8 @@ main_dispatch_resolver(int fd, short event, void *bula) break; switch (imsg.hdr.type) { - case IMSG_OPEN_HTTP_PORT: - if (IMSG_DATA_SIZE(imsg) != sizeof(sin)) - fatalx("%s: IMSG_OPEN_HTTP_PORT wrong length: " - "%lu", __func__, IMSG_DATA_SIZE(imsg)); - memcpy(&sin, imsg.data, sizeof(sin)); - - if ((httpsock = socket(AF_INET, SOCK_STREAM | - SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { - log_warn("%s: socket", __func__); - break; - } - if (connect(httpsock, (struct sockaddr *)&sin, - sin.sin_len) == -1) { - if (errno != EINPROGRESS) { - log_warn("%s: connect", __func__); - close(httpsock); - break; - } - } - main_imsg_compose_captiveportal_fd(IMSG_HTTPSOCK, 0, - httpsock); + case IMSG_RESOLVE_CAPTIVE_PORTAL: + resolve_captive_portal(); break; default: log_debug("%s: error handling imsg %d", __func__, @@ -938,3 +921,62 @@ open_ports(void) if (udp6sock != -1) main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock); } + +void +resolve_captive_portal(void) +{ + struct addrinfo hints; + void *as; + + if (main_conf->captive_portal_host == NULL) + return; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + + log_debug("%s: %s", __func__, main_conf->captive_portal_host); + + if ((as = getaddrinfo_async(main_conf->captive_portal_host, "www", + &hints, NULL)) != NULL) + event_asr_run(as, resolve_captive_portal_done, NULL); + else + log_warn("%s: getaddrinfo_async", __func__); + +} + +void +resolve_captive_portal_done(struct asr_result *ar, void *arg) +{ + struct addrinfo *res; + int httpsock; + + if (ar->ar_gai_errno) { + log_warnx("%s: %s", __func__, gai_strerror(ar->ar_gai_errno)); + return; + } + + for (res = ar->ar_addrinfo; res; res = res->ai_next) { + if (res->ai_family != PF_INET) + continue; + log_debug("%s: ip_port: %s", __func__, + ip_port(res->ai_addr)); + + if ((httpsock = socket(AF_INET, SOCK_STREAM | + SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { + log_warn("%s: socket", __func__); + break; + } + if (connect(httpsock, res->ai_addr, res->ai_addrlen) == -1) { + if (errno != EINPROGRESS) { + log_warn("%s: connect", __func__); + close(httpsock); + break; + } + } + main_imsg_compose_captiveportal_fd(IMSG_HTTPSOCK, 0, + httpsock); + } + + freeaddrinfo(ar->ar_addrinfo); +} diff --git a/sbin/unwind/unwind.h b/sbin/unwind/unwind.h index a9cf9563647..135aedcdf70 100644 --- a/sbin/unwind/unwind.h +++ b/sbin/unwind/unwind.h @@ -1,4 +1,4 @@ -/* $OpenBSD: unwind.h,v 1.12 2019/03/24 17:55:59 florian Exp $ */ +/* $OpenBSD: unwind.h,v 1.13 2019/03/30 12:52:03 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -97,7 +97,6 @@ enum imsg_type { IMSG_CTL_RESOLVER_HISTOGRAM, IMSG_CTL_END, IMSG_CTL_RECHECK_CAPTIVEPORTAL, - IMSG_OPEN_HTTP_PORT, IMSG_HTTPSOCK, IMSG_CAPTIVEPORTAL_STATE, IMSG_TAFD, @@ -105,6 +104,7 @@ enum imsg_type { IMSG_NEW_TAS_ABORT, IMSG_NEW_TAS_DONE, IMSG_RECHECK_RESOLVERS, + IMSG_RESOLVE_CAPTIVE_PORTAL, }; struct uw_forwarder { |