diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2021-01-12 16:40:34 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2021-01-12 16:40:34 +0000 |
commit | 0269460d250706fb2e360dd0bf64adc5fd7b8cc2 (patch) | |
tree | 962fef9006c12f154d4328c2c29c6116e41ea5ff /sbin/unwind/unwind.c | |
parent | 62617ad43e025f2725270d2ac927d1f543d9af49 (diff) |
Implement listening on 53/TCP
Since we are only serving localhost we could get away with doing
serving over UDP only because we have a huge MTU on lo0, it's still
not correct behavior.
This also enables sending truncated answers with TC set if the answer
does not fit into the edns announced udp size.
Testing at least by matthieu, jca, otto, phessler
OK phessler
Diffstat (limited to 'sbin/unwind/unwind.c')
-rw-r--r-- | sbin/unwind/unwind.c | 67 |
1 files changed, 64 insertions, 3 deletions
diff --git a/sbin/unwind/unwind.c b/sbin/unwind/unwind.c index cde7c2d0dc8..c161401cded 100644 --- a/sbin/unwind/unwind.c +++ b/sbin/unwind/unwind.c @@ -1,4 +1,4 @@ -/* $OpenBSD: unwind.c,v 1.52 2020/11/09 04:22:05 tb Exp $ */ +/* $OpenBSD: unwind.c,v 1.53 2021/01/12 16:40:33 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -725,6 +725,7 @@ open_ports(void) { struct addrinfo hints, *res0; int udp4sock = -1, udp6sock = -1, error, bsize = 65535; + int tcp4sock = -1, tcp6sock = -1; int opt = 1; memset(&hints, 0, sizeof(hints)); @@ -773,13 +774,73 @@ open_ports(void) if (res0) freeaddrinfo(res0); - if (udp4sock == -1 && udp6sock == -1) - fatal("could not bind to 127.0.0.1 or ::1 on port 53"); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + error = getaddrinfo("127.0.0.1", "domain", &hints, &res0); + if (!error && res0) { + if ((tcp4sock = socket(res0->ai_family, + res0->ai_socktype | SOCK_NONBLOCK, + res0->ai_protocol)) != -1) { + if (setsockopt(tcp4sock, SOL_SOCKET, SO_REUSEADDR, + &opt, sizeof(opt)) == -1) + log_warn("setting SO_REUSEADDR on socket"); + if (setsockopt(tcp4sock, SOL_SOCKET, SO_SNDBUF, &bsize, + sizeof(bsize)) == -1) + log_warn("setting SO_SNDBUF on socket"); + if (bind(tcp4sock, res0->ai_addr, res0->ai_addrlen) + == -1) { + close(tcp4sock); + tcp4sock = -1; + } + if (listen(tcp4sock, 5) == -1) { + close(tcp4sock); + tcp4sock = -1; + } + } + } + if (res0) + freeaddrinfo(res0); + + hints.ai_family = AF_INET6; + error = getaddrinfo("::1", "domain", &hints, &res0); + if (!error && res0) { + if ((tcp6sock = socket(res0->ai_family, + res0->ai_socktype | SOCK_NONBLOCK, + res0->ai_protocol)) != -1) { + if (setsockopt(tcp6sock, SOL_SOCKET, SO_REUSEADDR, + &opt, sizeof(opt)) == -1) + log_warn("setting SO_REUSEADDR on socket"); + if (setsockopt(tcp6sock, SOL_SOCKET, SO_SNDBUF, &bsize, + sizeof(bsize)) == -1) + log_warn("setting SO_SNDBUF on socket"); + if (bind(tcp6sock, res0->ai_addr, res0->ai_addrlen) + == -1) { + close(tcp6sock); + tcp6sock = -1; + } + if (listen(tcp6sock, 5) == -1) { + close(tcp6sock); + tcp6sock = -1; + } + } + } + if (res0) + freeaddrinfo(res0); + + if ((udp4sock == -1 || tcp4sock == -1) && (udp6sock == -1 || + tcp6sock == -1)) + //fatalx("could not bind to 127.0.0.1 or ::1 on port 53"); + fatalx("could not bind to 127.0.0.1 or ::1 on port 53 %d %d %d %d", udp4sock, tcp4sock, udp6sock, tcp6sock); if (udp4sock != -1) main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, udp4sock); if (udp6sock != -1) main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock); + if (tcp4sock != -1) + main_imsg_compose_frontend_fd(IMSG_TCP4SOCK, 0, tcp4sock); + if (tcp6sock != -1) + main_imsg_compose_frontend_fd(IMSG_TCP6SOCK, 0, tcp6sock); } void |