Changeset 1359


Ignore:
Timestamp:
Jun 11, 2007 4:56:26 PM (12 years ago)
Author:
bennylp
Message:

Ticket #326: added more DNS resolver tests

Location:
pjproject/trunk/pjlib-util/src/pjlib-util-test
Files:
2 edited

Legend:

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

    r1347 r1359  
    2424#define THIS_FILE   "srv_resolver_test.c" 
    2525 
     26//////////////////////////////////////////////////////////////////////////// 
     27/* 
     28 * TODO: create various invalid DNS packets. 
     29 */ 
     30 
     31 
     32//////////////////////////////////////////////////////////////////////////// 
     33 
     34 
    2635#define ACTION_REPLY    0 
    2736#define ACTION_IGNORE   -1 
     
    5867static pj_dns_settings set; 
    5968 
    60 static int print_label(char *start, const pj_str_t *name) 
    61 { 
    62     char *p = (char*) start; 
    63     const char *startlabel, *endlabel; 
    64     char *endname; 
    65  
    66     /* Tokenize name */ 
    67     startlabel = endlabel = name->ptr; 
     69#define MAX_LABEL   32 
     70 
     71struct label_tab 
     72{ 
     73    unsigned count; 
     74 
     75    struct { 
     76        unsigned pos; 
     77        pj_str_t label; 
     78    } a[MAX_LABEL]; 
     79}; 
     80 
     81static void write16(pj_uint8_t *p, pj_uint16_t val) 
     82{ 
     83    p[0] = (pj_uint8_t)(val >> 8); 
     84    p[1] = (pj_uint8_t)(val & 0xFF); 
     85} 
     86 
     87static void write32(pj_uint8_t *p, pj_uint32_t val) 
     88{ 
     89    val = pj_htonl(val); 
     90    pj_memcpy(p, &val, 4); 
     91} 
     92 
     93static int print_name(pj_uint8_t *pkt, int size, 
     94                      pj_uint8_t *pos, const pj_str_t *name, 
     95                      struct label_tab *tab) 
     96{ 
     97    pj_uint8_t *p = pos; 
     98    const char *endlabel, *endname; 
     99    unsigned i; 
     100    pj_str_t label; 
     101 
     102    /* Check if name is in the table */ 
     103    for (i=0; i<tab->count; ++i) { 
     104        if (pj_strcmp(&tab->a[i].label, name)==0) 
     105            break; 
     106    } 
     107 
     108    if (i != tab->count) { 
     109        write16(p, (pj_uint16_t)(tab->a[i].pos | (0xc0 << 8))); 
     110        return 2; 
     111    } else { 
     112        if (tab->count < MAX_LABEL) { 
     113            tab->a[tab->count].pos = (p-pkt); 
     114            tab->a[tab->count].label.ptr = (char*)(p+1); 
     115            tab->a[tab->count].label.slen = name->slen; 
     116            ++tab->count; 
     117        } 
     118    } 
     119 
     120    endlabel = name->ptr; 
    68121    endname = name->ptr + name->slen; 
     122 
     123    label.ptr = (char*)name->ptr; 
     124 
    69125    while (endlabel != endname) { 
     126 
    70127        while (endlabel != endname && *endlabel != '.') 
    71128            ++endlabel; 
    72         *p++ = (char)(endlabel - startlabel); 
    73         pj_memcpy(p, startlabel, endlabel-startlabel); 
    74         p += (endlabel-startlabel); 
     129 
     130        label.slen = (endlabel - label.ptr); 
     131 
     132        if (size < label.slen+1) 
     133            return -1; 
     134 
     135        *p = (pj_uint8_t)label.slen; 
     136        pj_memcpy(p+1, label.ptr, label.slen); 
     137 
     138        size -= (label.slen+1); 
     139        p += (label.slen+1); 
     140 
    75141        if (endlabel != endname && *endlabel == '.') 
    76142            ++endlabel; 
    77         startlabel = endlabel; 
    78     } 
     143        label.ptr = (char*)endlabel; 
     144    } 
     145 
     146    if (size == 0) 
     147        return -1; 
     148 
    79149    *p++ = '\0'; 
    80150 
    81     return p-start; 
    82 } 
    83  
    84 static int print_packet(const pj_dns_parsed_packet *rec, char *packet) 
    85 { 
    86     pj_dns_hdr *hdr; 
    87     char *p; 
     151    return p-pos; 
     152} 
     153 
     154static int print_rr(pj_uint8_t *pkt, int size, pj_uint8_t *pos, 
     155                    const pj_dns_parsed_rr *rr, struct label_tab *tab) 
     156{ 
     157    pj_uint8_t *p = pos; 
     158    int len; 
     159 
     160    len = print_name(pkt, size, pos, &rr->name, tab); 
     161    if (len < 0) 
     162        return -1; 
     163 
     164    p += len; 
     165    size -= len; 
     166 
     167    if (size < 8) 
     168        return -1; 
     169 
     170    pj_assert(rr->dnsclass == 1); 
     171 
     172    write16(p+0, (pj_uint16_t)rr->type);        /* type     */ 
     173    write16(p+2, (pj_uint16_t)rr->dnsclass);    /* class    */ 
     174    write32(p+4, rr->ttl);                      /* TTL      */ 
     175 
     176    p += 8; 
     177    size -= 8; 
     178 
     179    if (rr->type == PJ_DNS_TYPE_A) { 
     180 
     181        if (size < 6) 
     182            return -1; 
     183 
     184        /* RDLEN is 4 */ 
     185        write16(p, 4); 
     186 
     187        /* Address */ 
     188        pj_memcpy(p+2, &rr->rdata.a.ip_addr, 4); 
     189 
     190        p += 6; 
     191        size -= 6; 
     192 
     193    } else if (rr->type == PJ_DNS_TYPE_CNAME || 
     194               rr->type == PJ_DNS_TYPE_NS || 
     195               rr->type == PJ_DNS_TYPE_PTR) { 
     196 
     197        if (size < 4) 
     198            return -1; 
     199 
     200        len = print_name(pkt, size-2, p+2, &rr->rdata.cname.name, tab); 
     201        if (len < 0) 
     202            return -1; 
     203 
     204        write16(p, (pj_uint16_t)len); 
     205 
     206        p += (len + 2); 
     207        size -= (len + 2); 
     208 
     209    } else if (rr->type == PJ_DNS_TYPE_SRV) { 
     210 
     211        if (size < 10) 
     212            return -1; 
     213 
     214        write16(p+2, rr->rdata.srv.prio);   /* Priority */ 
     215        write16(p+4, rr->rdata.srv.weight); /* Weight */ 
     216        write16(p+6, rr->rdata.srv.port);   /* Port */ 
     217 
     218        /* Target */ 
     219        len = print_name(pkt, size-8, p+8, &rr->rdata.srv.target, tab); 
     220        if (len < 0) 
     221            return -1; 
     222 
     223        /* RDLEN */ 
     224        write16(p, (pj_uint16_t)(len + 6)); 
     225 
     226        p += (len + 8); 
     227        size -= (len + 8); 
     228 
     229    } else { 
     230        pj_assert(!"Not supported"); 
     231        return -1; 
     232    } 
     233 
     234    return p-pos; 
     235} 
     236 
     237static int print_packet(const pj_dns_parsed_packet *rec, pj_uint8_t *pkt, 
     238                        int size) 
     239{ 
     240    pj_uint8_t *p = pkt; 
     241    struct label_tab tab; 
    88242    int i, len; 
    89243 
     244    tab.count = 0; 
     245 
     246#if 0 
     247    pj_enter_critical_section(); 
     248    PJ_LOG(3,(THIS_FILE, "Sending response:")); 
     249    pj_dns_dump_packet(rec); 
     250    pj_leave_critical_section(); 
     251#endif 
     252 
     253    pj_assert(sizeof(pj_dns_hdr)==12); 
     254    if (size < sizeof(pj_dns_hdr)) 
     255        return -1; 
     256 
    90257    /* Initialize header */ 
    91     hdr = (pj_dns_hdr*) packet; 
    92     pj_bzero(hdr, sizeof(pj_dns_hdr)); 
    93     hdr->id = pj_htons(rec->hdr.id); 
    94     hdr->flags = pj_htons(rec->hdr.flags); 
    95     hdr->qdcount = pj_htons(rec->hdr.qdcount); 
    96     hdr->anscount = pj_htons(rec->hdr.anscount); 
    97     hdr->nscount = pj_htons(rec->hdr.nscount); 
    98     hdr->arcount = pj_htons(rec->hdr.arcount); 
    99  
    100     p = packet + sizeof(pj_dns_hdr); 
     258    write16(p+0,  rec->hdr.id); 
     259    write16(p+2,  rec->hdr.flags); 
     260    write16(p+4,  rec->hdr.qdcount); 
     261    write16(p+6,  rec->hdr.anscount); 
     262    write16(p+8,  rec->hdr.nscount); 
     263    write16(p+10, rec->hdr.arcount); 
     264 
     265    p = pkt + sizeof(pj_dns_hdr); 
     266    size -= sizeof(pj_dns_hdr); 
    101267 
    102268    /* Print queries */ 
    103269    for (i=0; i<rec->hdr.qdcount; ++i) { 
    104         pj_uint16_t tmp; 
    105  
    106         len = print_label(p, &rec->q[i].name); 
     270 
     271        len = print_name(pkt, size, p, &rec->q[i].name, &tab); 
     272        if (len < 0) 
     273            return -1; 
     274 
    107275        p += len; 
     276        size -= len; 
     277 
     278        if (size < 4) 
     279            return -1; 
    108280 
    109281        /* Set type */ 
    110         tmp = pj_htons((pj_uint16_t)rec->q[i].type); 
    111         pj_memcpy(p, &tmp, 2); 
    112         p += 2; 
     282        write16(p+0, (pj_uint16_t)rec->q[i].type); 
    113283 
    114284        /* Set class (IN=1) */ 
    115         tmp = pj_htons(rec->q[i].dnsclass); 
    116         pj_memcpy(p, &tmp, 2); 
    117         p += 2; 
     285        pj_assert(rec->q[i].dnsclass == 1); 
     286        write16(p+2, rec->q[i].dnsclass); 
     287 
     288        p += 4; 
    118289    } 
    119290 
    120291    /* Print answers */ 
    121292    for (i=0; i<rec->hdr.anscount; ++i) { 
    122         const pj_dns_parsed_rr *rr = &rec->ans[i]; 
    123         pj_uint16_t tmp; 
    124         pj_uint32_t ttl; 
    125  
    126         len = print_label(p, &rr->name); 
     293        len = print_rr(pkt, size, p, &rec->ans[i], &tab); 
     294        if (len < 0) 
     295            return -1; 
     296 
    127297        p += len; 
    128  
    129         /* Set type */ 
    130         tmp = pj_htons((pj_uint16_t)rr->type); 
    131         pj_memcpy(p, &tmp, 2); 
    132         p += 2; 
    133  
    134         /* Set class */ 
    135         tmp = pj_htons((pj_uint16_t)rr->dnsclass); 
    136         pj_memcpy(p, &tmp, 2); 
    137         p += 2; 
    138  
    139         /* Set TTL */ 
    140         ttl = pj_htonl(rr->ttl); 
    141         pj_memcpy(p, &ttl, 4); 
    142         p += 4; 
    143  
    144         if (rr->type == PJ_DNS_TYPE_A) { 
    145  
    146             /* RDLEN is 4 */ 
    147             tmp = pj_htons(4); 
    148             pj_memcpy(p, &tmp, 2); 
    149             p += 2; 
    150  
    151             /* Address */ 
    152             pj_memcpy(p, &rr->rdata.a.ip_addr, 4); 
    153             p += 4; 
    154  
    155         } else if (rr->type == PJ_DNS_TYPE_CNAME || 
    156                    rr->type == PJ_DNS_TYPE_NS) { 
    157  
    158             len = print_label(p+2, &rr->rdata.cname.name); 
    159  
    160             tmp = pj_htons((pj_uint16_t)len); 
    161             pj_memcpy(p, &tmp, 2); 
    162  
    163             p += (len + 2); 
    164  
    165         } else if (rr->type == PJ_DNS_TYPE_SRV) { 
    166  
    167             /* Skip RDLEN (will write later) */ 
    168             char *p_rdlen = p; 
    169  
    170             p += 2; 
    171  
    172             /* Priority */ 
    173             tmp = pj_htons(rr->rdata.srv.prio); 
    174             pj_memcpy(p, &tmp, 2); 
    175             p += 2; 
    176  
    177             /* Weight */ 
    178             tmp = pj_htons(rr->rdata.srv.weight); 
    179             pj_memcpy(p, &tmp, 2); 
    180             p += 2; 
    181  
    182             /* Port */ 
    183             tmp = pj_htons(rr->rdata.srv.port); 
    184             pj_memcpy(p, &tmp, 2); 
    185             p += 2; 
    186  
    187             /* Target */ 
    188             len = print_label(p, &rr->rdata.srv.target); 
    189  
    190             /* Now print RDLEN */ 
    191             tmp = pj_htons((pj_uint16_t)(len + 6)); 
    192             pj_memcpy(p_rdlen, &tmp, 2); 
    193  
    194             p += len; 
    195  
    196         } else { 
    197             pj_assert(!"Not supported"); 
    198         } 
    199     } 
    200  
    201     return p - packet; 
     298        size -= len; 
     299    } 
     300 
     301    /* Print NS records */ 
     302    for (i=0; i<rec->hdr.nscount; ++i) { 
     303        len = print_rr(pkt, size, p, &rec->ns[i], &tab); 
     304        if (len < 0) 
     305            return -1; 
     306 
     307        p += len; 
     308        size -= len; 
     309    } 
     310 
     311    /* Print additional records */ 
     312    for (i=0; i<rec->hdr.arcount; ++i) { 
     313        len = print_rr(pkt, size, p, &rec->arr[i], &tab); 
     314        if (len < 0) 
     315            return -1; 
     316 
     317        p += len; 
     318        size -= len; 
     319    } 
     320 
     321    return p - pkt; 
    202322} 
    203323 
     
    241361        } 
    242362 
     363        /* Verify packet */ 
     364        pj_assert(req->hdr.qdcount == 1); 
     365        pj_assert(req->q[0].dnsclass == 1); 
     366 
    243367        /* Simulate network RTT */ 
    244368        pj_thread_sleep(50); 
     
    248372        } else if (srv->action == ACTION_REPLY) { 
    249373            srv->resp.hdr.id = req->hdr.id; 
    250             pkt_len = print_packet(&srv->resp, pkt); 
     374            pkt_len = print_packet(&srv->resp, (pj_uint8_t*)pkt, sizeof(pkt)); 
    251375            pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len); 
    252376        } else if (srv->action == ACTION_CB) { 
     
    254378            (*srv->action_cb)(req, &resp); 
    255379            resp->hdr.id = req->hdr.id; 
    256             pkt_len = print_packet(resp, pkt); 
     380            pkt_len = print_packet(resp, (pj_uint8_t*)pkt, sizeof(pkt)); 
    257381            pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len); 
    258382        } else if (srv->action > 0) { 
    259383            req->hdr.flags |= PJ_DNS_SET_RCODE(srv->action); 
    260             pkt_len = print_packet(req, pkt); 
     384            pkt_len = print_packet(req, (pj_uint8_t*)pkt, sizeof(pkt)); 
    261385            pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len); 
    262386        } 
     
    364488    pj_sem_destroy(sem); 
    365489    pj_pool_release(pool); 
     490} 
     491 
     492 
     493//////////////////////////////////////////////////////////////////////////// 
     494/* DNS A parser tests */ 
     495static int a_parser_test(void) 
     496{ 
     497    pj_dns_parsed_packet pkt; 
     498    pj_dns_a_record rec; 
     499    pj_status_t rc; 
     500 
     501    PJ_LOG(3,(THIS_FILE, "  DNS A record parser tests")); 
     502 
     503    pkt.q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query); 
     504    pkt.ans = (pj_dns_parsed_rr*) 
     505              pj_pool_calloc(pool, 32, sizeof(pj_dns_parsed_rr)); 
     506 
     507    /* Simple answer with direct A record, but with addition of 
     508     * a CNAME and another A to confuse the parser. 
     509     */ 
     510    PJ_LOG(3,(THIS_FILE, "    A RR with duplicate CNAME/A")); 
     511    pkt.hdr.flags = 0; 
     512    pkt.hdr.qdcount = 1; 
     513    pkt.q[0].type = PJ_DNS_TYPE_A; 
     514    pkt.q[0].dnsclass = 1; 
     515    pkt.q[0].name = pj_str("ahost"); 
     516    pkt.hdr.anscount = 3; 
     517 
     518    /* This is the RR corresponding to the query */ 
     519    pkt.ans[0].name = pj_str("ahost"); 
     520    pkt.ans[0].type = PJ_DNS_TYPE_A; 
     521    pkt.ans[0].dnsclass = 1; 
     522    pkt.ans[0].ttl = 1; 
     523    pkt.ans[0].rdata.a.ip_addr.s_addr = 0x01020304; 
     524 
     525    /* CNAME to confuse the parser */ 
     526    pkt.ans[1].name = pj_str("ahost"); 
     527    pkt.ans[1].type = PJ_DNS_TYPE_CNAME; 
     528    pkt.ans[1].dnsclass = 1; 
     529    pkt.ans[1].ttl = 1; 
     530    pkt.ans[1].rdata.cname.name = pj_str("bhost"); 
     531 
     532    /* DNS A RR to confuse the parser */ 
     533    pkt.ans[2].name = pj_str("bhost"); 
     534    pkt.ans[2].type = PJ_DNS_TYPE_A; 
     535    pkt.ans[2].dnsclass = 1; 
     536    pkt.ans[2].ttl = 1; 
     537    pkt.ans[2].rdata.a.ip_addr.s_addr = 0x0203; 
     538 
     539 
     540    rc = pj_dns_parse_a_response(&pkt, &rec); 
     541    pj_assert(rc == PJ_SUCCESS); 
     542    pj_assert(pj_strcmp2(&rec.name, "ahost")==0); 
     543    pj_assert(rec.alias.slen == 0); 
     544    pj_assert(rec.addr_count == 1); 
     545    pj_assert(rec.addr[0].s_addr == 0x01020304); 
     546 
     547    /* Answer with the target corresponds to a CNAME entry, but not 
     548     * as the first record, and with additions of some CNAME and A 
     549     * entries to confuse the parser. 
     550     */ 
     551    PJ_LOG(3,(THIS_FILE, "    CNAME RR with duplicate CNAME/A")); 
     552    pkt.hdr.flags = 0; 
     553    pkt.hdr.qdcount = 1; 
     554    pkt.q[0].type = PJ_DNS_TYPE_A; 
     555    pkt.q[0].dnsclass = 1; 
     556    pkt.q[0].name = pj_str("ahost"); 
     557    pkt.hdr.anscount = 4; 
     558 
     559    /* This is the DNS A record for the alias */ 
     560    pkt.ans[0].name = pj_str("ahostalias"); 
     561    pkt.ans[0].type = PJ_DNS_TYPE_A; 
     562    pkt.ans[0].dnsclass = 1; 
     563    pkt.ans[0].ttl = 1; 
     564    pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202; 
     565 
     566    /* CNAME entry corresponding to the query */ 
     567    pkt.ans[1].name = pj_str("ahost"); 
     568    pkt.ans[1].type = PJ_DNS_TYPE_CNAME; 
     569    pkt.ans[1].dnsclass = 1; 
     570    pkt.ans[1].ttl = 1; 
     571    pkt.ans[1].rdata.cname.name = pj_str("ahostalias"); 
     572 
     573    /* Another CNAME to confuse the parser */ 
     574    pkt.ans[2].name = pj_str("ahost"); 
     575    pkt.ans[2].type = PJ_DNS_TYPE_CNAME; 
     576    pkt.ans[2].dnsclass = 1; 
     577    pkt.ans[2].ttl = 1; 
     578    pkt.ans[2].rdata.cname.name = pj_str("ahostalias2"); 
     579 
     580    /* Another DNS A to confuse the parser */ 
     581    pkt.ans[3].name = pj_str("ahostalias2"); 
     582    pkt.ans[3].type = PJ_DNS_TYPE_A; 
     583    pkt.ans[3].dnsclass = 1; 
     584    pkt.ans[3].ttl = 1; 
     585    pkt.ans[3].rdata.a.ip_addr.s_addr = 0x03030303; 
     586 
     587    rc = pj_dns_parse_a_response(&pkt, &rec); 
     588    pj_assert(rc == PJ_SUCCESS); 
     589    pj_assert(pj_strcmp2(&rec.name, "ahost")==0); 
     590    pj_assert(pj_strcmp2(&rec.alias, "ahostalias")==0); 
     591    pj_assert(rec.addr_count == 1); 
     592    pj_assert(rec.addr[0].s_addr == 0x02020202); 
     593 
     594    /* 
     595     * No query section. 
     596     */ 
     597    PJ_LOG(3,(THIS_FILE, "    No query section")); 
     598    pkt.hdr.qdcount = 0; 
     599    pkt.hdr.anscount = 0; 
     600 
     601    rc = pj_dns_parse_a_response(&pkt, &rec); 
     602    pj_assert(rc == PJLIB_UTIL_EDNSINANSWER); 
     603 
     604    /* 
     605     * No answer section. 
     606     */ 
     607    PJ_LOG(3,(THIS_FILE, "    No answer section")); 
     608    pkt.hdr.flags = 0; 
     609    pkt.hdr.qdcount = 1; 
     610    pkt.q[0].type = PJ_DNS_TYPE_A; 
     611    pkt.q[0].dnsclass = 1; 
     612    pkt.q[0].name = pj_str("ahost"); 
     613    pkt.hdr.anscount = 0; 
     614 
     615    rc = pj_dns_parse_a_response(&pkt, &rec); 
     616    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC); 
     617 
     618    /* 
     619     * Answer doesn't match query. 
     620     */ 
     621    PJ_LOG(3,(THIS_FILE, "    Answer doesn't match query")); 
     622    pkt.hdr.flags = 0; 
     623    pkt.hdr.qdcount = 1; 
     624    pkt.q[0].type = PJ_DNS_TYPE_A; 
     625    pkt.q[0].dnsclass = 1; 
     626    pkt.q[0].name = pj_str("ahost"); 
     627    pkt.hdr.anscount = 1; 
     628 
     629    /* An answer that doesn't match the query */ 
     630    pkt.ans[0].name = pj_str("ahostalias"); 
     631    pkt.ans[0].type = PJ_DNS_TYPE_A; 
     632    pkt.ans[0].dnsclass = 1; 
     633    pkt.ans[0].ttl = 1; 
     634    pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202; 
     635 
     636    rc = pj_dns_parse_a_response(&pkt, &rec); 
     637    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC); 
     638 
     639 
     640    /* 
     641     * DNS CNAME that doesn't have corresponding DNS A. 
     642     */ 
     643    PJ_LOG(3,(THIS_FILE, "    CNAME with no matching DNS A RR (1)")); 
     644    pkt.hdr.flags = 0; 
     645    pkt.hdr.qdcount = 1; 
     646    pkt.q[0].type = PJ_DNS_TYPE_A; 
     647    pkt.q[0].dnsclass = 1; 
     648    pkt.q[0].name = pj_str("ahost"); 
     649    pkt.hdr.anscount = 1; 
     650 
     651    /* The CNAME */ 
     652    pkt.ans[0].name = pj_str("ahost"); 
     653    pkt.ans[0].type = PJ_DNS_TYPE_CNAME; 
     654    pkt.ans[0].dnsclass = 1; 
     655    pkt.ans[0].ttl = 1; 
     656    pkt.ans[0].rdata.cname.name = pj_str("ahostalias"); 
     657 
     658    rc = pj_dns_parse_a_response(&pkt, &rec); 
     659    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC); 
     660 
     661 
     662    /* 
     663     * DNS CNAME that doesn't have corresponding DNS A. 
     664     */ 
     665    PJ_LOG(3,(THIS_FILE, "    CNAME with no matching DNS A RR (2)")); 
     666    pkt.hdr.flags = 0; 
     667    pkt.hdr.qdcount = 1; 
     668    pkt.q[0].type = PJ_DNS_TYPE_A; 
     669    pkt.q[0].dnsclass = 1; 
     670    pkt.q[0].name = pj_str("ahost"); 
     671    pkt.hdr.anscount = 2; 
     672 
     673    /* The CNAME */ 
     674    pkt.ans[0].name = pj_str("ahost"); 
     675    pkt.ans[0].type = PJ_DNS_TYPE_CNAME; 
     676    pkt.ans[0].dnsclass = 1; 
     677    pkt.ans[0].ttl = 1; 
     678    pkt.ans[0].rdata.cname.name = pj_str("ahostalias"); 
     679 
     680    /* DNS A record, but the name doesn't match */ 
     681    pkt.ans[1].name = pj_str("ahost"); 
     682    pkt.ans[1].type = PJ_DNS_TYPE_A; 
     683    pkt.ans[1].dnsclass = 1; 
     684    pkt.ans[1].ttl = 1; 
     685    pkt.ans[1].rdata.a.ip_addr.s_addr = 0x01020304; 
     686 
     687    rc = pj_dns_parse_a_response(&pkt, &rec); 
     688    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC); 
     689 
     690    return 0; 
    366691} 
    367692 
     
    393718    pj_status_t status; 
    394719 
    395     PJ_LOG(3,(THIS_FILE, "    simple successful test")); 
     720    PJ_LOG(3,(THIS_FILE, "  simple successful test")); 
    396721 
    397722    g_server[0].pkt_count = 0; 
     
    467792    pj_status_t status; 
    468793 
    469     PJ_LOG(3,(THIS_FILE, "    simple error response test")); 
     794    PJ_LOG(3,(THIS_FILE, "  simple error response test")); 
    470795 
    471796    g_server[0].pkt_count = 0; 
     
    490815 
    491816    /* Wait to allow probing period to complete */ 
    492     PJ_LOG(3,(THIS_FILE, "    waiting for active NS to expire (%d sec)", 
     817    PJ_LOG(3,(THIS_FILE, "  waiting for active NS to expire (%d sec)", 
    493818                         set.good_ns_ttl)); 
    494819    pj_thread_sleep(set.good_ns_ttl * 1000); 
     
    497822     * Fail-over test  
    498823     */ 
    499     PJ_LOG(3,(THIS_FILE, "    failing server0")); 
     824    PJ_LOG(3,(THIS_FILE, "  failing server0")); 
    500825    g_server[0].action = ACTION_IGNORE; 
    501826    g_server[1].action = PJ_DNS_RCODE_NXDOMAIN; 
     
    516841     * in probing state. 
    517842     */ 
    518     PJ_LOG(3,(THIS_FILE, "    checking both NS during probing period")); 
     843    PJ_LOG(3,(THIS_FILE, "  checking both NS during probing period")); 
    519844    g_server[0].action = ACTION_IGNORE; 
    520845    g_server[1].action = PJ_DNS_RCODE_NXDOMAIN; 
     
    537862 
    538863    /* Wait to allow probing period to complete */ 
    539     PJ_LOG(3,(THIS_FILE, "    waiting for probing state to end (%d sec)", 
     864    PJ_LOG(3,(THIS_FILE, "  waiting for probing state to end (%d sec)", 
    540865                         set.qretr_delay *  
    541866                         (set.qretr_count+2) / 1000)); 
     
    546871     * Now only server 1 should get requests. 
    547872     */ 
    548     PJ_LOG(3,(THIS_FILE, "    verifying only good NS is used")); 
     873    PJ_LOG(3,(THIS_FILE, "  verifying only good NS is used")); 
    549874    g_server[0].action = PJ_DNS_RCODE_NXDOMAIN; 
    550875    g_server[1].action = PJ_DNS_RCODE_NXDOMAIN; 
     
    567892 
    568893    /* Wait to allow probing period to complete */ 
    569     PJ_LOG(3,(THIS_FILE, "    waiting for active NS to expire (%d sec)", 
     894    PJ_LOG(3,(THIS_FILE, "  waiting for active NS to expire (%d sec)", 
    570895                         set.good_ns_ttl)); 
    571896    pj_thread_sleep(set.good_ns_ttl * 1000); 
     
    589914 
    590915    /* Wait to allow probing period to complete */ 
    591     PJ_LOG(3,(THIS_FILE, "    waiting for probing state (%d sec)", 
     916    PJ_LOG(3,(THIS_FILE, "  waiting for probing state (%d sec)", 
    592917                         set.qretr_delay * (set.qretr_count+2) / 1000)); 
    593918    pj_thread_sleep(set.qretr_delay * (set.qretr_count + 2)); 
     
    596921     * Now only server 0 should get requests. 
    597922     */ 
    598     PJ_LOG(3,(THIS_FILE, "    verifying good NS")); 
     923    PJ_LOG(3,(THIS_FILE, "  verifying good NS")); 
    599924    g_server[0].action = PJ_DNS_RCODE_NXDOMAIN; 
    600925    g_server[1].action = ACTION_IGNORE; 
     
    612937    pj_thread_sleep(1000); 
    613938 
    614     /* Both servers must get requests */ 
     939    /* Only good NS should get request */ 
    615940    pj_assert(g_server[0].pkt_count == 1); 
    616941    pj_assert(g_server[1].pkt_count == 0); 
     
    624949/* Resolver test, normal, with CNAME */ 
    625950#define IP_ADDR1    0x02030405 
     951#define PORT1       50061 
    626952 
    627953static void action1_1(const pj_dns_parsed_packet *pkt, 
     
    657983        res->ans[0].rdata.srv.prio = 1; 
    658984        res->ans[0].rdata.srv.weight = 2; 
    659         res->ans[0].rdata.srv.port = 5061; 
     985        res->ans[0].rdata.srv.port = PORT1; 
    660986        res->ans[0].rdata.srv.target = pj_str(target); 
    661987 
     
    6921018    pj_assert(rec->entry[0].priority == 1); 
    6931019    pj_assert(rec->entry[0].weight == 2); 
    694     pj_assert(rec->entry[0].addr.ipv4.sin_addr.s_addr == IP_ADDR1); 
    695     pj_assert(pj_ntohs(rec->entry[0].addr.ipv4.sin_port) == 5061); 
     1020    pj_assert(pj_strcmp2(&rec->entry[0].server.name, "sip.somedomain.com")==0); 
     1021    pj_assert(pj_strcmp2(&rec->entry[0].server.alias, "sipalias.somedomain.com")==0); 
     1022    pj_assert(rec->entry[0].server.addr[0].s_addr == IP_ADDR1); 
     1023    pj_assert(rec->entry[0].port == PORT1); 
    6961024 
    6971025    pj_sem_post(sem); 
     
    7171045 
    7181046    /* Successful scenario */ 
    719     PJ_LOG(3,(THIS_FILE, "    srv_resolve(): success scenario")); 
     1047    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): success scenario")); 
    7201048 
    7211049    g_server[0].action = ACTION_CB; 
     
    7281056 
    7291057    status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE, 
    730                                 NULL, &srv_cb_1); 
     1058                                NULL, &srv_cb_1, NULL); 
    7311059    pj_assert(status == PJ_SUCCESS); 
    7321060 
    7331061    pj_sem_wait(sem); 
    7341062 
    735     /* Both servers should receive requests since state should be probing */ 
     1063    /* Because of previous tests, only NS 1 should get the request */ 
    7361064    pj_assert(g_server[0].pkt_count == 2);  /* 2 because of SRV and A resolution */ 
    7371065    pj_assert(g_server[1].pkt_count == 0); 
     
    7391067 
    7401068    /* Wait until cache expires and nameserver state moves out from STATE_PROBING */ 
    741     PJ_LOG(3,(THIS_FILE, "    waiting for cache to expire (~15 secs)..")); 
     1069    PJ_LOG(3,(THIS_FILE, "  waiting for cache to expire (~15 secs)..")); 
    7421070    pj_thread_sleep(1000 +  
    7431071                    ((set.qretr_count + 2) * set.qretr_delay)); 
    7441072 
    7451073    /* Successful scenario */ 
    746     PJ_LOG(3,(THIS_FILE, "    srv_resolve(): parallel queries")); 
     1074    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): parallel queries")); 
    7471075    g_server[0].pkt_count = 0; 
    7481076    g_server[1].pkt_count = 0; 
    7491077 
    7501078    status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE, 
    751                                 NULL, &srv_cb_1); 
     1079                                NULL, &srv_cb_1, NULL); 
    7521080    pj_assert(status == PJ_SUCCESS); 
    7531081 
    7541082 
    7551083    status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE, 
    756                                 NULL, &srv_cb_1); 
     1084                                NULL, &srv_cb_1, NULL); 
    7571085    pj_assert(status == PJ_SUCCESS); 
    7581086 
     
    7651093 
    7661094    /* Since TTL is one, subsequent queries should fail */ 
    767     PJ_LOG(3,(THIS_FILE, "    srv_resolve(): cache expires scenario")); 
     1095    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): cache expires scenario")); 
    7681096 
    7691097 
     
    7741102 
    7751103    status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE, 
    776                                 NULL, &srv_cb_1b); 
     1104                                NULL, &srv_cb_1b, NULL); 
    7771105    pj_assert(status == PJ_SUCCESS); 
    7781106 
     
    7871115#define TARGET      "domain2.com" 
    7881116#define IP_ADDR2    0x02030405 
     1117#define PORT2       50062 
    7891118 
    7901119static void action2_1(const pj_dns_parsed_packet *pkt, 
    7911120                      pj_dns_parsed_packet **p_res) 
    7921121{ 
    793     static pj_dns_parsed_packet res; 
    794  
    795     if (res.q == NULL) { 
    796         res.q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query); 
    797     } 
    798     if (res.ans == NULL) { 
    799         res.ans = (pj_dns_parsed_rr*)  
    800                   pj_pool_calloc(pool, 4, sizeof(pj_dns_parsed_rr)); 
    801     } 
    802  
    803     res.hdr.qdcount = 1; 
    804     res.q[0].type = pkt->q[0].type; 
    805     res.q[0].dnsclass = pkt->q[0].dnsclass; 
    806     res.q[0].name = pkt->q[0].name; 
     1122    pj_dns_parsed_packet *res; 
     1123 
     1124    res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet); 
     1125 
     1126    res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query); 
     1127    res->ans = (pj_dns_parsed_rr*)  
     1128               pj_pool_calloc(pool, 4, sizeof(pj_dns_parsed_rr)); 
     1129 
     1130    res->hdr.qdcount = 1; 
     1131    res->q[0].type = pkt->q[0].type; 
     1132    res->q[0].dnsclass = pkt->q[0].dnsclass; 
     1133    res->q[0].name = pkt->q[0].name; 
    8071134 
    8081135    if (pkt->q[0].type == PJ_DNS_TYPE_SRV) { 
     
    8101137        pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp." TARGET)==0); 
    8111138 
    812         res.hdr.anscount = 1; 
    813         res.ans[0].type = PJ_DNS_TYPE_A;    // <-- this will cause the fallback 
    814         res.ans[0].dnsclass = 1; 
    815         res.ans[0].name = res.q[0].name; 
    816         res.ans[0].ttl = 1; 
    817         res.ans[0].rdata.srv.prio = 1; 
    818         res.ans[0].rdata.srv.weight = 2; 
    819         res.ans[0].rdata.srv.port = 5062; 
    820         res.ans[0].rdata.srv.target = pj_str("sip01." TARGET); 
     1139        res->hdr.anscount = 1; 
     1140        res->ans[0].type = PJ_DNS_TYPE_A;    // <-- this will cause the fallback 
     1141        res->ans[0].dnsclass = 1; 
     1142        res->ans[0].name = res->q[0].name; 
     1143        res->ans[0].ttl = 1; 
     1144        res->ans[0].rdata.srv.prio = 1; 
     1145        res->ans[0].rdata.srv.weight = 2; 
     1146        res->ans[0].rdata.srv.port = PORT2; 
     1147        res->ans[0].rdata.srv.target = pj_str("sip01." TARGET); 
    8211148 
    8221149    } else if (pkt->q[0].type == PJ_DNS_TYPE_A) { 
    823         char *alias = "sipalias.somedomain.com"; 
    824  
    825         pj_assert(pj_strcmp2(&res.q[0].name, TARGET)==0); 
    826  
    827         res.hdr.anscount = 2; 
    828         res.ans[0].type = PJ_DNS_TYPE_CNAME; 
    829         res.ans[0].dnsclass = 1; 
    830         res.ans[0].name = res.q[0].name; 
    831         res.ans[0].ttl = 1; 
    832         res.ans[0].rdata.cname.name = pj_str(alias); 
    833  
    834         res.ans[1].type = PJ_DNS_TYPE_A; 
    835         res.ans[1].dnsclass = 1; 
    836         res.ans[1].name = pj_str(alias); 
    837         res.ans[1].ttl = 1; 
    838         res.ans[1].rdata.a.ip_addr.s_addr = IP_ADDR2; 
    839     } 
    840  
    841     *p_res = &res; 
     1150        char *alias = "sipalias01." TARGET; 
     1151 
     1152        pj_assert(pj_strcmp2(&res->q[0].name, TARGET)==0); 
     1153 
     1154        res->hdr.anscount = 2; 
     1155        res->ans[0].type = PJ_DNS_TYPE_CNAME; 
     1156        res->ans[0].dnsclass = 1; 
     1157        res->ans[0].name = res->q[0].name; 
     1158        res->ans[0].ttl = 1; 
     1159        res->ans[0].rdata.cname.name = pj_str(alias); 
     1160 
     1161        res->ans[1].type = PJ_DNS_TYPE_A; 
     1162        res->ans[1].dnsclass = 1; 
     1163        res->ans[1].name = pj_str(alias); 
     1164        res->ans[1].ttl = 1; 
     1165        res->ans[1].rdata.a.ip_addr.s_addr = IP_ADDR2; 
     1166    } 
     1167 
     1168    *p_res = res; 
    8421169} 
    8431170 
     
    8521179    pj_assert(rec->entry[0].priority == 0); 
    8531180    pj_assert(rec->entry[0].weight == 0); 
    854     pj_assert(rec->entry[0].addr.ipv4.sin_addr.s_addr == IP_ADDR2); 
    855     pj_assert(pj_ntohs(rec->entry[0].addr.ipv4.sin_port) == 5062); 
     1181    pj_assert(pj_strcmp2(&rec->entry[0].server.name, TARGET)==0); 
     1182    pj_assert(pj_strcmp2(&rec->entry[0].server.alias, "sipalias01." TARGET)==0); 
     1183    pj_assert(rec->entry[0].server.addr[0].s_addr == IP_ADDR2); 
     1184    pj_assert(rec->entry[0].port == PORT2); 
    8561185 
    8571186    pj_sem_post(sem); 
     
    8641193    pj_str_t res_name = pj_str("_sip._udp."); 
    8651194 
    866     PJ_LOG(3,(THIS_FILE, "    srv_resolve(): fallback test")); 
     1195    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): fallback test")); 
    8671196 
    8681197    g_server[0].action = ACTION_CB; 
     
    8711200    g_server[1].action_cb = &action2_1; 
    8721201 
    873     status = pj_dns_srv_resolve(&domain, &res_name, 5062, pool, resolver, PJ_TRUE, 
    874                                 NULL, &srv_cb_2); 
     1202    status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver, PJ_TRUE, 
     1203                                NULL, &srv_cb_2, NULL); 
    8751204    if (status != PJ_SUCCESS) { 
    876         app_perror("     srv_resolve error", status); 
     1205        app_perror("   srv_resolve error", status); 
    8771206        pj_assert(status == PJ_SUCCESS); 
    8781207    } 
     
    8811210 
    8821211    /* Subsequent query should just get the response from the cache */ 
    883     PJ_LOG(3,(THIS_FILE, "    srv_resolve(): cache test")); 
     1212    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): cache test")); 
    8841213    g_server[0].pkt_count = 0; 
    8851214    g_server[1].pkt_count = 0; 
    8861215 
    887     status = pj_dns_srv_resolve(&domain, &res_name, 5062, pool, resolver, PJ_TRUE, 
    888                                 NULL, &srv_cb_2); 
     1216    status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver, PJ_TRUE, 
     1217                                NULL, &srv_cb_2, NULL); 
    8891218    if (status != PJ_SUCCESS) { 
    890         app_perror("     srv_resolve error", status); 
     1219        app_perror("   srv_resolve error", status); 
    8911220        pj_assert(status == PJ_SUCCESS); 
    8921221    } 
     
    8961225    pj_assert(g_server[0].pkt_count == 0); 
    8971226    pj_assert(g_server[1].pkt_count == 0); 
     1227 
     1228    return 0; 
     1229} 
     1230 
     1231 
     1232//////////////////////////////////////////////////////////////////////////// 
     1233/* Too many SRV or A entries */ 
     1234#define DOMAIN3     "d3" 
     1235#define SRV_COUNT3  (PJ_DNS_SRV_MAX_ADDR+1) 
     1236#define A_COUNT3    (PJ_DNS_MAX_IP_IN_A_REC+1) 
     1237#define PORT3       50063 
     1238#define IP_ADDR3    0x03030303 
     1239 
     1240static void action3_1(const pj_dns_parsed_packet *pkt, 
     1241                      pj_dns_parsed_packet **p_res) 
     1242{ 
     1243    pj_dns_parsed_packet *res; 
     1244    unsigned i; 
     1245 
     1246    res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet); 
     1247 
     1248    if (res->q == NULL) { 
     1249        res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query); 
     1250    } 
     1251 
     1252    res->hdr.qdcount = 1; 
     1253    res->q[0].type = pkt->q[0].type; 
     1254    res->q[0].dnsclass = pkt->q[0].dnsclass; 
     1255    res->q[0].name = pkt->q[0].name; 
     1256 
     1257    if (pkt->q[0].type == PJ_DNS_TYPE_SRV) { 
     1258 
     1259        pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp." DOMAIN3)==0); 
     1260 
     1261        res->hdr.anscount = SRV_COUNT3; 
     1262        res->ans = (pj_dns_parsed_rr*)  
     1263                   pj_pool_calloc(pool, SRV_COUNT3, sizeof(pj_dns_parsed_rr)); 
     1264 
     1265        for (i=0; i<SRV_COUNT3; ++i) { 
     1266            char *target; 
     1267 
     1268            res->ans[i].type = PJ_DNS_TYPE_SRV; 
     1269            res->ans[i].dnsclass = 1; 
     1270            res->ans[i].name = res->q[0].name; 
     1271            res->ans[i].ttl = 1; 
     1272            res->ans[i].rdata.srv.prio = (pj_uint16_t)i; 
     1273            res->ans[i].rdata.srv.weight = 2; 
     1274            res->ans[i].rdata.srv.port = (pj_uint16_t)(PORT3+i); 
     1275 
     1276            target = (char*)pj_pool_alloc(pool, 16); 
     1277            sprintf(target, "sip%02d." DOMAIN3, i); 
     1278            res->ans[i].rdata.srv.target = pj_str(target); 
     1279        } 
     1280 
     1281    } else if (pkt->q[0].type == PJ_DNS_TYPE_A) { 
     1282 
     1283        //pj_assert(pj_strcmp2(&res->q[0].name, "sip." DOMAIN3)==0); 
     1284 
     1285        res->hdr.anscount = A_COUNT3; 
     1286        res->ans = (pj_dns_parsed_rr*)  
     1287                   pj_pool_calloc(pool, A_COUNT3, sizeof(pj_dns_parsed_rr)); 
     1288 
     1289        for (i=0; i<A_COUNT3; ++i) { 
     1290            res->ans[i].type = PJ_DNS_TYPE_A; 
     1291            res->ans[i].dnsclass = 1; 
     1292            res->ans[i].ttl = 1; 
     1293            res->ans[i].name = res->q[0].name; 
     1294            res->ans[i].rdata.a.ip_addr.s_addr = IP_ADDR3+i; 
     1295        } 
     1296    } 
     1297 
     1298    *p_res = res; 
     1299} 
     1300 
     1301static void srv_cb_3(void *user_data, 
     1302                     pj_status_t status, 
     1303                     const pj_dns_srv_record *rec) 
     1304{ 
     1305    unsigned i; 
     1306 
     1307    PJ_UNUSED_ARG(user_data); 
     1308 
     1309    pj_assert(status == PJ_SUCCESS); 
     1310    pj_assert(rec->count == PJ_DNS_SRV_MAX_ADDR); 
     1311    for (i=0; i<PJ_DNS_SRV_MAX_ADDR; ++i) { 
     1312        unsigned j; 
     1313 
     1314        pj_assert(rec->entry[i].priority == i); 
     1315        pj_assert(rec->entry[i].weight == 2); 
     1316        //pj_assert(pj_strcmp2(&rec->entry[i].server.name, "sip." DOMAIN3)==0); 
     1317        pj_assert(rec->entry[i].server.alias.slen == 0); 
     1318        pj_assert(rec->entry[i].port == PORT3+i); 
     1319 
     1320        pj_assert(rec->entry[i].server.addr_count == PJ_DNS_MAX_IP_IN_A_REC); 
     1321 
     1322        for (j=0; j<PJ_DNS_MAX_IP_IN_A_REC; ++j) { 
     1323            pj_assert(rec->entry[i].server.addr[j].s_addr == IP_ADDR3+j); 
     1324        } 
     1325    } 
     1326 
     1327    pj_sem_post(sem); 
     1328} 
     1329 
     1330static int srv_resolver_many_test(void) 
     1331{ 
     1332    pj_status_t status; 
     1333    pj_str_t domain = pj_str(DOMAIN3); 
     1334    pj_str_t res_name = pj_str("_sip._udp."); 
     1335 
     1336    /* Successful scenario */ 
     1337    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): too many entries test")); 
     1338 
     1339    g_server[0].action = ACTION_CB; 
     1340    g_server[0].action_cb = &action3_1; 
     1341    g_server[1].action = ACTION_CB; 
     1342    g_server[1].action_cb = &action3_1; 
     1343 
     1344    g_server[0].pkt_count = 0; 
     1345    g_server[1].pkt_count = 0; 
     1346 
     1347    status = pj_dns_srv_resolve(&domain, &res_name, 1, pool, resolver, PJ_TRUE, 
     1348                                NULL, &srv_cb_3, NULL); 
     1349    pj_assert(status == PJ_SUCCESS); 
     1350 
     1351    pj_sem_wait(sem); 
    8981352 
    8991353    return 0; 
     
    9091363     
    9101364#ifdef NDEBUG 
    911     PJ_LOG(3,(THIS_FILE, "    error: NDEBUG is declared")); 
     1365    PJ_LOG(3,(THIS_FILE, "  error: NDEBUG is declared")); 
    9121366    return -1; 
    9131367#endif 
    9141368 
    9151369    rc = init(); 
     1370 
     1371    rc = a_parser_test(); 
     1372    if (rc != 0) 
     1373        goto on_error; 
    9161374 
    9171375    rc = simple_test(); 
     
    9251383    srv_resolver_test(); 
    9261384    srv_resolver_fallback_test(); 
     1385    srv_resolver_many_test(); 
    9271386 
    9281387    destroy(); 
  • pjproject/trunk/pjlib-util/src/pjlib-util-test/test.c

    r1347 r1359  
    5151    mem = &caching_pool.factory; 
    5252 
    53     pj_log_set_level(5); 
     53    pj_log_set_level(3); 
    5454    pj_log_set_decor(PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME |  
    5555                     PJ_LOG_HAS_MICRO_SEC); 
Note: See TracChangeset for help on using the changeset viewer.