diff options
| -rw-r--r-- | TODO | 1 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-scope.c | 8 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-scope.h | 2 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-transaction.c | 94 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-transaction.h | 9 | ||||
| -rw-r--r-- | src/resolve/resolved-manager.c | 89 | ||||
| -rw-r--r-- | src/resolve/resolved-manager.h | 9 | 
7 files changed, 107 insertions, 105 deletions
| @@ -353,7 +353,6 @@ Features:    - edns0    - dname    - cname on PTR (?) -  - maybe randomize DNS UDP source ports  * Allow multiple ExecStart= for all Type= settings, so that we can cover rescue.service nicely diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 34d4a98e82..7b72c090c2 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -125,7 +125,7 @@ void dns_scope_next_dns_server(DnsScope *s) {                  manager_next_dns_server(s->manager);  } -int dns_scope_emit(DnsScope *s, DnsPacket *p, DnsServer **server) { +int dns_scope_emit(DnsScope *s, DnsTransaction *t, DnsPacket *p, DnsServer **server) {          DnsServer *srv = NULL;          union in_addr_union addr;          int ifindex = 0, r; @@ -163,9 +163,9 @@ int dns_scope_emit(DnsScope *s, DnsPacket *p, DnsServer **server) {                          return -EMSGSIZE;                  if (family == AF_INET) -                        fd = manager_dns_ipv4_fd(s->manager); +                        fd = transaction_dns_ipv4_fd(t);                  else if (family == AF_INET6) -                        fd = manager_dns_ipv6_fd(s->manager); +                        fd = transaction_dns_ipv6_fd(t);                  else                          return -EAFNOSUPPORT;                  if (fd < 0) @@ -700,7 +700,7 @@ static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata                          return 0;                  } -                r = dns_scope_emit(scope, p, NULL); +                r = dns_scope_emit(scope, NULL, p, NULL);                  if (r < 0)                          log_debug_errno(r, "Failed to send conflict packet: %m");          } diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index f836407f9b..5c5ccc71c5 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -65,7 +65,7 @@ struct DnsScope {  int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol p, int family);  DnsScope* dns_scope_free(DnsScope *s); -int dns_scope_emit(DnsScope *s, DnsPacket *p, DnsServer **server); +int dns_scope_emit(DnsScope *s, DnsTransaction *t, DnsPacket *p, DnsServer **server);  int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server);  DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 3260ded424..e468f245f7 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -39,6 +39,11 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {          dns_packet_unref(t->received);          dns_answer_unref(t->cached); +        sd_event_source_unref(t->dns_ipv4_event_source); +        sd_event_source_unref(t->dns_ipv6_event_source); +        safe_close(t->dns_ipv4_fd); +        safe_close(t->dns_ipv6_fd); +          dns_server_unref(t->server);          dns_stream_free(t->stream); @@ -89,6 +94,8 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsQuestion *q) {          if (!t)                  return -ENOMEM; +        t->dns_ipv4_fd = t->dns_ipv6_fd = -1; +          t->question = dns_question_ref(q);          do @@ -590,7 +597,7 @@ int dns_transaction_go(DnsTransaction *t) {                  DnsServer *server;                  /* Try via UDP, and if that fails due to large size try via TCP */ -                r = dns_scope_emit(t->scope, t->sent, &server); +                r = dns_scope_emit(t->scope, t, t->sent, &server);                  if (r >= 0)                          t->server = dns_server_ref(server);                  else if (r == -EMSGSIZE) @@ -625,6 +632,91 @@ int dns_transaction_go(DnsTransaction *t) {          return 1;  } +static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { +        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; +        DnsTransaction *t = userdata; +        int r; + +        assert(t); +        assert(t->scope); + +        r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p); +        if (r <= 0) +                return r; + +        if (dns_packet_validate_reply(p) > 0 && +            DNS_PACKET_ID(p) == t->id) { +                dns_transaction_process_reply(t, p); +        } else +                log_debug("Invalid DNS packet."); + +        return 0; +} + +int transaction_dns_ipv4_fd(DnsTransaction *t) { +        const int one = 1; +        int r; + +        assert(t); +        assert(t->scope); +        assert(t->scope->manager); + +        if (t->dns_ipv4_fd >= 0) +                return t->dns_ipv4_fd; + +        t->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); +        if (t->dns_ipv4_fd < 0) +                return -errno; + +        r = setsockopt(t->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); +        if (r < 0) { +                r = -errno; +                goto fail; +        } + +        r = sd_event_add_io(t->scope->manager->event, &t->dns_ipv4_event_source, t->dns_ipv4_fd, EPOLLIN, on_dns_packet, t); +        if (r < 0) +                goto fail; + +        return t->dns_ipv4_fd; + +fail: +        t->dns_ipv4_fd = safe_close(t->dns_ipv4_fd); +        return r; +} + +int transaction_dns_ipv6_fd(DnsTransaction *t) { +        const int one = 1; +        int r; + +        assert(t); +        assert(t->scope); +        assert(t->scope->manager); + +        if (t->dns_ipv6_fd >= 0) +                return t->dns_ipv6_fd; + +        t->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); +        if (t->dns_ipv6_fd < 0) +                return -errno; + +        r = setsockopt(t->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); +        if (r < 0) { +                r = -errno; +                goto fail; +        } + +        r = sd_event_add_io(t->scope->manager->event, &t->dns_ipv6_event_source, t->dns_ipv6_fd, EPOLLIN, on_dns_packet, t); +        if (r < 0) +                goto fail; + +        return t->dns_ipv6_fd; + +fail: +        t->dns_ipv6_fd = safe_close(t->dns_ipv6_fd); +        return r; +} +  static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {          [DNS_TRANSACTION_NULL] = "null",          [DNS_TRANSACTION_PENDING] = "pending", diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h index 42f846e7d1..87f342ca11 100644 --- a/src/resolve/resolved-dns-transaction.h +++ b/src/resolve/resolved-dns-transaction.h @@ -61,6 +61,12 @@ struct DnsTransaction {          sd_event_source *timeout_event_source;          unsigned n_attempts; +        int dns_ipv4_fd; +        int dns_ipv6_fd; + +        sd_event_source *dns_ipv4_event_source; +        sd_event_source *dns_ipv6_event_source; +          /* the active server */          DnsServer *server; @@ -89,6 +95,9 @@ int dns_transaction_go(DnsTransaction *t);  void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p);  void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state); +int transaction_dns_ipv4_fd(DnsTransaction *t); +int transaction_dns_ipv6_fd(DnsTransaction *t); +  const char* dns_transaction_state_to_string(DnsTransactionState p) _const_;  DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_; diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index e050092a12..17de14bae1 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -404,7 +404,6 @@ int manager_new(Manager **ret) {          if (!m)                  return -ENOMEM; -        m->dns_ipv4_fd = m->dns_ipv6_fd = -1;          m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;          m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;          m->hostname_fd = -1; @@ -486,11 +485,6 @@ Manager *manager_free(Manager *m) {          sd_event_source_unref(m->network_event_source);          sd_network_monitor_unref(m->network_monitor); -        sd_event_source_unref(m->dns_ipv4_event_source); -        sd_event_source_unref(m->dns_ipv6_event_source); -        safe_close(m->dns_ipv4_fd); -        safe_close(m->dns_ipv6_fd); -          manager_llmnr_stop(m);          sd_bus_slot_unref(m->prepare_for_sleep_slot); @@ -929,89 +923,6 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {          return 1;  } -static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { -        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; -        DnsTransaction *t = NULL; -        Manager *m = userdata; -        int r; - -        r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p); -        if (r <= 0) -                return r; - -        if (dns_packet_validate_reply(p) > 0) { -                t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p))); -                if (!t) -                        return 0; - -                dns_transaction_process_reply(t, p); - -        } else -                log_debug("Invalid DNS packet."); - -        return 0; -} - -int manager_dns_ipv4_fd(Manager *m) { -        const int one = 1; -        int r; - -        assert(m); - -        if (m->dns_ipv4_fd >= 0) -                return m->dns_ipv4_fd; - -        m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); -        if (m->dns_ipv4_fd < 0) -                return -errno; - -        r = setsockopt(m->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); -        if (r < 0) { -                r = -errno; -                goto fail; -        } - -        r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_packet, m); -        if (r < 0) -                goto fail; - -        return m->dns_ipv4_fd; - -fail: -        m->dns_ipv4_fd = safe_close(m->dns_ipv4_fd); -        return r; -} - -int manager_dns_ipv6_fd(Manager *m) { -        const int one = 1; -        int r; - -        assert(m); - -        if (m->dns_ipv6_fd >= 0) -                return m->dns_ipv6_fd; - -        m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); -        if (m->dns_ipv6_fd < 0) -                return -errno; - -        r = setsockopt(m->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); -        if (r < 0) { -                r = -errno; -                goto fail; -        } - -        r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_packet, m); -        if (r < 0) -                goto fail; - -        return m->dns_ipv6_fd; - -fail: -        m->dns_ipv6_fd = safe_close(m->dns_ipv6_fd); -        return r; -} -  static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {          int r; diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 4e70a5b500..005f844df2 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -65,12 +65,6 @@ struct Manager {          unsigned n_dns_streams;          /* Unicast dns */ -        int dns_ipv4_fd; -        int dns_ipv6_fd; - -        sd_event_source *dns_ipv4_event_source; -        sd_event_source *dns_ipv6_event_source; -          LIST_HEAD(DnsServer, dns_servers);          LIST_HEAD(DnsServer, fallback_dns_servers);          DnsServer *current_dns_server; @@ -128,9 +122,6 @@ uint32_t manager_find_mtu(Manager *m);  int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p);  int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret); -int manager_dns_ipv4_fd(Manager *m); -int manager_dns_ipv6_fd(Manager *m); -  int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr);  LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr); | 
