From: Yehuda Sadeh Date: Mon, 29 Oct 2012 23:46:21 +0000 (-0700) Subject: rgw: resolve hostname dns cname record X-Git-Tag: v0.55~194 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=951c6be42a482e07c9f922d5da4587ecd9d425d8;p=ceph.git rgw: resolve hostname dns cname record Implements #3206 This allows using vanity domains. A CNAME record can now be set for the domain that would point at the rgw instance, with or without a bucket set as a subdomain. Signed-off-by: Yehuda Sadeh --- diff --git a/src/Makefile.am b/src/Makefile.am index dbb37df5fe2..5e86d03c966 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -339,6 +339,7 @@ my_radosgw_ldadd = \ $(PTHREAD_LIBS) -lm $(CRYPTO_LIBS) $(EXTRALIBS) radosgw_SOURCES = \ + rgw/rgw_resolve.cc \ rgw/rgw_rest.cc \ rgw/rgw_rest_swift.cc \ rgw/rgw_rest_s3.cc \ diff --git a/src/common/config_opts.h b/src/common/config_opts.h index c95af92b58b..07149bef079 100644 --- a/src/common/config_opts.h +++ b/src/common/config_opts.h @@ -449,6 +449,7 @@ OPTION(rgw_gc_max_objs, OPT_INT, 32) OPTION(rgw_gc_obj_min_wait, OPT_INT, 2 * 3600) // wait time before object may be handled by gc OPTION(rgw_gc_processor_max_time, OPT_INT, 3600) // total run time for a single gc processor work OPTION(rgw_gc_processor_period, OPT_INT, 3600) // gc processor cycle time +OPTION(rgw_resolve_cname, OPT_BOOL, false) // should rgw try to resolve hostname as a dns cname record // This will be set to true when it is safe to start threads. // Once it is true, it will never change. diff --git a/src/rgw/rgw_main.cc b/src/rgw/rgw_main.cc index a2cf9e13b81..5d9efee3cd4 100644 --- a/src/rgw/rgw_main.cc +++ b/src/rgw/rgw_main.cc @@ -42,6 +42,7 @@ #include "rgw_swift.h" #include "rgw_log.h" #include "rgw_tools.h" +#include "rgw_resolve.h" #include #include @@ -419,6 +420,7 @@ int main(int argc, const char **argv) rgw_tools_init(g_ceph_context); + rgw_init_resolver(); rgw_rest_init(); curl_global_init(CURL_GLOBAL_ALL); diff --git a/src/rgw/rgw_resolve.cc b/src/rgw/rgw_resolve.cc new file mode 100644 index 00000000000..80d94f7153d --- /dev/null +++ b/src/rgw/rgw_resolve.cc @@ -0,0 +1,172 @@ +#include +#include +#include +#include + +#include "rgw_common.h" +#include "rgw_resolve.h" + +#define dout_subsys ceph_subsys_rgw + +class RGWDNSResolver { + list 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::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(); +} diff --git a/src/rgw/rgw_resolve.h b/src/rgw/rgw_resolve.h new file mode 100644 index 00000000000..164a31a0215 --- /dev/null +++ b/src/rgw/rgw_resolve.h @@ -0,0 +1,21 @@ +#ifndef CEPH_RGW_RESOLVE_H +#define CEPH_RGW_RESOLVE_H + +#include "rgw_common.h" + +class RGWDNSResolver; + +class RGWResolver { + RGWDNSResolver *resolver; + + ~RGWResolver(); +public: + RGWResolver(); + int resolve_cname(const string& hostname, string& cname, bool *found); +}; + + +extern void rgw_init_resolver(void); +extern RGWResolver *rgw_resolver; + +#endif diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index 3612a9e6752..e30778c4c20 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -15,6 +15,7 @@ #include "rgw_formats.h" #include "rgw_client_io.h" +#include "rgw_resolve.h" #define dout_subsys ceph_subsys_rgw @@ -993,6 +994,20 @@ int RGWREST::preprocess(struct req_state *s, RGWClientIO *cio) 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));