From 848e8f726cd1fb547e78107d722ff912c64e7e52 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 23 Jun 2009 19:47:23 +0000 Subject: [PATCH] Tue Jun 23 08:18:24 CDT 2009 Mikhail Zabaluev * sresolv/sres.c: implemented automatic CNAME resolution Ignore-this: 1483f6b65deb976e372921ef7ff1b0a0 Fixes sf.net bug #2531152 Behavioral change: intermediate CNAME results are not retrieved to the client. The only cases where CNAME results are retrieved are queries for sres_type_cname and sres_qtype_any, meaning no CNAME resolution is performed. git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@13919 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/sofia-sip/.update | 2 +- libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c | 47 +++++++++++-- .../libsofia-sip-ua/sresolv/sres_cache.c | 8 --- .../libsofia-sip-ua/sresolv/test_sresolv.c | 66 +------------------ 4 files changed, 44 insertions(+), 79 deletions(-) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 1efdb4f792..8b7ebea150 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Tue Jun 23 14:45:32 CDT 2009 +Tue Jun 23 14:46:33 CDT 2009 diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c b/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c index 8f91b9724d..e4ed573d79 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c @@ -311,6 +311,7 @@ struct sres_query_s { uint16_t q_retry_count; uint8_t q_n_servers; uint8_t q_i_server; + int8_t q_aliased; int8_t q_edns; uint8_t q_n_subs; sres_query_t *q_subqueries[1 + SRES_MAX_SEARCH]; @@ -3069,6 +3070,18 @@ sres_resend_dns_query(sres_resolver_t *res, sres_query_t *q, int timeout) sres_query_report_error(q, NULL); } +static void +sres_resolve_cname(sres_resolver_t *res, + const sres_query_t *orig_query, + const char *alias) +{ + sres_query_t *query; + query = sres_query_alloc(res, + orig_query->q_callback, orig_query->q_context, orig_query->q_type, + alias); + query->q_aliased = 1; + sres_send_dns_query(res, query); +} /** Get a server by socket */ static @@ -3456,10 +3469,30 @@ sres_resolver_receive(sres_resolver_t *res, int socket) query->q_retry_count++; } else if (!error && reply) { - /* Remove the query from the pending list and notify the listener */ + /* Remove the query from the pending list */ sres_remove_query(res, query, 1); - if (query->q_callback != NULL) - (query->q_callback)(query->q_context, query, reply); + + /* Resolve the CNAME alias, if necessary */ + if (query->q_type != sres_type_cname && query->q_type != sres_qtype_any && + reply[0] && reply[0]->sr_type == sres_type_cname) { + const char *alias = reply[0]->sr_cname[0].cn_cname; + sres_record_t **cached = NULL; + + /* Check for the aliased results in the cache */ + if (sres_cache_get(res->res_cache, query->q_type, alias, &cached) + > 0) { + reply = cached; + } else { + /* Resubmit the query with the aliased name, dropping this result */ + sres_resolve_cname(res, query, alias); + reply = NULL; + } + } + if (reply) { + /* Notify the listener */ + if (query->q_callback != NULL) + (query->q_callback)(query->q_context, query, reply); + } sres_free_query(res, query); } else { @@ -3630,15 +3663,17 @@ sres_decode_msg(sres_resolver_t *res, return -1; } - if (m->m_ancount > 0 && errorcount == 0 && query->q_type < sres_qtype_tsig) { - char b0[8], b1[8]; + if (m->m_ancount > 0 && errorcount == 0 && query->q_type < sres_qtype_tsig + && (query->q_aliased || answers[0]->sr_type != sres_type_cname)) { + for (i = 0; i < m->m_ancount; i++) { if (query->q_type == answers[i]->sr_type) break; } if (i == m->m_ancount) { - /* The queried request was not found. CNAME? */ + char b0[8], b1[8]; + /* The queried request was not found */ SU_DEBUG_5(("sres_decode_msg: sent query %s, got %s\n", sres_record_type(query->q_type, b0), sres_record_type(answers[0]->sr_type, b1))); diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c b/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c index 902cc3651b..1f16588e0a 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c @@ -226,14 +226,6 @@ sres_cache_get0(sres_htable_t *htable, struct frame *f, frame = { previous, domain }; unsigned hash = sres_hash_key(domain = cname->cn_cname); - if (cached) { - if (dcount >= len) - return -1; - cached[dcount] = (sres_record_t *)cname; - cname->cn_record->r_refcount++; - } - dcount++; - /* Check for cname loops */ for (f = previous; f; f = f->previous) { if (su_casematch(domain, f->domain)) diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c b/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c index 5e20e58a47..8c068329a5 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c @@ -998,22 +998,12 @@ int test_cname(sres_context_t *ctx) TEST_1(result = ctx->result); TEST_1(sr = result[0]); TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR); - TEST_1(cn = result[1]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "sip00.example.com."); sres_free_answers(res, ctx->result), ctx->result = NULL; TEST_1(result = sres_cached_answers(res, sres_type_naptr, domain)); TEST_1(sr = result[0]); TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR); - TEST_1(cn = result[1]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "sip00.example.com."); sres_free_answers(res, result), ctx->result = NULL; @@ -1031,24 +1021,14 @@ int test_cname(sres_context_t *ctx) TEST_RUN(ctx); TEST_1(result = ctx->result); - TEST_1(cn = result[0]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "sip00.example.com."); - TEST_1(sr = result[1]); + TEST_1(sr = result[0]); TEST(sr->sr_record->r_class, sres_class_in); TEST(sr->sr_record->r_type, sres_type_a); sres_free_answers(res, ctx->result), ctx->result = NULL; TEST_1(result = sres_cached_answers(res, sres_type_a, domain)); - TEST_1(cn = result[0]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "sip00.example.com."); - TEST_1(sr = result[1]); + TEST_1(sr = result[0]); TEST(sr->sr_record->r_class, sres_class_in); TEST(sr->sr_record->r_type, sres_type_a); @@ -1062,54 +1042,12 @@ int test_cname(sres_context_t *ctx) TEST_1(result = ctx->result); TEST_1(sr = result[0]); TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR); - TEST_1(cn = result[1]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "cloop0.example.com."); - TEST_1(cn = result[2]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "cloop1.example.com."); - TEST_1(cn = result[3]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "cloop2.example.com."); - TEST_1(cn = result[4]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "cloop0.example.com."); - TEST_1(result[5] == NULL); sres_free_answers(res, ctx->result), ctx->result = NULL; TEST_1(result = sres_cached_answers(res, sres_type_a, domain)); TEST_1(sr = result[0]); TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR); - TEST_1(cn = result[1]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "cloop0.example.com."); - TEST_1(cn = result[2]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "cloop1.example.com."); - TEST_1(cn = result[3]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "cloop2.example.com."); - TEST_1(cn = result[4]->sr_cname); - TEST(cn->cn_record->r_class, sres_class_in); - TEST(cn->cn_record->r_type, sres_type_cname); - TEST(cn->cn_record->r_ttl, 60); - TEST_S(cn->cn_cname, "cloop0.example.com."); - TEST_1(result[5] == NULL); sres_free_answers(res, result);