diff options
| author | Daniel Mack <github@zonque.org> | 2015-07-14 13:26:16 -0400 | 
|---|---|---|
| committer | Daniel Mack <github@zonque.org> | 2015-07-14 13:26:16 -0400 | 
| commit | c0d645b51f6a65a03cce4e29ed276ccdcb5b6ab0 (patch) | |
| tree | fb5f6d2154cb7d2a021a57721f5f92962cd24361 /src/resolve | |
| parent | ca970016b7e5176e94eee3af24a70d5b3355018f (diff) | |
| parent | d20b1667dbab8bccf69735523a0d5fc645e81b80 (diff) | |
Merge pull request #585 from teg/resolved-harden-2
resolved: harden
Diffstat (limited to 'src/resolve')
| -rw-r--r-- | src/resolve/resolved-dns-packet.c | 4 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-packet.h | 3 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-scope.c | 24 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-scope.h | 4 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-server.c | 44 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-server.h | 7 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-transaction.c | 131 | ||||
| -rw-r--r-- | src/resolve/resolved-dns-transaction.h | 12 | ||||
| -rw-r--r-- | src/resolve/resolved-link.c | 23 | ||||
| -rw-r--r-- | src/resolve/resolved-manager.c | 121 | ||||
| -rw-r--r-- | src/resolve/resolved-manager.h | 9 | 
11 files changed, 229 insertions, 153 deletions
| diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index fa0516f8a0..a9cc5ca6aa 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -32,10 +32,10 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {          assert(ret); -        if (mtu <= 0) +        if (mtu <= UDP_PACKET_HEADER_SIZE)                  a = DNS_PACKET_SIZE_START;          else -                a = mtu; +                a = mtu - UDP_PACKET_HEADER_SIZE;          if (a < DNS_PACKET_HEADER_SIZE)                  a = DNS_PACKET_HEADER_SIZE; diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index bf998aa84e..6588ed9df5 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -21,6 +21,8 @@    along with systemd; If not, see <http://www.gnu.org/licenses/>.   ***/ +#include <netinet/udp.h> +#include <netinet/ip.h>  #include "macro.h"  #include "sparse-endian.h" @@ -53,6 +55,7 @@ struct DnsPacketHeader {  };  #define DNS_PACKET_HEADER_SIZE sizeof(DnsPacketHeader) +#define UDP_PACKET_HEADER_SIZE (sizeof(struct iphdr) + sizeof(struct udphdr))  /* The various DNS protocols deviate in how large a packet can grow,     but the TCP transport has a 16bit size field, hence that appears to diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 25392d21d7..7b72c090c2 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -125,7 +125,8 @@ void dns_scope_next_dns_server(DnsScope *s) {                  manager_next_dns_server(s->manager);  } -int dns_scope_emit(DnsScope *s, DnsPacket *p) { +int dns_scope_emit(DnsScope *s, DnsTransaction *t, DnsPacket *p, DnsServer **server) { +        DnsServer *srv = NULL;          union in_addr_union addr;          int ifindex = 0, r;          int family; @@ -144,8 +145,6 @@ int dns_scope_emit(DnsScope *s, DnsPacket *p) {                  mtu = manager_find_mtu(s->manager);          if (s->protocol == DNS_PROTOCOL_DNS) { -                DnsServer *srv; -                  if (DNS_PACKET_QDCOUNT(p) > 1)                          return -EOPNOTSUPP; @@ -160,13 +159,13 @@ int dns_scope_emit(DnsScope *s, DnsPacket *p) {                  if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)                          return -EMSGSIZE; -                if (p->size > mtu) +                if (p->size + UDP_PACKET_HEADER_SIZE > mtu)                          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) @@ -200,10 +199,14 @@ int dns_scope_emit(DnsScope *s, DnsPacket *p) {          if (r < 0)                  return r; +        if (server) +                *server = srv; +          return 1;  } -int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port) { +int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) { +        DnsServer *srv = NULL;          _cleanup_close_ int fd = -1;          union sockaddr_union sa = {};          socklen_t salen; @@ -214,8 +217,6 @@ int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *add          assert((family == AF_UNSPEC) == !address);          if (family == AF_UNSPEC) { -                DnsServer *srv; -                  srv = dns_scope_get_dns_server(s);                  if (!srv)                          return -ESRCH; @@ -288,6 +289,9 @@ int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *add          if (r < 0 && errno != EINPROGRESS)                  return -errno; +        if (server) +                *server = srv; +          ret = fd;          fd = -1; @@ -696,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); +                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 cfbde1343f..5c5ccc71c5 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -65,8 +65,8 @@ 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); -int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port); +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);  int dns_scope_good_key(DnsScope *s, DnsResourceKey *key); diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 9a62a63258..92e48ae442 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -41,6 +41,7 @@ int dns_server_new(          if (!s)                  return -ENOMEM; +        s->n_ref = 1;          s->type = type;          s->family = family;          s->address = *in_addr; @@ -74,33 +75,46 @@ int dns_server_new(          return 0;  } -DnsServer* dns_server_free(DnsServer *s)  { +DnsServer* dns_server_ref(DnsServer *s)  {          if (!s)                  return NULL; -        if (s->link) { -                if (s->type == DNS_SERVER_LINK) -                        LIST_REMOVE(servers, s->link->dns_servers, s); +        assert(s->n_ref > 0); -                if (s->link->current_dns_server == s) -                        link_set_dns_server(s->link, NULL); -        } +        s->n_ref ++; -        if (s->manager) { -                if (s->type == DNS_SERVER_SYSTEM) -                        LIST_REMOVE(servers, s->manager->dns_servers, s); -                else if (s->type == DNS_SERVER_FALLBACK) -                        LIST_REMOVE(servers, s->manager->fallback_dns_servers, s); +        return s; +} + +static DnsServer* dns_server_free(DnsServer *s)  { +        if (!s) +                return NULL; -                if (s->manager->current_dns_server == s) -                        manager_set_dns_server(s->manager, NULL); -        } +        if (s->link && s->link->current_dns_server == s) +                link_set_dns_server(s->link, NULL); + +        if (s->manager && s->manager->current_dns_server == s) +                manager_set_dns_server(s->manager, NULL);          free(s);          return NULL;  } +DnsServer* dns_server_unref(DnsServer *s)  { +        if (!s) +                return NULL; + +        assert(s->n_ref > 0); + +        if (s->n_ref == 1) +                dns_server_free(s); +        else +                s->n_ref --; + +        return NULL; +} +  static unsigned long dns_server_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {          const DnsServer *s = p;          uint64_t u; diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index 70ff35b08f..06059e8829 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -37,6 +37,8 @@ typedef enum DnsServerType {  struct DnsServer {          Manager *manager; +        unsigned n_ref; +          DnsServerType type;          Link *link; @@ -57,6 +59,9 @@ int dns_server_new(                  int family,                  const union in_addr_union *address); -DnsServer* dns_server_free(DnsServer *s); +DnsServer* dns_server_ref(DnsServer *s); +DnsServer* dns_server_unref(DnsServer *s); + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref);  extern const struct hash_ops dns_server_hash_ops; diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 3f4673df7a..e468f245f7 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -39,6 +39,12 @@ 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);          if (t->scope) { @@ -88,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 @@ -237,6 +245,7 @@ static int on_stream_complete(DnsStream *s, int error) {  }  static int dns_transaction_open_tcp(DnsTransaction *t) { +        _cleanup_(dns_server_unrefp) DnsServer *server = NULL;          _cleanup_close_ int fd = -1;          int r; @@ -246,12 +255,12 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {                  return 0;          if (t->scope->protocol == DNS_PROTOCOL_DNS) -                fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53); +                fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);          else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {                  /* When we already received a query to this (but it was truncated), send to its sender address */                  if (t->received) -                        fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port); +                        fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);                  else {                          union in_addr_union address;                          int family = AF_UNSPEC; @@ -265,7 +274,7 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {                          if (r == 0)                                  return -EINVAL; -                        fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT); +                        fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);                  }          } else                  return -EAFNOSUPPORT; @@ -285,6 +294,9 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {                  return r;          } + +        dns_server_unref(t->server); +        t->server = dns_server_ref(server);          t->received = dns_packet_unref(t->received);          t->stream->complete = on_stream_complete;          t->stream->transaction = t; @@ -333,10 +345,15 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {          if (t->scope->protocol == DNS_PROTOCOL_DNS) {                  /* For DNS we are fine with accepting packets on any -                 * interface, but the source IP address must be one of -                 * a valid DNS server */ +                 * interface, but the source IP address must be the +                 * one of the DNS server we queried */ + +                assert(t->server); -                if (!dns_scope_good_dns_server(t->scope, p->family, &p->sender)) +                if (t->server->family != p->family) +                        return; + +                if (!in_addr_equal(p->family, &p->sender, &t->server->address))                          return;                  if (p->sender_port != 53) @@ -398,6 +415,11 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {                  return;          } +        /* Only consider responses with equivalent query section to the request */ +        if (!dns_question_is_superset(p->question, t->question) || +            !dns_question_is_superset(t->question, p->question)) +                dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); +          /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */          dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender); @@ -492,6 +514,7 @@ int dns_transaction_go(DnsTransaction *t) {          }          t->n_attempts++; +        t->server = dns_server_unref(t->server);          t->received = dns_packet_unref(t->received);          t->cached = dns_answer_unref(t->cached);          t->cached_rcode = 0; @@ -571,17 +594,20 @@ int dns_transaction_go(DnsTransaction *t) {                   * always be made via TCP on LLMNR */                  r = dns_transaction_open_tcp(t);          } else { +                DnsServer *server; +                  /* Try via UDP, and if that fails due to large size try via TCP */ -                r = dns_scope_emit(t->scope, t->sent); -                if (r == -EMSGSIZE) +                r = dns_scope_emit(t->scope, t, t->sent, &server); +                if (r >= 0) +                        t->server = dns_server_ref(server); +                else if (r == -EMSGSIZE)                          r = dns_transaction_open_tcp(t);          }          if (r == -ESRCH) {                  /* No servers to send this to? */                  dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);                  return 0; -        } -        if (r < 0) { +        } else if (r < 0) {                  if (t->scope->protocol != DNS_PROTOCOL_DNS) {                          dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);                          return 0; @@ -606,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 f6d539d315..87f342ca11 100644 --- a/src/resolve/resolved-dns-transaction.h +++ b/src/resolve/resolved-dns-transaction.h @@ -61,6 +61,15 @@ 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; +          /* TCP connection logic, if we need it */          DnsStream *stream; @@ -86,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-link.c b/src/resolve/resolved-link.c index ff8dc3a5bc..d66b3a88fc 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -58,7 +58,6 @@ int link_new(Manager *m, Link **ret, int ifindex) {  }  Link *link_free(Link *l) { -          if (!l)                  return NULL; @@ -68,8 +67,12 @@ Link *link_free(Link *l) {          if (l->manager)                  hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex)); -        while (l->dns_servers) -                dns_server_free(l->dns_servers); +        while (l->dns_servers) { +                DnsServer *s = l->dns_servers; + +                LIST_REMOVE(servers, l->dns_servers, s); +                dns_server_unref(s); +        }          dns_scope_free(l->unicast_scope);          dns_scope_free(l->llmnr_ipv4_scope); @@ -182,14 +185,20 @@ static int link_update_dns_servers(Link *l) {          }          LIST_FOREACH_SAFE(servers, s, nx, l->dns_servers) -                if (s->marked) -                        dns_server_free(s); +                if (s->marked) { +                        LIST_REMOVE(servers, l->dns_servers, s); +                        dns_server_unref(s); +                }          return 0;  clear: -        while (l->dns_servers) -                dns_server_free(l->dns_servers); +        while (l->dns_servers) { +                s = l->dns_servers; + +                LIST_REMOVE(servers, l->dns_servers, s); +                dns_server_unref(s); +        }          return r;  } diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 6785a2e3c7..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); @@ -603,8 +597,10 @@ int manager_read_resolv_conf(Manager *m) {          }          LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers) -                if (s->marked) -                        dns_server_free(s); +                if (s->marked) { +                        LIST_REMOVE(servers, m->dns_servers, s); +                        dns_server_unref(s); +                }          /* Whenever /etc/resolv.conf changes, start using the first           * DNS server of it. This is useful to deal with broken @@ -619,8 +615,12 @@ int manager_read_resolv_conf(Manager *m) {          return 0;  clear: -        while (m->dns_servers) -                dns_server_free(m->dns_servers); +        while (m->dns_servers) { +                s = m->dns_servers; + +                LIST_REMOVE(servers, m->dns_servers, s); +                dns_server_unref(s); +        }          return r;  } @@ -923,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; @@ -1381,15 +1298,25 @@ void manager_verify_all(Manager *m) {  }  void manager_flush_dns_servers(Manager *m, DnsServerType t) { +        DnsServer *s; +          assert(m);          if (t == DNS_SERVER_SYSTEM) -                while (m->dns_servers) -                        dns_server_free(m->dns_servers); +                while (m->dns_servers) { +                        s = m->dns_servers; + +                        LIST_REMOVE(servers, m->dns_servers, s); +                        dns_server_unref(s); +                }          if (t == DNS_SERVER_FALLBACK) -                while (m->fallback_dns_servers) -                        dns_server_free(m->fallback_dns_servers); +                while (m->fallback_dns_servers) { +                        s = m->fallback_dns_servers; + +                        LIST_REMOVE(servers, m->fallback_dns_servers, s); +                        dns_server_unref(s); +                }  }  static const char* const support_table[_SUPPORT_MAX] = { 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); | 
