Ignore:
Timestamp:
Jun 20, 2016 10:10:42 AM (8 years ago)
Author:
nanang
Message:

Close #1927: IPv6 support in DNS SRV:

  • support DNS A and AAAA resolution for each target in DNS SRV record
  • support fallback to DNS A and DNS AAAA resolution when DNS SRV record is not available
  • support IPv6 nameservers.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip/sip_resolve.c

    r5337 r5349  
    5454    pjsip_resolver_callback *cb; 
    5555    pj_dns_async_query      *object; 
     56    pj_dns_async_query      *object6; 
    5657    pj_status_t              last_error; 
    5758 
     
    6566    unsigned                 naptr_cnt; 
    6667    struct naptr_target      naptr[8]; 
     68 
     69    /* Query result */ 
     70    pjsip_server_addresses   server; 
    6771}; 
    6872 
     
    8185                           pj_status_t status, 
    8286                           pj_dns_parsed_packet *response); 
     87static void dns_aaaa_callback(void *user_data, 
     88                              pj_status_t status, 
     89                              pj_dns_parsed_packet *response); 
    8390 
    8491 
     
    207214    ip_addr_ver = get_ip_addr_ver(&target->addr.host); 
    208215 
    209     /* Initialize address family type */ 
     216    /* Initialize address family type. Unfortunately, target type doesn't 
     217     * really tell the address family type, except when IPv6 flag is 
     218     * explicitly set. 
     219     */ 
    210220    if ((ip_addr_ver == 6) || (type & PJSIP_TRANSPORT_IPV6)) 
    211221        af = pj_AF_INET6(); 
     
    402412 
    403413    if (query->query_type == PJ_DNS_TYPE_SRV) { 
     414        int opt = 0; 
     415 
     416        if (af == pj_AF_UNSPEC()) 
     417            opt = PJ_DNS_SRV_FALLBACK_A | PJ_DNS_SRV_FALLBACK_AAAA | 
     418                  PJ_DNS_SRV_RESOLVE_AAAA; 
     419        else if (af == pj_AF_INET6()) 
     420            opt = PJ_DNS_SRV_FALLBACK_AAAA | PJ_DNS_SRV_RESOLVE_AAAA_ONLY; 
     421        else /* af == pj_AF_INET() */ 
     422            opt = PJ_DNS_SRV_FALLBACK_A; 
    404423 
    405424        status = pj_dns_srv_resolve(&query->naptr[0].name, 
    406425                                    &query->naptr[0].res_type, 
    407426                                    query->req.def_port, pool, resolver->res, 
    408                                     PJ_TRUE, query, &srv_resolver_cb, NULL); 
     427                                    opt, query, &srv_resolver_cb, NULL); 
    409428 
    410429    } else if (query->query_type == PJ_DNS_TYPE_A) { 
    411430 
    412         status = pj_dns_resolver_start_query(resolver->res,  
    413                                              &query->naptr[0].name, 
    414                                              PJ_DNS_TYPE_A, 0,  
    415                                              &dns_a_callback, 
    416                                              query, &query->object); 
     431        /* Resolve DNS A record if address family is not fixed to IPv6 */ 
     432        if (af != pj_AF_INET6()) { 
     433            status = pj_dns_resolver_start_query(resolver->res,  
     434                                                 &query->naptr[0].name, 
     435                                                 PJ_DNS_TYPE_A, 0,  
     436                                                 &dns_a_callback, 
     437                                                 query, &query->object); 
     438        } 
     439 
     440        /* Resolve DNS AAAA record if address family is not fixed to IPv4 */ 
     441        if (af != pj_AF_INET()) { 
     442            status = pj_dns_resolver_start_query(resolver->res,  
     443                                                 &query->naptr[0].name, 
     444                                                 PJ_DNS_TYPE_AAAA, 0,  
     445                                                 &dns_aaaa_callback, 
     446                                                 query, &query->object6); 
     447        } 
    417448 
    418449    } else { 
     
    455486{ 
    456487    struct query *query = (struct query*) user_data; 
    457     pjsip_server_addresses srv; 
    458     pj_dns_a_record rec; 
    459     unsigned i; 
    460  
    461     rec.addr_count = 0; 
    462  
    463     /* Parse the response */ 
     488    pjsip_server_addresses *srv = &query->server; 
     489 
     490    /* Reset outstanding job */ 
     491    query->object = NULL; 
     492 
    464493    if (status == PJ_SUCCESS) { 
    465         status = pj_dns_parse_a_response(pkt, &rec); 
    466     } 
    467  
    468     if (status != PJ_SUCCESS) { 
     494        pj_dns_addr_record rec; 
     495        unsigned i; 
     496 
     497        /* Parse the response */ 
     498        rec.addr_count = 0; 
     499        status = pj_dns_parse_addr_response(pkt, &rec); 
     500 
     501        /* Build server addresses and call callback */ 
     502        for (i = 0; i < rec.addr_count && 
     503                    srv->count < PJSIP_MAX_RESOLVED_ADDRESSES; ++i) 
     504        { 
     505            /* Should not happen, just in case */ 
     506            if (rec.addr[i].af != pj_AF_INET()) 
     507                continue; 
     508 
     509            srv->entry[srv->count].type = query->naptr[0].type; 
     510            srv->entry[srv->count].priority = 0; 
     511            srv->entry[srv->count].weight = 0; 
     512            srv->entry[srv->count].addr_len = sizeof(pj_sockaddr_in); 
     513            pj_sockaddr_in_init(&srv->entry[srv->count].addr.ipv4, 
     514                                0, (pj_uint16_t)query->req.def_port); 
     515            srv->entry[srv->count].addr.ipv4.sin_addr = rec.addr[i].ip.v4; 
     516 
     517            ++srv->count; 
     518        } 
     519 
     520    } else { 
     521 
    469522        char errmsg[PJ_ERR_MSG_SIZE]; 
    470523 
     
    474527                  errmsg)); 
    475528 
    476         /* Call the callback */ 
    477         (*query->cb)(status, query->token, NULL); 
    478         return; 
    479     } 
    480  
    481     /* Build server addresses and call callback */ 
    482     srv.count = 0; 
    483     for (i = 0; i < rec.addr_count && 
    484                 srv.count < PJSIP_MAX_RESOLVED_ADDRESSES; ++i) 
    485     { 
    486         srv.entry[srv.count].type = query->naptr[0].type; 
    487         srv.entry[srv.count].priority = 0; 
    488         srv.entry[srv.count].weight = 0; 
    489         srv.entry[srv.count].addr_len = sizeof(pj_sockaddr_in); 
    490         pj_sockaddr_in_init(&srv.entry[srv.count].addr.ipv4, 
    491                             0, (pj_uint16_t)query->req.def_port); 
    492         srv.entry[srv.count].addr.ipv4.sin_addr.s_addr = 
    493             rec.addr[i].s_addr; 
    494  
    495         ++srv.count; 
    496     } 
    497  
    498     /* Call the callback */ 
    499     (*query->cb)(PJ_SUCCESS, query->token, &srv); 
     529        query->last_error = status; 
     530    } 
     531 
     532    /* Call the callback if all DNS queries have been completed */ 
     533    if (query->object == NULL && query->object6 == NULL) { 
     534        if (srv->count > 0) 
     535            (*query->cb)(PJ_SUCCESS, query->token, &query->server); 
     536        else 
     537            (*query->cb)(query->last_error, query->token, NULL); 
     538    } 
     539} 
     540 
     541 
     542/*  
     543 * This callback is called when target is resolved with DNS AAAA query. 
     544 */ 
     545static void dns_aaaa_callback(void *user_data, 
     546                              pj_status_t status, 
     547                              pj_dns_parsed_packet *pkt) 
     548{ 
     549    struct query *query = (struct query*) user_data; 
     550    pjsip_server_addresses *srv = &query->server; 
     551 
     552    /* Reset outstanding job */ 
     553    query->object6 = NULL; 
     554 
     555    if (status == PJ_SUCCESS) { 
     556        pj_dns_addr_record rec; 
     557        unsigned i; 
     558 
     559        /* Parse the response */ 
     560        rec.addr_count = 0; 
     561        status = pj_dns_parse_addr_response(pkt, &rec); 
     562 
     563        /* Build server addresses and call callback */ 
     564        for (i = 0; i < rec.addr_count && 
     565                    srv->count < PJSIP_MAX_RESOLVED_ADDRESSES; ++i) 
     566        { 
     567            /* Should not happen, just in case */ 
     568            if (rec.addr[i].af != pj_AF_INET6()) 
     569                continue; 
     570 
     571            srv->entry[srv->count].type = query->naptr[0].type | 
     572                                          PJSIP_TRANSPORT_IPV6; 
     573            srv->entry[srv->count].priority = 0; 
     574            srv->entry[srv->count].weight = 0; 
     575            srv->entry[srv->count].addr_len = sizeof(pj_sockaddr_in); 
     576            pj_sockaddr_init(pj_AF_INET6(), &srv->entry[srv->count].addr, 
     577                             0, (pj_uint16_t)query->req.def_port); 
     578            srv->entry[srv->count].addr.ipv6.sin6_addr = rec.addr[i].ip.v6; 
     579 
     580            ++srv->count; 
     581        } 
     582 
     583    } else { 
     584 
     585        char errmsg[PJ_ERR_MSG_SIZE]; 
     586 
     587        /* Log error */ 
     588        pj_strerror(status, errmsg, sizeof(errmsg)); 
     589        PJ_LOG(4,(query->objname, "DNS AAAA record resolution failed: %s",  
     590                  errmsg)); 
     591 
     592        query->last_error = status; 
     593    } 
     594 
     595    /* Call the callback if all DNS queries have been completed */ 
     596    if (query->object == NULL && query->object6 == NULL) { 
     597        if (srv->count > 0) 
     598            (*query->cb)(PJ_SUCCESS, query->token, &query->server); 
     599        else 
     600            (*query->cb)(query->last_error, query->token, NULL); 
     601    } 
    500602} 
    501603 
     
    515617        /* Log error */ 
    516618        pj_strerror(status, errmsg, sizeof(errmsg)); 
    517         PJ_LOG(4,(query->objname, "DNS A record resolution failed: %s",  
     619        PJ_LOG(4,(query->objname, "DNS A/AAAA record resolution failed: %s", 
    518620                  errmsg)); 
    519621 
     
    526628    srv.count = 0; 
    527629    for (i=0; i<rec->count; ++i) { 
     630        const pj_dns_addr_record *s = &rec->entry[i].server; 
    528631        unsigned j; 
    529632 
    530         for (j = 0; j < rec->entry[i].server.addr_count && 
     633        for (j = 0; j < s->addr_count && 
    531634                    srv.count < PJSIP_MAX_RESOLVED_ADDRESSES; ++j) 
    532635        { 
     
    535638            srv.entry[srv.count].weight = rec->entry[i].weight; 
    536639            srv.entry[srv.count].addr_len = sizeof(pj_sockaddr_in); 
    537             pj_sockaddr_in_init(&srv.entry[srv.count].addr.ipv4, 
    538                                 0, (pj_uint16_t)rec->entry[i].port); 
    539             srv.entry[srv.count].addr.ipv4.sin_addr.s_addr = 
    540                 rec->entry[i].server.addr[j].s_addr; 
     640            pj_sockaddr_init(s->addr[j].af, 
     641                             &srv.entry[srv.count].addr, 
     642                             0, (pj_uint16_t)rec->entry[i].port); 
     643            if (s->addr[j].af == pj_AF_INET6()) 
     644                srv.entry[srv.count].addr.ipv6.sin6_addr = s->addr[j].ip.v6; 
     645            else 
     646                srv.entry[srv.count].addr.ipv4.sin_addr = s->addr[j].ip.v4; 
     647 
     648            /* Update transport type if this is IPv6 */ 
     649            if (s->addr[j].af == pj_AF_INET6()) 
     650                srv.entry[srv.count].type |= PJSIP_TRANSPORT_IPV6; 
    541651 
    542652            ++srv.count; 
Note: See TracChangeset for help on using the changeset viewer.