summaryrefslogtreecommitdiffstats
path: root/src/common/dns_resolve.h
blob: 59504e156c2d02e589d94c16c0a92ff6fb3535ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2016 SUSE LINUX GmbH
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */
#ifndef CEPH_DNS_RESOLVE_H
#define CEPH_DNS_RESOLVE_H

#include <netinet/in.h>
#ifndef _WIN32
#include <resolv.h>
#endif

#include "common/ceph_mutex.h"
#include "msg/msg_types.h"		// for entity_addr_t

namespace ceph {

/**
 * this class is used to facilitate the testing of
 * resolv.h functions.
 */
class ResolvHWrapper {
  public:
    virtual ~ResolvHWrapper() {}

#ifdef HAVE_RES_NQUERY
    virtual int res_nquery(res_state s, const char *hostname, int cls, int type, 
        u_char *buf, int bufsz);

    virtual int res_nsearch(res_state s, const char *hostname, int cls, int type, 
        u_char *buf, int bufsz);
#else
    virtual int res_query(const char *hostname, int cls, int type,
        u_char *buf, int bufsz);

    virtual int res_search(const char *hostname, int cls, int type,
        u_char *buf, int bufsz);
#endif

};


/**
 * @class DNSResolver
 *
 * This is a singleton class that exposes the functionality of DNS querying.
 */
class DNSResolver {

  public:
    // singleton declaration
    static DNSResolver *get_instance()
    {
      static DNSResolver instance;
      return &instance;
    }
    DNSResolver(DNSResolver const&) = delete;
    void operator=(DNSResolver const&) = delete;

    // this function is used by the unit test
    static DNSResolver *get_instance(ResolvHWrapper *resolv_wrapper) {
      DNSResolver *resolv = DNSResolver::get_instance();
      delete resolv->resolv_h;
      resolv->resolv_h = resolv_wrapper;
      return resolv;
    }

    enum class SRV_Protocol {
      TCP, UDP
    };


    struct Record {
      uint16_t priority;
      uint16_t weight;
      entity_addr_t addr;
    };

    int resolve_cname(CephContext *cct, const std::string& hostname,
        std::string *cname, bool *found);

    /**
     * Resolves the address given a hostname.
     *
     * @param hostname the hostname to resolved
     * @param[out] addr the hostname's address
     * @returns 0 on success, negative error code on failure
     */
    int resolve_ip_addr(CephContext *cct, const std::string& hostname,
        entity_addr_t *addr);

    /**
     * Returns the list of hostnames and addresses that provide a given
     * service configured as DNS SRV records.
     *
     * @param service_name the service name
     * @param trans_protocol the IP protocol used by the service (TCP or UDP)
     * @param[out] srv_hosts the hostname to address map of available hosts
     *             providing the service. If no host exists the map is not
     *             changed.
     * @returns 0 on success, negative error code on failure
     */
    int resolve_srv_hosts(CephContext *cct, const std::string& service_name,
        const SRV_Protocol trans_protocol, std::map<std::string, Record> *srv_hosts);

    /**
     * Returns the list of hostnames and addresses that provide a given
     * service configured as DNS SRV records.
     *
     * @param service_name the service name
     * @param trans_protocol the IP protocol used by the service (TCP or UDP)
     * @param domain the domain of the service
     * @param[out] srv_hosts the hostname to address map of available hosts
     *             providing the service. If no host exists the map is not
     *             changed.
     * @returns 0 on success, negative error code on failure
     */
    int resolve_srv_hosts(CephContext *cct, const std::string& service_name,
        const SRV_Protocol trans_protocol, const std::string& domain,
        std::map<std::string, Record> *srv_hosts);

  private:
    DNSResolver() { resolv_h = new ResolvHWrapper(); }
    ~DNSResolver();

    ceph::mutex lock = ceph::make_mutex("DNSResolver::lock");
    ResolvHWrapper *resolv_h;
#ifdef HAVE_RES_NQUERY
    std::list<res_state> states;

    int get_state(CephContext *cct, res_state *ps);
    void put_state(res_state s);
#endif

#ifndef _WIN32
    /* this private function allows to reuse the res_state structure used
     * by other function of this class
     */
    int resolve_ip_addr(CephContext *cct, res_state *res,
        const std::string& hostname, entity_addr_t *addr);
#endif

    std::string srv_protocol_to_str(SRV_Protocol proto) {
      switch (proto) {
        case SRV_Protocol::TCP:
          return "tcp";
        case SRV_Protocol::UDP:
          return "udp";
      }
      return "";
    }

};

}

#endif