From fdf444b5c4ec258181715864b53e4d383efaea25 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Fri, 2 Mar 2007 14:51:03 +0000 Subject: Fixed ticket #156: Not enough memory to parse DNS packets in resolver (thanks Frank Wiersma) git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/pjproject-0.5-stable@1033 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib-util/include/pjlib-util/config.h | 9 +++++++++ pjlib-util/include/pjlib-util/dns.h | 19 +++++++++++++++++-- pjlib-util/src/pjlib-util/dns.c | 17 +++++++---------- pjlib-util/src/pjlib-util/dns_dump.c | 5 ++--- pjlib-util/src/pjlib-util/resolver.c | 16 +++++++++------- pjsip/src/pjsip/sip_resolve.c | 20 +++++++++----------- 6 files changed, 53 insertions(+), 33 deletions(-) diff --git a/pjlib-util/include/pjlib-util/config.h b/pjlib-util/include/pjlib-util/config.h index 7abba3c1..5d363b00 100644 --- a/pjlib-util/include/pjlib-util/config.h +++ b/pjlib-util/include/pjlib-util/config.h @@ -169,6 +169,15 @@ #endif +/** + * Size of temporary pool buffer for parsing DNS packets in resolver. + * + * default: 4000 + */ +#ifndef PJ_DNS_RESOLVER_TMP_BUF_SIZE +# define PJ_DNS_RESOLVER_TMP_BUF_SIZE 4000 +#endif + /* ************************************************************************** * SCANNER CONFIGURATION diff --git a/pjlib-util/include/pjlib-util/dns.h b/pjlib-util/include/pjlib-util/dns.h index cebc20f8..4505eb3d 100644 --- a/pjlib-util/include/pjlib-util/dns.h +++ b/pjlib-util/include/pjlib-util/dns.h @@ -25,7 +25,7 @@ * @brief Low level DNS message parsing and packetization. */ #include - +#include PJ_BEGIN_DECL @@ -258,7 +258,7 @@ typedef struct pj_dns_parsed_rr /** A Resource Data (PJ_DNS_TYPE_A, 1) */ struct a { - pj_str_t ip_addr;/**< IP host address string. */ + pj_in_addr ip_addr;/**< IP host address string. */ } a; } rdata; @@ -281,6 +281,19 @@ typedef struct pj_dns_parsed_packet } pj_dns_parsed_packet; +/** + * Option flags to be specified when calling #pj_dns_packet_dup() function. + * These flags can be combined with bitwise OR operation. + */ +enum pj_dns_dup_options +{ + PJ_DNS_NO_QD = 1, /**< Do not duplicate the query section. */ + PJ_DNS_NO_ANS = 2, /**< Do not duplicate the answer section. */ + PJ_DNS_NO_NS = 4, /**< Do not duplicate the NS section. */ + PJ_DNS_NO_AR = 8 /**< Do not duplicate the additional rec section */ +}; + + /** * Create DNS query packet to resolve the specified names. This function * can be used to build any types of DNS query, such as A record or DNS SRV @@ -331,10 +344,12 @@ PJ_DECL(pj_status_t) pj_dns_parse_packet(pj_pool_t *pool, * * @param pool The pool to allocate memory for the duplicated packet. * @param p The DNS packet to be cloned. + * @param options Option flags, from pj_dns_dup_options. * @param p_dst Pointer to store the cloned DNS packet. */ PJ_DECL(void) pj_dns_packet_dup(pj_pool_t *pool, const pj_dns_parsed_packet*p, + unsigned options, pj_dns_parsed_packet **p_dst); diff --git a/pjlib-util/src/pjlib-util/dns.c b/pjlib-util/src/pjlib-util/dns.c index 71bad5b6..a3c3217b 100644 --- a/pjlib-util/src/pjlib-util/dns.c +++ b/pjlib-util/src/pjlib-util/dns.c @@ -340,11 +340,7 @@ static pj_status_t parse_rr(pj_dns_parsed_rr *rr, pj_pool_t *pool, /* Parse some well known records */ if (rr->type == PJ_DNS_TYPE_A) { - pj_in_addr ip_addr; - - pj_memcpy(&ip_addr, p, 4); - pj_strdup2(pool, &rr->rdata.a.ip_addr, pj_inet_ntoa(ip_addr)); - + pj_memcpy(&rr->rdata.a.ip_addr, p, 4); p += 4; } else if (rr->type == PJ_DNS_TYPE_CNAME || @@ -587,7 +583,7 @@ static void copy_rr(pj_pool_t *pool, pj_dns_parsed_rr *dst, apply_name_table(nametable_count, nametable, &src->rdata.srv.target, pool, &dst->rdata.srv.target); } else if (src->type == PJ_DNS_TYPE_A) { - pj_strdup(pool, &dst->rdata.a.ip_addr, &src->rdata.a.ip_addr); + dst->rdata.a.ip_addr.s_addr = src->rdata.a.ip_addr.s_addr; } else if (src->type == PJ_DNS_TYPE_CNAME) { pj_strdup(pool, &dst->rdata.cname.name, &src->rdata.cname.name); } else if (src->type == PJ_DNS_TYPE_NS) { @@ -602,6 +598,7 @@ static void copy_rr(pj_pool_t *pool, pj_dns_parsed_rr *dst, */ PJ_DEF(void) pj_dns_packet_dup(pj_pool_t *pool, const pj_dns_parsed_packet*p, + unsigned options, pj_dns_parsed_packet **p_dst) { pj_dns_parsed_packet *dst; @@ -630,7 +627,7 @@ PJ_DEF(void) pj_dns_packet_dup(pj_pool_t *pool, /* Copy query section */ - if (p->hdr.qdcount) { + if (p->hdr.qdcount && (options & PJ_DNS_NO_QD)==0) { dst->q = pj_pool_alloc(pool, p->hdr.qdcount * sizeof(pj_dns_parsed_query)); for (i=0; ihdr.qdcount; ++i) { @@ -641,7 +638,7 @@ PJ_DEF(void) pj_dns_packet_dup(pj_pool_t *pool, } /* Copy answer section */ - if (p->hdr.anscount) { + if (p->hdr.anscount && (options & PJ_DNS_NO_ANS)==0) { dst->ans = pj_pool_alloc(pool, p->hdr.anscount * sizeof(pj_dns_parsed_rr)); for (i=0; ihdr.anscount; ++i) { @@ -652,7 +649,7 @@ PJ_DEF(void) pj_dns_packet_dup(pj_pool_t *pool, } /* Copy NS section */ - if (p->hdr.nscount) { + if (p->hdr.nscount && (options & PJ_DNS_NO_NS)==0) { dst->ns = pj_pool_alloc(pool, p->hdr.nscount * sizeof(pj_dns_parsed_rr)); for (i=0; ihdr.nscount; ++i) { @@ -663,7 +660,7 @@ PJ_DEF(void) pj_dns_packet_dup(pj_pool_t *pool, } /* Copy additional info section */ - if (p->hdr.arcount) { + if (p->hdr.arcount && (options & PJ_DNS_NO_AR)==0) { dst->arr = pj_pool_alloc(pool, p->hdr.arcount * sizeof(pj_dns_parsed_rr)); for (i=0; ihdr.arcount; ++i) { diff --git a/pjlib-util/src/pjlib-util/dns_dump.c b/pjlib-util/src/pjlib-util/dns_dump.c index 2a3e803d..d493323a 100644 --- a/pjlib-util/src/pjlib-util/dns_dump.c +++ b/pjlib-util/src/pjlib-util/dns_dump.c @@ -115,9 +115,8 @@ static void dump_answer(unsigned index, const pj_dns_parsed_rr *rr) (int)rr->rdata.cname.name.slen, rr->rdata.cname.name.ptr)); } else if (rr->type == PJ_DNS_TYPE_A) { - PJ_LOG(3,(THIS_FILE, " IP address: %.*s", - (int)rr->rdata.a.ip_addr.slen, - rr->rdata.a.ip_addr.ptr)); + PJ_LOG(3,(THIS_FILE, " IP address: %s", + pj_inet_ntoa(rr->rdata.a.ip_addr))); } } diff --git a/pjlib-util/src/pjlib-util/resolver.c b/pjlib-util/src/pjlib-util/resolver.c index 24304482..d4a950e2 100644 --- a/pjlib-util/src/pjlib-util/resolver.c +++ b/pjlib-util/src/pjlib-util/resolver.c @@ -51,6 +51,7 @@ #define RES_BUF_SZ PJ_DNS_RESOLVER_RES_BUF_SIZE #define UDPSZ PJ_DNS_RESOLVER_MAX_UDP_SIZE +#define TMP_SZ PJ_DNS_RESOLVER_TMP_BUF_SIZE /* Nameserver state */ @@ -161,7 +162,7 @@ struct pj_dns_resolver pj_timer_heap_t *timer; /**< Timer instance. */ pj_bool_t own_ioqueue; /**< Do we own ioqueue? */ pj_ioqueue_t *ioqueue; /**< Ioqueue instance. */ - char tmp_pool[1500];/**< Temporary pool buffer. */ + char tmp_pool[TMP_SZ];/**< Temporary pool buffer. */ /* Socket */ pj_sock_t udp_sock; /**< UDP socket. */ @@ -993,11 +994,16 @@ static void update_res_cache(pj_dns_resolver *resolver, } } - /* Duplicate the packet */ + /* Duplicate the packet. + * We don't need to keep the query, NS, and AR sections from the packet, + * so exclude from duplication. + */ res_pool = pj_pool_create_on_buf("respool", cache->buf, sizeof(cache->buf)); PJ_TRY { cache->pkt = NULL; - pj_dns_packet_dup(res_pool, pkt, &cache->pkt); + pj_dns_packet_dup(res_pool, pkt, + PJ_DNS_NO_QD | PJ_DNS_NO_NS | PJ_DNS_NO_AR, + &cache->pkt); } PJ_CATCH_ANY { PJ_LOG(1,(THIS_FILE, @@ -1223,10 +1229,6 @@ static void on_read_complete(pj_ioqueue_key_t *key, } } - /* We don't need NS and query section in the packet, so trim them. */ - dns_pkt->hdr.qdcount = 0; - dns_pkt->hdr.nscount = 0; - /* Save/update response cache. */ update_res_cache(resolver, &q->key, status, PJ_TRUE, dns_pkt); diff --git a/pjsip/src/pjsip/sip_resolve.c b/pjsip/src/pjsip/sip_resolve.c index ec6835a8..8faa57d4 100644 --- a/pjsip/src/pjsip/sip_resolve.c +++ b/pjsip/src/pjsip/sip_resolve.c @@ -535,7 +535,7 @@ static void build_server_entries(struct query *query, for (j=0; jsrv_cnt; ++j) { if (pj_stricmp(&rr->name, &query->srv[j].target_name)==0) { unsigned cnt = query->srv[j].addr_cnt; - query->srv[j].addr[cnt] = pj_inet_addr(&rr->rdata.a.ip_addr); + query->srv[j].addr[cnt].s_addr = rr->rdata.a.ip_addr.s_addr; ++query->srv[j].addr_cnt; ++query->host_resolved; break; @@ -777,29 +777,27 @@ static void dns_callback(void *user_data, } else { unsigned j; - query->srv[i].addr[query->srv[i].addr_cnt++] = - pj_inet_addr(&pkt->ans[0].rdata.a.ip_addr); + query->srv[i].addr[query->srv[i].addr_cnt++].s_addr = + pkt->ans[0].rdata.a.ip_addr.s_addr; PJ_LOG(5,(query->objname, - "DNS A for %.*s: %.*s", + "DNS A for %.*s: %s", (int)query->srv[i].target_name.slen, query->srv[i].target_name.ptr, - (int)pkt->ans[0].rdata.a.ip_addr.slen, - pkt->ans[0].rdata.a.ip_addr.ptr)); + pj_inet_ntoa(pkt->ans[0].rdata.a.ip_addr))); /* Check for multiple IP addresses */ for (j=1; jhdr.anscount && query->srv[i].addr_cnt < ADDR_MAX_COUNT; ++j) { - query->srv[i].addr[query->srv[i].addr_cnt++] = - pj_inet_addr(&pkt->ans[j].rdata.a.ip_addr); + query->srv[i].addr[query->srv[i].addr_cnt++].s_addr = + pkt->ans[j].rdata.a.ip_addr.s_addr; PJ_LOG(5,(query->objname, - "Additional DNS A for %.*s: %.*s", + "Additional DNS A for %.*s: %s", (int)query->srv[i].target_name.slen, query->srv[i].target_name.ptr, - (int)pkt->ans[j].rdata.a.ip_addr.slen, - pkt->ans[j].rdata.a.ip_addr.ptr)); + pj_inet_ntoa(pkt->ans[j].rdata.a.ip_addr))); } } -- cgit v1.2.3