--- /dev/null
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include "rgw_common.h"
+#include "rgw_resolve.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+class RGWDNSResolver {
+ list<res_state> states;
+ Mutex lock;
+
+ int get_state(res_state *ps);
+ void put_state(res_state s);
+
+
+public:
+ ~RGWDNSResolver();
+ RGWDNSResolver() : lock("RGWDNSResolver") {}
+ int resolve_cname(const string& hostname, string& cname, bool *found);
+};
+
+RGWDNSResolver::~RGWDNSResolver()
+{
+ list<res_state>::iterator iter;
+ for (iter = states.begin(); iter != states.end(); ++iter) {
+ struct __res_state *s = *iter;
+ delete s;
+ }
+}
+
+
+int RGWDNSResolver::get_state(res_state *ps)
+{
+ lock.Lock();
+ if (!states.empty()) {
+ res_state s = states.front();
+ states.pop_front();
+ lock.Unlock();
+ *ps = s;
+ return 0;
+ }
+ lock.Unlock();
+ struct __res_state *s = new struct __res_state;
+ s->options = 0;
+ if (res_ninit(s) < 0) {
+ delete s;
+ dout(0) << "ERROR: failed to call res_ninit()" << dendl;
+ return -EINVAL;
+ }
+ *ps = s;
+ return 0;
+}
+
+void RGWDNSResolver::put_state(res_state s)
+{
+ Mutex::Locker l(lock);
+ states.push_back(s);
+}
+
+
+int RGWDNSResolver::resolve_cname(const string& hostname, string& cname, bool *found)
+{
+ res_state res;
+
+ *found = false;
+
+ int r = get_state(&res);
+ if (r < 0) {
+ return r;
+ }
+
+ int ret;
+
+#define LARGE_ENOUGH_DNS_BUFSIZE 1024
+ unsigned char buf[LARGE_ENOUGH_DNS_BUFSIZE];
+
+#define MAX_FQDN_SIZE 255
+ char host[MAX_FQDN_SIZE + 1];
+ const char *origname = hostname.c_str();
+ unsigned char *pt, *answer;
+ unsigned char *answend;
+ int len = res_nquery(res, origname, C_IN, T_CNAME, buf, sizeof(buf));
+ if (len < 0) {
+ dout(20) << "res_query() failed" << dendl;
+ ret = 0;
+ goto done;
+ }
+
+ answer = buf;
+ pt = answer + sizeof(HEADER);
+ answend = answer + len;
+
+ /* read query */
+ if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) {
+ dout(0) << "ERROR: dn_expand() failed" << dendl;
+ ret = -EINVAL;
+ goto done;
+ }
+ pt += len;
+
+ if (pt + 4 > answend) {
+ dout(0) << "ERROR: bad reply" << dendl;
+ ret = -EIO;
+ goto done;
+ }
+
+ int type;
+ GETSHORT(type, pt);
+
+ if (type != T_CNAME) {
+ dout(0) << "ERROR: failed response type: type=%d (was expecting " << T_CNAME << ")" << dendl;
+ ret = -EIO;
+ goto done;
+ }
+
+ pt += INT16SZ; /* class */
+
+ /* read answer */
+
+ if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) {
+ ret = 0;
+ goto done;
+ }
+ pt += len;
+ dout(20) << "name=" << host << dendl;
+
+ if (pt + 10 > answend) {
+ dout(0) << "ERROR: bad reply" << dendl;
+ ret = -EIO;
+ goto done;
+ }
+
+ GETSHORT(type, pt);
+ pt += INT16SZ; /* class */
+ pt += INT32SZ; /* ttl */
+ pt += INT16SZ; /* size */
+
+ if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) {
+ ret = 0;
+ goto done;
+ }
+ dout(20) << "cname host=" << host << dendl;
+ cname = host;
+
+ *found = true;
+ ret = 0;
+done:
+ put_state(res);
+ return ret;
+}
+
+RGWResolver::~RGWResolver() {
+ delete resolver;
+}
+RGWResolver::RGWResolver() {
+ resolver = new RGWDNSResolver;
+}
+
+int RGWResolver::resolve_cname(const string& hostname, string& cname, bool *found) {
+ return resolver->resolve_cname(hostname, cname, found);
+};
+
+RGWResolver *rgw_resolver;
+
+
+void rgw_init_resolver()
+{
+ rgw_resolver = new RGWResolver();
+}
#include "rgw_formats.h"
#include "rgw_client_io.h"
+#include "rgw_resolve.h"
#define dout_subsys ceph_subsys_rgw
ldout(s->cct, 10) << "host=" << s->host << " rgw_dns_name=" << g_conf->rgw_dns_name << dendl;
pos = h.find(g_conf->rgw_dns_name);
+ if (g_conf->rgw_resolve_cname && pos < 0) {
+ string cname;
+ bool found;
+ int r = rgw_resolver->resolve_cname(h, cname, &found);
+ if (r < 0) {
+ dout(0) << "WARNING: rgw_resolver->resolve_cname() returned r=" << r << dendl;
+ }
+ if (found) {
+ dout(0) << "resolved host cname " << h << " -> " << cname << dendl;
+ h = cname;
+ pos = h.find(g_conf->rgw_dns_name);
+ }
+ }
+
if (pos > 0 && h[pos - 1] == '.') {
string encoded_bucket = "/";
encoded_bucket.append(h.substr(0, pos-1));