| Line | 
      Branch | 
      Exec | 
      Source | 
    
    
      | 1 | 
      
       | 
       | 
      /** | 
    
    
      | 2 | 
      
       | 
       | 
       * This file is part of the CernVM File System. | 
    
    
      | 3 | 
      
       | 
       | 
       */ | 
    
    
      | 4 | 
      
       | 
       | 
       | 
    
    
      | 5 | 
      
       | 
       | 
      #ifndef CVMFS_DNS_H_ | 
    
    
      | 6 | 
      
       | 
       | 
      #define CVMFS_DNS_H_ | 
    
    
      | 7 | 
      
       | 
       | 
       | 
    
    
      | 8 | 
      
       | 
       | 
      #include <stdint.h> | 
    
    
      | 9 | 
      
       | 
       | 
       | 
    
    
      | 10 | 
      
       | 
       | 
      #include <cstdio> | 
    
    
      | 11 | 
      
       | 
       | 
      #include <ctime> | 
    
    
      | 12 | 
      
       | 
       | 
      #include <map> | 
    
    
      | 13 | 
      
       | 
       | 
      #include <set> | 
    
    
      | 14 | 
      
       | 
       | 
      #include <string> | 
    
    
      | 15 | 
      
       | 
       | 
      #include <vector> | 
    
    
      | 16 | 
      
       | 
       | 
       | 
    
    
      | 17 | 
      
       | 
       | 
      #include "duplex_cares.h" | 
    
    
      | 18 | 
      
       | 
       | 
      #include "gtest/gtest_prod.h" | 
    
    
      | 19 | 
      
       | 
       | 
      #include "util/atomic.h" | 
    
    
      | 20 | 
      
       | 
       | 
      #include "util/prng.h" | 
    
    
      | 21 | 
      
       | 
       | 
      #include "util/single_copy.h" | 
    
    
      | 22 | 
      
       | 
       | 
       | 
    
    
      | 23 | 
      
       | 
       | 
      namespace dns { | 
    
    
      | 24 | 
      
       | 
       | 
       | 
    
    
      | 25 | 
      
       | 
       | 
      /** | 
    
    
      | 26 | 
      
       | 
       | 
       * Possible errors when trying to resolve a host name. | 
    
    
      | 27 | 
      
       | 
       | 
       */ | 
    
    
      | 28 | 
      
       | 
       | 
      enum Failures { | 
    
    
      | 29 | 
      
       | 
       | 
        kFailOk = 0, | 
    
    
      | 30 | 
      
       | 
       | 
        kFailInvalidResolvers, | 
    
    
      | 31 | 
      
       | 
       | 
        kFailTimeout, | 
    
    
      | 32 | 
      
       | 
       | 
        kFailInvalidHost, | 
    
    
      | 33 | 
      
       | 
       | 
        kFailUnknownHost,   ///< Resolver returned a negative reply | 
    
    
      | 34 | 
      
       | 
       | 
        kFailMalformed, | 
    
    
      | 35 | 
      
       | 
       | 
        kFailNoAddress,     ///< Resolver returned a positive reply but without IPs | 
    
    
      | 36 | 
      
       | 
       | 
        kFailNotYetResolved, | 
    
    
      | 37 | 
      
       | 
       | 
        kFailOther, | 
    
    
      | 38 | 
      
       | 
       | 
       | 
    
    
      | 39 | 
      
       | 
       | 
        kFailNumEntries | 
    
    
      | 40 | 
      
       | 
       | 
      }; | 
    
    
      | 41 | 
      
       | 
       | 
       | 
    
    
      | 42 | 
      
       | 
       | 
       | 
    
    
      | 43 | 
      
       | 
       | 
      /** | 
    
    
      | 44 | 
      
       | 
       | 
       * Steers IP protocol selection. | 
    
    
      | 45 | 
      
       | 
       | 
       */ | 
    
    
      | 46 | 
      
       | 
       | 
      enum IpPreference { | 
    
    
      | 47 | 
      
       | 
       | 
        // use system default, currently unused and mapped to IPv4 | 
    
    
      | 48 | 
      
       | 
       | 
        kIpPreferSystem = 0, | 
    
    
      | 49 | 
      
       | 
       | 
        kIpPreferV4, | 
    
    
      | 50 | 
      
       | 
       | 
        kIpPreferV6, | 
    
    
      | 51 | 
      
       | 
       | 
      }; | 
    
    
      | 52 | 
      
       | 
       | 
       | 
    
    
      | 53 | 
      
       | 
      16 | 
      inline const char *Code2Ascii(const Failures error) { | 
    
    
      | 54 | 
      
       | 
       | 
        const char *texts[kFailNumEntries + 1]; | 
    
    
      | 55 | 
      
       | 
      16 | 
        texts[0] = "OK"; | 
    
    
      | 56 | 
      
       | 
      16 | 
        texts[1] = "invalid resolver addresses"; | 
    
    
      | 57 | 
      
       | 
      16 | 
        texts[2] = "DNS query timeout"; | 
    
    
      | 58 | 
      
       | 
      16 | 
        texts[3] = "invalid host name to resolve"; | 
    
    
      | 59 | 
      
       | 
      16 | 
        texts[4] = "unknown host name"; | 
    
    
      | 60 | 
      
       | 
      16 | 
        texts[5] = "malformed DNS request"; | 
    
    
      | 61 | 
      
       | 
      16 | 
        texts[6] = "no IP address for host"; | 
    
    
      | 62 | 
      
       | 
      16 | 
        texts[7] = "internal error, not yet resolved"; | 
    
    
      | 63 | 
      
       | 
      16 | 
        texts[8] = "unknown name resolving error"; | 
    
    
      | 64 | 
      
       | 
      16 | 
        texts[9] = "no text"; | 
    
    
      | 65 | 
      
       | 
      16 | 
        return texts[error]; | 
    
    
      | 66 | 
      
       | 
       | 
      } | 
    
    
      | 67 | 
      
       | 
       | 
       | 
    
    
      | 68 | 
      
       | 
       | 
       | 
    
    
      | 69 | 
      
       | 
       | 
      std::string ExtractHost(const std::string &url); | 
    
    
      | 70 | 
      
       | 
       | 
      std::string ExtractPort(const std::string &url); | 
    
    
      | 71 | 
      
       | 
       | 
      std::string RewriteUrl(const std::string &url, const std::string &ip); | 
    
    
      | 72 | 
      
       | 
       | 
      std::string StripIp(const std::string &decorated_ip); | 
    
    
      | 73 | 
      
       | 
       | 
      std::string AddDefaultScheme(const std::string &proxy); | 
    
    
      | 74 | 
      
       | 
       | 
       | 
    
    
      | 75 | 
      
       | 
       | 
       | 
    
    
      | 76 | 
      
       | 
       | 
      /** | 
    
    
      | 77 | 
      
       | 
       | 
       * Stores the resolved IPv4 and IPv6 addresses of a host name including their | 
    
    
      | 78 | 
      
       | 
       | 
       * time to live.  Data in these objects are immutable.  They are created by a | 
    
    
      | 79 | 
      
       | 
       | 
       * a Resolver.  Once the TTL has expired, they become invalid and a new Host | 
    
    
      | 80 | 
      
       | 
       | 
       * object should be fetched from a resolver. | 
    
    
      | 81 | 
      
       | 
       | 
       * | 
    
    
      | 82 | 
      
       | 
       | 
       * A host object can be copied into a new object with an extended deadline. | 
    
    
      | 83 | 
      
       | 
       | 
       * This is useful if an attempt to resolve a name fails where it previously | 
    
    
      | 84 | 
      
       | 
       | 
       * succeeded.  In this case, the extended deadline can be used to delay another | 
    
    
      | 85 | 
      
       | 
       | 
       * name resolution attempt for some grace period. | 
    
    
      | 86 | 
      
       | 
       | 
       * | 
    
    
      | 87 | 
      
       | 
       | 
       * For successful name resolution, the name is the fully qualified domain name, | 
    
    
      | 88 | 
      
       | 
       | 
       * even if a short name was given to the resolver. | 
    
    
      | 89 | 
      
       | 
       | 
       */ | 
    
    
      | 90 | 
      
       | 
       | 
      class Host { | 
    
    
      | 91 | 
      
       | 
       | 
        FRIEND_TEST(T_Dns, HostEquivalent); | 
    
    
      | 92 | 
      
       | 
       | 
        FRIEND_TEST(T_Dns, HostExpired); | 
    
    
      | 93 | 
      
       | 
       | 
        FRIEND_TEST(T_Dns, HostValid); | 
    
    
      | 94 | 
      
       | 
       | 
        FRIEND_TEST(T_Dns, HostExtendDeadline); | 
    
    
      | 95 | 
      
       | 
       | 
        FRIEND_TEST(T_Dns, HostBestAddresses); | 
    
    
      | 96 | 
      
       | 
       | 
        friend class Resolver; | 
    
    
      | 97 | 
      
       | 
       | 
       | 
    
    
      | 98 | 
      
       | 
       | 
       public: | 
    
    
      | 99 | 
      
       | 
       | 
        static Host ExtendDeadline(const Host &original, unsigned seconds_from_now); | 
    
    
      | 100 | 
      
       | 
       | 
        Host(); | 
    
    
      | 101 | 
      
       | 
       | 
        Host(const Host &other); | 
    
    
      | 102 | 
      
       | 
       | 
        Host &operator= (const Host &other); | 
    
    
      | 103 | 
      
       | 
       | 
        bool IsEquivalent(const Host &other) const; | 
    
    
      | 104 | 
      
       | 
       | 
        bool IsExpired() const; | 
    
    
      | 105 | 
      
       | 
       | 
        bool IsValid() const; | 
    
    
      | 106 | 
      
       | 
       | 
       | 
    
    
      | 107 | 
      
       | 
      6 | 
        time_t deadline() const { return deadline_; } | 
    
    
      | 108 | 
      
       | 
      4 | 
        int64_t id() const { return id_; } | 
    
    
      | 109 | 
      
       | 
      56 | 
        bool HasIpv4() const { return !ipv4_addresses_.empty(); } | 
    
    
      | 110 | 
      
       | 
      52 | 
        bool HasIpv6() const { return !ipv6_addresses_.empty(); } | 
    
    
      | 111 | 
      
       | 
      66 | 
        const std::set<std::string> &ipv4_addresses() const { | 
    
    
      | 112 | 
      
       | 
      66 | 
          return ipv4_addresses_; | 
    
    
      | 113 | 
      
       | 
       | 
        } | 
    
    
      | 114 | 
      
       | 
      54 | 
        const std::set<std::string> &ipv6_addresses() const { | 
    
    
      | 115 | 
      
       | 
      54 | 
          return ipv6_addresses_; | 
    
    
      | 116 | 
      
       | 
       | 
        } | 
    
    
      | 117 | 
      
       | 
       | 
        const std::set<std::string> &ViewBestAddresses(IpPreference preference) const; | 
    
    
      | 118 | 
      
       | 
      48 | 
        const std::string &name() const { return name_; } | 
    
    
      | 119 | 
      
       | 
      60 | 
        Failures status() const { return status_; } | 
    
    
      | 120 | 
      
       | 
       | 
       | 
    
    
      | 121 | 
      
       | 
       | 
       private: | 
    
    
      | 122 | 
      
       | 
       | 
        void CopyFrom(const Host &other); | 
    
    
      | 123 | 
      
       | 
       | 
       | 
    
    
      | 124 | 
      
       | 
       | 
         /** | 
    
    
      | 125 | 
      
       | 
       | 
          * Counter that is increased with every creation of a host object.  Allows to | 
    
    
      | 126 | 
      
       | 
       | 
          * distinguish two Host objects with the same host name.  E.g. when the proxy | 
    
    
      | 127 | 
      
       | 
       | 
          * list in Download.cc reads "http://A:3128|http://A:3128". | 
    
    
      | 128 | 
      
       | 
       | 
          */ | 
    
    
      | 129 | 
      
       | 
       | 
        static atomic_int64 global_id_; | 
    
    
      | 130 | 
      
       | 
       | 
       | 
    
    
      | 131 | 
      
       | 
       | 
        /** | 
    
    
      | 132 | 
      
       | 
       | 
         * When the name resolution becomes outdated, in UTC seconds since UNIX epoch. | 
    
    
      | 133 | 
      
       | 
       | 
         * Once the deadline is passed, IsValid returns false. | 
    
    
      | 134 | 
      
       | 
       | 
         */ | 
    
    
      | 135 | 
      
       | 
       | 
        time_t deadline_; | 
    
    
      | 136 | 
      
       | 
       | 
       | 
    
    
      | 137 | 
      
       | 
       | 
        /** | 
    
    
      | 138 | 
      
       | 
       | 
         * The unique id of this instance of Host. | 
    
    
      | 139 | 
      
       | 
       | 
         */ | 
    
    
      | 140 | 
      
       | 
       | 
        int64_t id_; | 
    
    
      | 141 | 
      
       | 
       | 
       | 
    
    
      | 142 | 
      
       | 
       | 
        /** | 
    
    
      | 143 | 
      
       | 
       | 
         * ASCII representation of IPv4 addresses (a.b.c.d), so that they can be | 
    
    
      | 144 | 
      
       | 
       | 
         * readily used by curl. | 
    
    
      | 145 | 
      
       | 
       | 
         */ | 
    
    
      | 146 | 
      
       | 
       | 
        std::set<std::string> ipv4_addresses_; | 
    
    
      | 147 | 
      
       | 
       | 
       | 
    
    
      | 148 | 
      
       | 
       | 
        /** | 
    
    
      | 149 | 
      
       | 
       | 
         * ASCII representation of IPv6 addresses in the form "[a:b:c:d:e:f:g:h]", | 
    
    
      | 150 | 
      
       | 
       | 
         * so that they can be readily used by curl. | 
    
    
      | 151 | 
      
       | 
       | 
         */ | 
    
    
      | 152 | 
      
       | 
       | 
        std::set<std::string> ipv6_addresses_; | 
    
    
      | 153 | 
      
       | 
       | 
       | 
    
    
      | 154 | 
      
       | 
       | 
        /** | 
    
    
      | 155 | 
      
       | 
       | 
         * The host name either fully qualified or within the search domain. | 
    
    
      | 156 | 
      
       | 
       | 
         */ | 
    
    
      | 157 | 
      
       | 
       | 
        std::string name_; | 
    
    
      | 158 | 
      
       | 
       | 
       | 
    
    
      | 159 | 
      
       | 
       | 
        /** | 
    
    
      | 160 | 
      
       | 
       | 
         * Error code of the name resolution that led to this object. | 
    
    
      | 161 | 
      
       | 
       | 
         */ | 
    
    
      | 162 | 
      
       | 
       | 
        Failures status_; | 
    
    
      | 163 | 
      
       | 
       | 
      }; | 
    
    
      | 164 | 
      
       | 
       | 
       | 
    
    
      | 165 | 
      
       | 
       | 
       | 
    
    
      | 166 | 
      
       | 
       | 
      /** | 
    
    
      | 167 | 
      
       | 
       | 
       * Abstract interface of a name resolver.  Returns a Host object upon successful | 
    
    
      | 168 | 
      
       | 
       | 
       * name resolution.  Also provides a vector interface to resolve multiple names | 
    
    
      | 169 | 
      
       | 
       | 
       * in parallel.  Can be configured with DNS servers, with a timeout, and whether | 
    
    
      | 170 | 
      
       | 
       | 
       * to use IPv4 only or not. | 
    
    
      | 171 | 
      
       | 
       | 
       */ | 
    
    
      | 172 | 
      
       | 
       | 
      class Resolver : SingleCopy { | 
    
    
      | 173 | 
      
       | 
       | 
       public: | 
    
    
      | 174 | 
      
       | 
       | 
        /** | 
    
    
      | 175 | 
      
       | 
       | 
         * Enlarge very small TTLs by default to 1 minute. | 
    
    
      | 176 | 
      
       | 
       | 
         */ | 
    
    
      | 177 | 
      
       | 
       | 
        static const unsigned kDefaultMinTtl = 60; | 
    
    
      | 178 | 
      
       | 
       | 
       | 
    
    
      | 179 | 
      
       | 
       | 
        /** | 
    
    
      | 180 | 
      
       | 
       | 
         * Cut off very large TTLs by default to 1 day. | 
    
    
      | 181 | 
      
       | 
       | 
         */ | 
    
    
      | 182 | 
      
       | 
       | 
        static const unsigned kDefaultMaxTtl = 84600; | 
    
    
      | 183 | 
      
       | 
       | 
       | 
    
    
      | 184 | 
      
       | 
       | 
        Resolver(const bool ipv4_only, | 
    
    
      | 185 | 
      
       | 
       | 
                 const unsigned retries, | 
    
    
      | 186 | 
      
       | 
       | 
                 const unsigned timeout_ms); | 
    
    
      | 187 | 
      
       | 
      1110 | 
        virtual ~Resolver() { } | 
    
    
      | 188 | 
      
       | 
       | 
       | 
    
    
      | 189 | 
      
       | 
       | 
        /** | 
    
    
      | 190 | 
      
       | 
       | 
         * A list of new resolvers in the form <IP address>[:port]. | 
    
    
      | 191 | 
      
       | 
       | 
         */ | 
    
    
      | 192 | 
      
       | 
       | 
        virtual bool SetResolvers(const std::vector<std::string> &resolvers) = 0; | 
    
    
      | 193 | 
      
       | 
       | 
        virtual bool SetSearchDomains(const std::vector<std::string> &domains) = 0; | 
    
    
      | 194 | 
      
       | 
       | 
        virtual void SetSystemResolvers() = 0; | 
    
    
      | 195 | 
      
       | 
       | 
        virtual void SetSystemSearchDomains() = 0; | 
    
    
      | 196 | 
      
       | 
       | 
        Host Resolve(const std::string &name); | 
    
    
      | 197 | 
      
       | 
       | 
        void ResolveMany(const std::vector<std::string> &names, | 
    
    
      | 198 | 
      
       | 
       | 
                         std::vector<Host> *hosts); | 
    
    
      | 199 | 
      
       | 
       | 
       | 
    
    
      | 200 | 
      
       | 
      320 | 
        const std::vector<std::string> &domains() const { return domains_; } | 
    
    
      | 201 | 
      
       | 
      506 | 
        bool ipv4_only() const { return ipv4_only_; } | 
    
    
      | 202 | 
      
       | 
      139 | 
        const std::vector<std::string> &resolvers() const { return resolvers_; } | 
    
    
      | 203 | 
      
       | 
      232 | 
        unsigned retries() const { return retries_; } | 
    
    
      | 204 | 
      
       | 
      3488489 | 
        unsigned timeout_ms() const { return timeout_ms_; } | 
    
    
      | 205 | 
      
       | 
      31 | 
        void set_throttle(const unsigned throttle) { throttle_ = throttle; } | 
    
    
      | 206 | 
      
       | 
      30 | 
        unsigned throttle() const { return throttle_; } | 
    
    
      | 207 | 
      
       | 
      64 | 
        void set_min_ttl(unsigned seconds) { min_ttl_ = seconds; } | 
    
    
      | 208 | 
      
       | 
      30 | 
        unsigned min_ttl() const { return min_ttl_; } | 
    
    
      | 209 | 
      
       | 
      64 | 
        void set_max_ttl(unsigned seconds) { max_ttl_ = seconds; } | 
    
    
      | 210 | 
      
       | 
      30 | 
        unsigned max_ttl() const { return max_ttl_; } | 
    
    
      | 211 | 
      
       | 
       | 
       | 
    
    
      | 212 | 
      
       | 
       | 
       protected: | 
    
    
      | 213 | 
      
       | 
       | 
        /** | 
    
    
      | 214 | 
      
       | 
       | 
         * Takes host names and returns the resolved lists of A and AAAA records in | 
    
    
      | 215 | 
      
       | 
       | 
         * the same order.  To keep it simple, returns only a single TTL per host, | 
    
    
      | 216 | 
      
       | 
       | 
         * the lower value of both record types A/AAAA.  The output vectors have | 
    
    
      | 217 | 
      
       | 
       | 
         * the same size as the input vector names.  Names that are handled by the | 
    
    
      | 218 | 
      
       | 
       | 
         * base class are marked with skip[i] set to true. The input names are | 
    
    
      | 219 | 
      
       | 
       | 
         * completed to fully qualified domain names. | 
    
    
      | 220 | 
      
       | 
       | 
         */ | 
    
    
      | 221 | 
      
       | 
       | 
        virtual void DoResolve(const std::vector<std::string> &names, | 
    
    
      | 222 | 
      
       | 
       | 
                               const std::vector<bool> &skip, | 
    
    
      | 223 | 
      
       | 
       | 
                               std::vector<std::vector<std::string> > *ipv4_addresses, | 
    
    
      | 224 | 
      
       | 
       | 
                               std::vector<std::vector<std::string> > *ipv6_addresses, | 
    
    
      | 225 | 
      
       | 
       | 
                               std::vector<Failures> *failures, | 
    
    
      | 226 | 
      
       | 
       | 
                               std::vector<unsigned> *ttls, | 
    
    
      | 227 | 
      
       | 
       | 
                               std::vector<std::string> *fqdns) = 0; | 
    
    
      | 228 | 
      
       | 
       | 
        bool IsIpv4Address(const std::string &address); | 
    
    
      | 229 | 
      
       | 
       | 
        bool IsIpv6Address(const std::string &address); | 
    
    
      | 230 | 
      
       | 
       | 
       | 
    
    
      | 231 | 
      
       | 
       | 
        /** | 
    
    
      | 232 | 
      
       | 
       | 
         * Currently active search domain list | 
    
    
      | 233 | 
      
       | 
       | 
         */ | 
    
    
      | 234 | 
      
       | 
       | 
        std::vector<std::string> domains_; | 
    
    
      | 235 | 
      
       | 
       | 
       | 
    
    
      | 236 | 
      
       | 
       | 
        /** | 
    
    
      | 237 | 
      
       | 
       | 
         * Do not try to get AAAA records if true. | 
    
    
      | 238 | 
      
       | 
       | 
         */ | 
    
    
      | 239 | 
      
       | 
       | 
        bool ipv4_only_; | 
    
    
      | 240 | 
      
       | 
       | 
       | 
    
    
      | 241 | 
      
       | 
       | 
        /** | 
    
    
      | 242 | 
      
       | 
       | 
         * Currently used resolver list in the form <ip address>:<port> | 
    
    
      | 243 | 
      
       | 
       | 
         */ | 
    
    
      | 244 | 
      
       | 
       | 
        std::vector<std::string> resolvers_; | 
    
    
      | 245 | 
      
       | 
       | 
       | 
    
    
      | 246 | 
      
       | 
       | 
        /** | 
    
    
      | 247 | 
      
       | 
       | 
         * 1 + retries_ attempts to unresponsive servers, each attempt bounded by | 
    
    
      | 248 | 
      
       | 
       | 
         * timeout_ms_ | 
    
    
      | 249 | 
      
       | 
       | 
         */ | 
    
    
      | 250 | 
      
       | 
       | 
        unsigned retries_; | 
    
    
      | 251 | 
      
       | 
       | 
       | 
    
    
      | 252 | 
      
       | 
       | 
        /** | 
    
    
      | 253 | 
      
       | 
       | 
         * Timeout in milliseconds for DNS queries.  Zero means no timeout. | 
    
    
      | 254 | 
      
       | 
       | 
         */ | 
    
    
      | 255 | 
      
       | 
       | 
        unsigned timeout_ms_; | 
    
    
      | 256 | 
      
       | 
       | 
       | 
    
    
      | 257 | 
      
       | 
       | 
        /** | 
    
    
      | 258 | 
      
       | 
       | 
         * Limit number of resolved IP addresses.  If throttle_ is 0 it has no effect. | 
    
    
      | 259 | 
      
       | 
       | 
         * Otherwise, if more than thottle_ IPs are registered for a host, only | 
    
    
      | 260 | 
      
       | 
       | 
         * throttle_ randomly picked IPs are returned. | 
    
    
      | 261 | 
      
       | 
       | 
         */ | 
    
    
      | 262 | 
      
       | 
       | 
        unsigned throttle_; | 
    
    
      | 263 | 
      
       | 
       | 
       | 
    
    
      | 264 | 
      
       | 
       | 
        /** | 
    
    
      | 265 | 
      
       | 
       | 
         * Effective minimum TTL, which by default is kDefaultMinTtl | 
    
    
      | 266 | 
      
       | 
       | 
         */ | 
    
    
      | 267 | 
      
       | 
       | 
        unsigned min_ttl_; | 
    
    
      | 268 | 
      
       | 
       | 
       | 
    
    
      | 269 | 
      
       | 
       | 
        /** | 
    
    
      | 270 | 
      
       | 
       | 
         * Effective maximum TTL, which by default is kDefaultMaxTtl | 
    
    
      | 271 | 
      
       | 
       | 
         */ | 
    
    
      | 272 | 
      
       | 
       | 
        unsigned max_ttl_; | 
    
    
      | 273 | 
      
       | 
       | 
       | 
    
    
      | 274 | 
      
       | 
       | 
        /** | 
    
    
      | 275 | 
      
       | 
       | 
         * Required for picking IP addresses in throttle_ | 
    
    
      | 276 | 
      
       | 
       | 
         */ | 
    
    
      | 277 | 
      
       | 
       | 
        Prng prng_; | 
    
    
      | 278 | 
      
       | 
       | 
      }; | 
    
    
      | 279 | 
      
       | 
       | 
       | 
    
    
      | 280 | 
      
       | 
       | 
       | 
    
    
      | 281 | 
      
       | 
       | 
      /** | 
    
    
      | 282 | 
      
       | 
       | 
       * Implementation of the Resolver interface using the c-ares library. | 
    
    
      | 283 | 
      
       | 
       | 
       */ | 
    
    
      | 284 | 
      
       | 
       | 
      class CaresResolver : public Resolver { | 
    
    
      | 285 | 
      
       | 
       | 
        friend class NormalResolver; | 
    
    
      | 286 | 
      
       | 
       | 
       public: | 
    
    
      | 287 | 
      
       | 
       | 
        /** | 
    
    
      | 288 | 
      
       | 
       | 
         * More IP addresses for a single name will be ignored.  Due to c-ares | 
    
    
      | 289 | 
      
       | 
       | 
         * exponential backoff, the number of retries should be limited to 2. | 
    
    
      | 290 | 
      
       | 
       | 
         * That results in 2 apptempts with the given timeout and a third one with | 
    
    
      | 291 | 
      
       | 
       | 
         * the timeout doubled. | 
    
    
      | 292 | 
      
       | 
       | 
         */ | 
    
    
      | 293 | 
      
       | 
       | 
        static const unsigned kMaxAddresses = 16; | 
    
    
      | 294 | 
      
       | 
       | 
       | 
    
    
      | 295 | 
      
       | 
       | 
        static CaresResolver *Create(const bool ipv4_only, | 
    
    
      | 296 | 
      
       | 
       | 
                                     const unsigned retries, | 
    
    
      | 297 | 
      
       | 
       | 
                                     const unsigned timeout_ms); | 
    
    
      | 298 | 
      
       | 
       | 
        virtual ~CaresResolver(); | 
    
    
      | 299 | 
      
       | 
       | 
       | 
    
    
      | 300 | 
      
       | 
       | 
        virtual bool SetResolvers(const std::vector<std::string> &resolvers); | 
    
    
      | 301 | 
      
       | 
       | 
        virtual bool SetSearchDomains(const std::vector<std::string> &domains); | 
    
    
      | 302 | 
      
       | 
       | 
        virtual void SetSystemResolvers(); | 
    
    
      | 303 | 
      
       | 
       | 
        virtual void SetSystemSearchDomains(); | 
    
    
      | 304 | 
      
       | 
       | 
       | 
    
    
      | 305 | 
      
       | 
       | 
       protected: | 
    
    
      | 306 | 
      
       | 
       | 
        CaresResolver(const bool ipv4_only, | 
    
    
      | 307 | 
      
       | 
       | 
                      const unsigned retries, | 
    
    
      | 308 | 
      
       | 
       | 
                      const unsigned timeout_ms); | 
    
    
      | 309 | 
      
       | 
       | 
        virtual void DoResolve(const std::vector<std::string> &names, | 
    
    
      | 310 | 
      
       | 
       | 
                               const std::vector<bool> &skip, | 
    
    
      | 311 | 
      
       | 
       | 
                               std::vector<std::vector<std::string> > *ipv4_addresses, | 
    
    
      | 312 | 
      
       | 
       | 
                               std::vector<std::vector<std::string> > *ipv6_addresses, | 
    
    
      | 313 | 
      
       | 
       | 
                               std::vector<Failures> *failures, | 
    
    
      | 314 | 
      
       | 
       | 
                               std::vector<unsigned> *ttls, | 
    
    
      | 315 | 
      
       | 
       | 
                               std::vector<std::string> *fqdns); | 
    
    
      | 316 | 
      
       | 
       | 
       | 
    
    
      | 317 | 
      
       | 
       | 
       private: | 
    
    
      | 318 | 
      
       | 
       | 
        void WaitOnCares(); | 
    
    
      | 319 | 
      
       | 
       | 
        ares_channel *channel_; | 
    
    
      | 320 | 
      
       | 
       | 
        char *lookup_options_; | 
    
    
      | 321 | 
      
       | 
       | 
        std::vector<std::string> system_resolvers_; | 
    
    
      | 322 | 
      
       | 
       | 
        std::vector<std::string> system_domains_; | 
    
    
      | 323 | 
      
       | 
       | 
      }; | 
    
    
      | 324 | 
      
       | 
       | 
       | 
    
    
      | 325 | 
      
       | 
       | 
       | 
    
    
      | 326 | 
      
       | 
       | 
      /** | 
    
    
      | 327 | 
      
       | 
       | 
       * Resolves against static name information like in /etc/hosts.  Setting | 
    
    
      | 328 | 
      
       | 
       | 
       * resolver addresses is a no-op for this resolver.  Search domains are not | 
    
    
      | 329 | 
      
       | 
       | 
       * automatically found but need to be set.  Not the most efficient | 
    
    
      | 330 | 
      
       | 
       | 
       * implementation but in the context of cvmfs should be called at most every 5 | 
    
    
      | 331 | 
      
       | 
       | 
       * minutes. | 
    
    
      | 332 | 
      
       | 
       | 
       */ | 
    
    
      | 333 | 
      
       | 
       | 
      class HostfileResolver : public Resolver { | 
    
    
      | 334 | 
      
       | 
       | 
        friend class NormalResolver; | 
    
    
      | 335 | 
      
       | 
       | 
       public: | 
    
    
      | 336 | 
      
       | 
       | 
        static HostfileResolver *Create(const std::string &path, bool ipv4_only); | 
    
    
      | 337 | 
      
       | 
       | 
        virtual ~HostfileResolver(); | 
    
    
      | 338 | 
      
       | 
       | 
       | 
    
    
      | 339 | 
      
       | 
      ✗ | 
        virtual bool SetResolvers(const std::vector<std::string> & /* resolvers */) { | 
    
    
      | 340 | 
      
       | 
      ✗ | 
          return true; | 
    
    
      | 341 | 
      
       | 
       | 
        } | 
    
    
      | 342 | 
      
       | 
       | 
        virtual bool SetSearchDomains(const std::vector<std::string> &domains); | 
    
    
      | 343 | 
      
       | 
      ✗ | 
        virtual void SetSystemResolvers() { } | 
    
    
      | 344 | 
      
       | 
       | 
        virtual void SetSystemSearchDomains(); | 
    
    
      | 345 | 
      
       | 
       | 
       | 
    
    
      | 346 | 
      
       | 
       | 
       protected: | 
    
    
      | 347 | 
      
       | 
       | 
        explicit HostfileResolver(const bool ipv4_only); | 
    
    
      | 348 | 
      
       | 
       | 
        virtual void DoResolve(const std::vector<std::string> &names, | 
    
    
      | 349 | 
      
       | 
       | 
                               const std::vector<bool> &skip, | 
    
    
      | 350 | 
      
       | 
       | 
                               std::vector<std::vector<std::string> > *ipv4_addresses, | 
    
    
      | 351 | 
      
       | 
       | 
                               std::vector<std::vector<std::string> > *ipv6_addresses, | 
    
    
      | 352 | 
      
       | 
       | 
                               std::vector<Failures> *failures, | 
    
    
      | 353 | 
      
       | 
       | 
                               std::vector<unsigned> *ttls, | 
    
    
      | 354 | 
      
       | 
       | 
                               std::vector<std::string> *fqdns); | 
    
    
      | 355 | 
      
       | 
       | 
       | 
    
    
      | 356 | 
      
       | 
       | 
       private: | 
    
    
      | 357 | 
      
       | 
       | 
        struct HostEntry { | 
    
    
      | 358 | 
      
       | 
       | 
          std::vector<std::string> ipv4_addresses; | 
    
    
      | 359 | 
      
       | 
       | 
          std::vector<std::string> ipv6_addresses; | 
    
    
      | 360 | 
      
       | 
       | 
        }; | 
    
    
      | 361 | 
      
       | 
       | 
        static const int kIpMaxLength = 45; | 
    
    
      | 362 | 
      
       | 
       | 
        static const int kHostnameMaxLength = 253; | 
    
    
      | 363 | 
      
       | 
       | 
        void ParseHostFile(); | 
    
    
      | 364 | 
      
       | 
       | 
        /** | 
    
    
      | 365 | 
      
       | 
       | 
         * Host names to lists of IPv4 and IPv6 addresses.  Reverse lookup in the | 
    
    
      | 366 | 
      
       | 
       | 
         * hosts file. | 
    
    
      | 367 | 
      
       | 
       | 
         */ | 
    
    
      | 368 | 
      
       | 
       | 
        std::map<std::string, HostEntry> host_map_; | 
    
    
      | 369 | 
      
       | 
       | 
       | 
    
    
      | 370 | 
      
       | 
       | 
        /** | 
    
    
      | 371 | 
      
       | 
       | 
         * Open the file descriptor when the resolver is constructed and only release | 
    
    
      | 372 | 
      
       | 
       | 
         * on destruction.  Thereby we can be relatively sure to not see I/O errors | 
    
    
      | 373 | 
      
       | 
       | 
         * once constructed. | 
    
    
      | 374 | 
      
       | 
       | 
         */ | 
    
    
      | 375 | 
      
       | 
       | 
        FILE *fhosts_; | 
    
    
      | 376 | 
      
       | 
       | 
      }; | 
    
    
      | 377 | 
      
       | 
       | 
       | 
    
    
      | 378 | 
      
       | 
       | 
       | 
    
    
      | 379 | 
      
       | 
       | 
      /** | 
    
    
      | 380 | 
      
       | 
       | 
       * The normal resolver combines Hostfile and C-ares resolver.  First looks up | 
    
    
      | 381 | 
      
       | 
       | 
       * host names in the host file.  All non-matches are looked up by c-ares. | 
    
    
      | 382 | 
      
       | 
       | 
       */ | 
    
    
      | 383 | 
      
       | 
       | 
      class NormalResolver : public Resolver { | 
    
    
      | 384 | 
      
       | 
       | 
        FRIEND_TEST(T_Dns, NormalResolverConstruct); | 
    
    
      | 385 | 
      
       | 
       | 
       | 
    
    
      | 386 | 
      
       | 
       | 
       public: | 
    
    
      | 387 | 
      
       | 
       | 
        static NormalResolver *Create(const bool ipv4_only, | 
    
    
      | 388 | 
      
       | 
       | 
                                      const unsigned retries, | 
    
    
      | 389 | 
      
       | 
       | 
                                      const unsigned timeout_ms); | 
    
    
      | 390 | 
      
       | 
       | 
        virtual bool SetResolvers(const std::vector<std::string> &resolvers); | 
    
    
      | 391 | 
      
       | 
       | 
        virtual bool SetSearchDomains(const std::vector<std::string> &domains); | 
    
    
      | 392 | 
      
       | 
       | 
        virtual void SetSystemResolvers(); | 
    
    
      | 393 | 
      
       | 
       | 
        virtual void SetSystemSearchDomains(); | 
    
    
      | 394 | 
      
       | 
       | 
        virtual ~NormalResolver(); | 
    
    
      | 395 | 
      
       | 
       | 
       | 
    
    
      | 396 | 
      
       | 
       | 
       protected: | 
    
    
      | 397 | 
      
       | 
       | 
        virtual void DoResolve(const std::vector<std::string> &names, | 
    
    
      | 398 | 
      
       | 
       | 
                               const std::vector<bool> &skip, | 
    
    
      | 399 | 
      
       | 
       | 
                               std::vector<std::vector<std::string> > *ipv4_addresses, | 
    
    
      | 400 | 
      
       | 
       | 
                               std::vector<std::vector<std::string> > *ipv6_addresses, | 
    
    
      | 401 | 
      
       | 
       | 
                               std::vector<Failures> *failures, | 
    
    
      | 402 | 
      
       | 
       | 
                               std::vector<unsigned> *ttls, | 
    
    
      | 403 | 
      
       | 
       | 
                               std::vector<std::string> *fqdns); | 
    
    
      | 404 | 
      
       | 
       | 
        NormalResolver(); | 
    
    
      | 405 | 
      
       | 
       | 
       | 
    
    
      | 406 | 
      
       | 
       | 
       private: | 
    
    
      | 407 | 
      
       | 
       | 
        CaresResolver *cares_resolver_; | 
    
    
      | 408 | 
      
       | 
       | 
        HostfileResolver *hostfile_resolver_; | 
    
    
      | 409 | 
      
       | 
       | 
      }; | 
    
    
      | 410 | 
      
       | 
       | 
       | 
    
    
      | 411 | 
      
       | 
       | 
      }  // namespace dns | 
    
    
      | 412 | 
      
       | 
       | 
       | 
    
    
      | 413 | 
      
       | 
       | 
      #endif  // CVMFS_DNS_H_ | 
    
    
      | 414 | 
      
       | 
       | 
       |