]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-dns-stub.c
Merge pull request #30284 from YHNdnzj/fstab-wantedby-defaultdeps
[thirdparty/systemd.git] / src / resolve / resolved-dns-stub.c
index 992ae19bbc74c1142a00ac87d8b79764716aaa6b..f43e1f8b617196e2609137d5eca37462449d9eb6 100644 (file)
@@ -3,6 +3,7 @@
 #include <net/if_arp.h>
 #include <netinet/tcp.h>
 
+#include "capability-util.h"
 #include "errno-util.h"
 #include "fd-util.h"
 #include "missing_network.h"
@@ -528,18 +529,26 @@ static int dns_stub_send(
         if (s)
                 r = dns_stream_write_packet(s, reply);
         else {
-                int fd;
+                int fd, ifindex;
 
-                fd = find_socket_fd(m, l, p->family, &p->sender, SOCK_DGRAM);
+                fd = find_socket_fd(m, l, p->family, &p->destination, SOCK_DGRAM);
                 if (fd < 0)
                         return fd;
 
+                if (address_is_proxy(p->family, &p->destination))
+                        /* Force loopback iface if this is the loopback proxy stub
+                         * and ifindex was normalized to 0 by manager_recv(). */
+                        ifindex = p->ifindex ?: LOOPBACK_IFINDEX;
+                else
+                        /* Force loopback iface if this is the main listener stub. */
+                        ifindex = l ? p->ifindex : LOOPBACK_IFINDEX;
+
                 /* Note that it is essential here that we explicitly choose the source IP address for this
                  * packet. This is because otherwise the kernel will choose it automatically based on the
-                 * routing table and will thus pick 127.0.0.1 rather than 127.0.0.53. */
+                 * routing table and will thus pick 127.0.0.1 rather than 127.0.0.53/54. */
                 r = manager_send(m,
                                  fd,
-                                 l || address_is_proxy(p->family, &p->destination) ? p->ifindex : LOOPBACK_IFINDEX, /* force loopback iface if this is the main listener stub */
+                                 ifindex,
                                  p->family, &p->sender, p->sender_port, &p->destination,
                                  reply);
         }
@@ -720,7 +729,8 @@ static int dns_stub_patch_bypass_reply_packet(
         return 0;
 }
 
-static void dns_stub_query_complete(DnsQuery *q) {
+static void dns_stub_query_complete(DnsQuery *query) {
+        _cleanup_(dns_query_freep) DnsQuery *q = query;
         int r;
 
         assert(q);
@@ -741,7 +751,6 @@ static void dns_stub_query_complete(DnsQuery *q) {
                         else
                                 (void) dns_stub_send(q->manager, q->stub_listener_extra, q->request_stream, q->request_packet, reply);
 
-                        dns_query_free(q);
                         return;
                 }
         }
@@ -753,11 +762,8 @@ static void dns_stub_query_complete(DnsQuery *q) {
                         q,
                         dns_query_question_for_protocol(q, DNS_PROTOCOL_DNS),
                         dns_stub_reply_with_edns0_do(q));
-        if (r < 0) {
-                log_debug_errno(r, "Failed to assign sections: %m");
-                dns_query_free(q);
-                return;
-        }
+        if (r < 0)
+                return (void) log_debug_errno(r, "Failed to assign sections: %m");
 
         switch (q->state) {
 
@@ -769,7 +775,7 @@ static void dns_stub_query_complete(DnsQuery *q) {
 
                         cname_result = dns_query_process_cname_one(q);
                         if (cname_result == -ELOOP) { /* CNAME loop, let's send what we already have */
-                                log_debug_errno(r, "Detected CNAME loop, returning what we already have.");
+                                log_debug("Detected CNAME loop, returning what we already have.");
                                 (void) dns_stub_send_reply(q, q->answer_rcode);
                                 break;
                         }
@@ -792,8 +798,9 @@ static void dns_stub_query_complete(DnsQuery *q) {
                                  * now with the redirected question. We'll */
                                 r = dns_query_go(q);
                                 if (r < 0)
-                                        log_debug_errno(r, "Failed to restart query: %m");
+                                        return (void) log_debug_errno(r, "Failed to restart query: %m");
 
+                                TAKE_PTR(q);
                                 return;
                         }
 
@@ -801,11 +808,8 @@ static void dns_stub_query_complete(DnsQuery *q) {
                                         q,
                                         dns_query_question_for_protocol(q, DNS_PROTOCOL_DNS),
                                         dns_stub_reply_with_edns0_do(q));
-                        if (r < 0) {
-                                log_debug_errno(r, "Failed to assign sections: %m");
-                                dns_query_free(q);
-                                return;
-                        }
+                        if (r < 0)
+                                return (void) log_debug_errno(r, "Failed to assign sections: %m");
 
                         if (cname_result == DNS_QUERY_MATCH) /* A match? Then we are done, let's return what we got */
                                 break;
@@ -851,8 +855,6 @@ static void dns_stub_query_complete(DnsQuery *q) {
         default:
                 assert_not_reached();
         }
-
-        dns_query_free(q);
 }
 
 static int dns_stub_stream_complete(DnsStream *s, int error) {
@@ -927,7 +929,7 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
                 return;
         }
 
-        if (dns_type_is_zone_transer(dns_question_first_key(p->question)->type)) {
+        if (dns_type_is_zone_transfer(dns_question_first_key(p->question)->type)) {
                 log_debug("Got request for zone transfer, refusing.");
                 dns_stub_send_failure(m, l, s, p, DNS_RCODE_REFUSED, false);
                 return;
@@ -1037,9 +1039,7 @@ static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void
 }
 
 static int on_dns_stub_packet_extra(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
-        DnsStubListenerExtra *l = userdata;
-
-        assert(l);
+        DnsStubListenerExtra *l = ASSERT_PTR(userdata);
 
         return on_dns_stub_packet_internal(s, fd, revents, l->manager, l);
 }
@@ -1090,9 +1090,8 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void
 }
 
 static int on_dns_stub_stream_extra(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
-        DnsStubListenerExtra *l = userdata;
+        DnsStubListenerExtra *l = ASSERT_PTR(userdata);
 
-        assert(l);
         return on_dns_stub_stream_internal(s, fd, revents, l->manager, l);
 }
 
@@ -1140,7 +1139,7 @@ static int manager_dns_stub_fd(
                 int type) {
 
         sd_event_source **event_source;
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         union sockaddr_union sa;
         int r;
 
@@ -1206,7 +1205,7 @@ static int manager_dns_stub_fd(
                 return -errno;
 
         if (type == SOCK_STREAM &&
-            listen(fd, SOMAXCONN) < 0)
+            listen(fd, SOMAXCONN_DELUXE) < 0)
                 return -errno;
 
         r = sd_event_add_io(m->event, event_source, fd, EPOLLIN,
@@ -1227,7 +1226,7 @@ static int manager_dns_stub_fd(
 
 static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int type) {
         _cleanup_free_ char *pretty = NULL;
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         union sockaddr_union sa;
         int r;
 
@@ -1239,6 +1238,12 @@ static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int ty
         if (*event_source)
                 return sd_event_source_get_io_fd(*event_source);
 
+        if (!have_effective_cap(CAP_NET_BIND_SERVICE) && dns_stub_listener_extra_port(l) < 1024) {
+                log_warning("Missing CAP_NET_BIND_SERVICE capability, not creating extra stub listener on port %hu.",
+                            dns_stub_listener_extra_port(l));
+                return 0;
+        }
+
         if (l->family == AF_INET)
                 sa = (union sockaddr_union) {
                         .in.sin_family = l->family,
@@ -1290,7 +1295,7 @@ static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int ty
                 goto fail;
 
         if (type == SOCK_STREAM &&
-            listen(fd, SOMAXCONN) < 0) {
+            listen(fd, SOMAXCONN_DELUXE) < 0) {
                 r = -errno;
                 goto fail;
         }
@@ -1334,6 +1339,8 @@ int manager_dns_stub_start(Manager *m) {
 
         if (m->dns_stub_listener_mode == DNS_STUB_LISTENER_NO)
                 log_debug("Not creating stub listener.");
+        else if (!have_effective_cap(CAP_NET_BIND_SERVICE))
+                log_warning("Missing CAP_NET_BIND_SERVICE capability, not creating stub listener on port 53.");
         else {
                 static const struct {
                         uint32_t addr;