Ignore:
Timestamp:
Jun 11, 2007 4:47:51 PM (17 years ago)
Author:
bennylp
Message:

Ticket #329: Added utility function to parse DNS A response in PJLIB-UTIL

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c

    r1348 r1356  
    425425 
    426426    PJ_ASSERT_RETURN(resolver && count && servers, PJ_EINVAL); 
     427    PJ_ASSERT_RETURN(count < PJ_DNS_RESOLVER_MAX_NS, PJ_EINVAL); 
    427428 
    428429    pj_mutex_lock(resolver->mutex); 
     
    801802} 
    802803 
     804 
     805/*  
     806 * DNS response containing A packet.  
     807 */ 
     808PJ_DEF(pj_status_t) pj_dns_parse_a_response(const pj_dns_parsed_packet *pkt, 
     809                                            pj_dns_a_record *rec) 
     810{ 
     811    pj_str_t hostname, alias, *res_name; 
     812    unsigned bufstart = 0; 
     813    unsigned bufleft = sizeof(rec->buf_); 
     814    unsigned i, ansidx; 
     815 
     816    PJ_ASSERT_RETURN(pkt && rec, PJ_EINVAL); 
     817 
     818    /* Init the record */ 
     819    pj_bzero(rec, sizeof(pj_dns_a_record)); 
     820 
     821    /* Return error if there's error in the packet. */ 
     822    if (PJ_DNS_GET_RCODE(pkt->hdr.flags)) 
     823        return PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_GET_RCODE(pkt->hdr.flags)); 
     824 
     825    /* Return error if there's no query section */ 
     826    if (pkt->hdr.qdcount == 0) 
     827        return PJLIB_UTIL_EDNSINANSWER; 
     828 
     829    /* Return error if there's no answer */ 
     830    if (pkt->hdr.anscount == 0) 
     831        return PJLIB_UTIL_EDNSNOANSWERREC; 
     832 
     833    /* Get the hostname from the query. */ 
     834    hostname = pkt->q[0].name; 
     835 
     836    /* Copy hostname to the record */ 
     837    if (hostname.slen > (int)bufleft) { 
     838        return PJ_ENAMETOOLONG; 
     839    } 
     840 
     841    pj_memcpy(&rec->buf_[bufstart], hostname.ptr, hostname.slen); 
     842    rec->name.ptr = &rec->buf_[bufstart]; 
     843    rec->name.slen = hostname.slen; 
     844 
     845    bufstart += hostname.slen; 
     846    bufleft -= hostname.slen; 
     847 
     848    /* Find the first RR which name matches the hostname */ 
     849    for (ansidx=0; ansidx < pkt->hdr.anscount; ++ansidx) { 
     850        if (pj_stricmp(&pkt->ans[ansidx].name, &hostname)==0) 
     851            break; 
     852    } 
     853 
     854    if (ansidx == pkt->hdr.anscount) 
     855        return PJLIB_UTIL_EDNSNOANSWERREC; 
     856 
     857    /* If hostname is a CNAME, get the alias. */ 
     858    if (pkt->ans[ansidx].type == PJ_DNS_TYPE_CNAME) { 
     859        alias = pkt->ans[ansidx].rdata.cname.name; 
     860        res_name = &alias; 
     861    } else if (pkt->ans[ansidx].type == PJ_DNS_TYPE_A) { 
     862        alias.ptr = NULL; 
     863        alias.slen = 0; 
     864        res_name = &hostname; 
     865    } else { 
     866        return PJLIB_UTIL_EDNSINANSWER; 
     867    } 
     868 
     869    /* Copy alias to the record, if present. */ 
     870    if (alias.slen) { 
     871        if (alias.slen > (int)bufleft) 
     872            return PJ_ENAMETOOLONG; 
     873 
     874        pj_memcpy(&rec->buf_[bufstart], alias.ptr, alias.slen); 
     875        rec->alias.ptr = &rec->buf_[bufstart]; 
     876        rec->alias.slen = alias.slen; 
     877 
     878        bufstart += alias.slen; 
     879        bufleft -= alias.slen; 
     880    } 
     881 
     882    /* Now scan the answer for all type A RRs where the name matches 
     883     * hostname or alias. 
     884     */ 
     885    for (i=0; i<pkt->hdr.anscount; ++i) { 
     886        if (pkt->ans[i].type == PJ_DNS_TYPE_A && 
     887            pj_stricmp(&pkt->ans[i].name, res_name)==0 && 
     888            rec->addr_count < PJ_DNS_MAX_IP_IN_A_REC) 
     889        { 
     890            rec->addr[rec->addr_count].s_addr =  
     891                pkt->ans[i].rdata.a.ip_addr.s_addr; 
     892            ++rec->addr_count; 
     893        } 
     894    } 
     895 
     896    if (rec->addr_count == 0) 
     897        return PJLIB_UTIL_EDNSNOANSWERREC; 
     898 
     899    return PJ_SUCCESS; 
     900} 
    803901 
    804902 
     
    10311129 
    10321130    /* Duplicate the packet. 
    1033      * We don't need to keep the query, NS, and AR sections from the packet, 
    1034      * so exclude from duplication. 
     1131     * We don't need to keep the NS and AR sections from the packet, 
     1132     * so exclude from duplication. We do need to keep the Query 
     1133     * section since DNS A parser needs the query section to know 
     1134     * the name being requested. 
    10351135     */ 
    10361136    res_pool = pj_pool_create_on_buf("respool", cache->buf, sizeof(cache->buf)); 
     
    10381138        cache->pkt = NULL; 
    10391139        pj_dns_packet_dup(res_pool, pkt,  
    1040                           PJ_DNS_NO_QD | PJ_DNS_NO_NS | PJ_DNS_NO_AR, 
     1140                          PJ_DNS_NO_NS | PJ_DNS_NO_AR, 
    10411141                          &cache->pkt); 
    10421142    } 
Note: See TracChangeset for help on using the changeset viewer.