Ignore:
Timestamp:
Jun 20, 2016 10:10:42 AM (3 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/pjlib-util/src/pjlib-util/resolver.c

    r5311 r5349  
    8080struct nameserver 
    8181{ 
    82     pj_sockaddr_in  addr;               /**< Server address.                */ 
     82    pj_sockaddr     addr;               /**< Server address.                */ 
    8383 
    8484    enum ns_state   state;              /**< Nameserver state.              */ 
     
    180180    pj_ioqueue_key_t    *udp_key;       /**< UDP socket ioqueue key.        */ 
    181181    unsigned char        udp_rx_pkt[UDPSZ];/**< UDP receive buffer.         */ 
    182     unsigned char        udp_tx_pkt[UDPSZ];/**< UDP receive buffer.         */ 
    183     pj_ssize_t           udp_len;       /**< Length of received packet.     */ 
     182    unsigned char        udp_tx_pkt[UDPSZ];/**< UDP transmit buffer.        */ 
    184183    pj_ioqueue_op_key_t  udp_op_rx_key; /**< UDP read operation key.        */ 
    185184    pj_ioqueue_op_key_t  udp_op_tx_key; /**< UDP write operation key.       */ 
    186     pj_sockaddr_in       udp_src_addr;  /**< Source address of packet       */ 
     185    pj_sockaddr          udp_src_addr;  /**< Source address of packet       */ 
    187186    int                  udp_addr_len;  /**< Source address length.         */ 
     187 
     188#if PJ_HAS_IPV6 
     189    /* IPv6 socket */ 
     190    pj_sock_t            udp6_sock;     /**< UDP socket.                    */ 
     191    pj_ioqueue_key_t    *udp6_key;      /**< UDP socket ioqueue key.        */ 
     192    unsigned char        udp6_rx_pkt[UDPSZ];/**< UDP receive buffer.        */ 
     193    //unsigned char      udp6_tx_pkt[UDPSZ];/**< UDP transmit buffer.       */ 
     194    pj_ioqueue_op_key_t  udp6_op_rx_key;/**< UDP read operation key.        */ 
     195    pj_ioqueue_op_key_t  udp6_op_tx_key;/**< UDP write operation key.       */ 
     196    pj_sockaddr          udp6_src_addr; /**< Source address of packet       */ 
     197    int                  udp6_addr_len; /**< Source address length.         */ 
     198#endif 
    188199 
    189200    /* Settings */ 
     
    238249        resv->udp_sock = PJ_INVALID_SOCKET; 
    239250    } 
     251 
     252#if PJ_HAS_IPV6 
     253    if (resv->udp6_key != NULL) { 
     254        pj_ioqueue_unregister(resv->udp6_key); 
     255        resv->udp6_key = NULL; 
     256        resv->udp6_sock = PJ_INVALID_SOCKET; 
     257    } else if (resv->udp6_sock != PJ_INVALID_SOCKET) { 
     258        pj_sock_close(resv->udp6_sock); 
     259        resv->udp6_sock = PJ_INVALID_SOCKET; 
     260    } 
     261#endif 
    240262} 
    241263 
     
    245267{ 
    246268    pj_ioqueue_callback socket_cb; 
     269    pj_sockaddr bound_addr; 
     270    pj_ssize_t rx_pkt_size; 
    247271    pj_status_t status; 
    248272 
     
    270294 
    271295    /* Start asynchronous read to the UDP socket */ 
    272     resv->udp_len = sizeof(resv->udp_rx_pkt); 
     296    rx_pkt_size = sizeof(resv->udp_rx_pkt); 
    273297    resv->udp_addr_len = sizeof(resv->udp_src_addr); 
    274298    status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_rx_key, 
    275                                  resv->udp_rx_pkt, &resv->udp_len, 
     299                                 resv->udp_rx_pkt, &rx_pkt_size, 
    276300                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
    277301                                 &resv->udp_src_addr, &resv->udp_addr_len); 
    278302    if (status != PJ_EPENDING) 
    279303        return status; 
     304 
     305 
     306#if PJ_HAS_IPV6 
     307    /* Also setup IPv6 socket */ 
     308 
     309    /* Create the UDP socket */ 
     310    status = pj_sock_socket(pj_AF_INET6(), pj_SOCK_DGRAM(), 0, 
     311                            &resv->udp6_sock); 
     312    if (status != PJ_SUCCESS) 
     313        return status; 
     314 
     315    /* Bind to any address/port */ 
     316    pj_sockaddr_init(pj_AF_INET6(), &bound_addr, NULL, 0); 
     317    status = pj_sock_bind(resv->udp6_sock, &bound_addr, 
     318                          pj_sockaddr_get_len(&bound_addr)); 
     319    if (status != PJ_SUCCESS) 
     320        return status; 
     321 
     322    /* Register to ioqueue */ 
     323    pj_bzero(&socket_cb, sizeof(socket_cb)); 
     324    socket_cb.on_read_complete = &on_read_complete; 
     325    status = pj_ioqueue_register_sock(resv->pool, resv->ioqueue, 
     326                                      resv->udp6_sock, resv, &socket_cb, 
     327                                      &resv->udp6_key); 
     328    if (status != PJ_SUCCESS) 
     329        return status; 
     330 
     331    pj_ioqueue_op_key_init(&resv->udp6_op_rx_key, 
     332                           sizeof(resv->udp6_op_rx_key)); 
     333    pj_ioqueue_op_key_init(&resv->udp6_op_tx_key, 
     334                           sizeof(resv->udp6_op_tx_key)); 
     335 
     336    /* Start asynchronous read to the UDP socket */ 
     337    rx_pkt_size = sizeof(resv->udp6_rx_pkt); 
     338    resv->udp6_addr_len = sizeof(resv->udp6_src_addr); 
     339    status = pj_ioqueue_recvfrom(resv->udp6_key, &resv->udp6_op_rx_key, 
     340                                 resv->udp6_rx_pkt, &rx_pkt_size, 
     341                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
     342                                 &resv->udp6_src_addr, &resv->udp6_addr_len); 
     343    if (status != PJ_EPENDING) 
     344        return status; 
     345#else 
     346    PJ_UNUSED_ARG(bound_addr); 
     347#endif 
    280348 
    281349    return PJ_SUCCESS; 
     
    475543        struct nameserver *ns = &resolver->ns[i]; 
    476544 
    477         status = pj_sockaddr_in_init(&ns->addr, &servers[i],  
    478                                      (pj_uint16_t)(ports ? ports[i] : PORT)); 
     545        status = pj_sockaddr_init(pj_AF_INET(), &ns->addr, &servers[i],  
     546                                  (pj_uint16_t)(ports ? ports[i] : PORT)); 
     547        if (status != PJ_SUCCESS) 
     548            status = pj_sockaddr_init(pj_AF_INET6(), &ns->addr, &servers[i],  
     549                                      (pj_uint16_t)(ports ? ports[i] : PORT)); 
    479550        if (status != PJ_SUCCESS) { 
    480551            pj_mutex_unlock(resolver->mutex); 
     
    613684 
    614685    /* Check if the socket is available for sending */ 
    615     if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key)) { 
     686    if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key) 
     687#if PJ_HAS_IPV6 
     688        || pj_ioqueue_is_pending(resolver->udp6_key, 
     689                                 &resolver->udp6_op_tx_key) 
     690#endif 
     691        ) 
     692    { 
    616693        ++q->transmit_cnt; 
    617694        PJ_LOG(4,(resolver->name.ptr, 
     
    643720        struct nameserver *ns = &resolver->ns[servers[i]]; 
    644721 
    645         status = pj_ioqueue_sendto(resolver->udp_key, 
    646                                    &resolver->udp_op_tx_key, 
    647                                    resolver->udp_tx_pkt, &sent, 0, 
    648                                    &resolver->ns[servers[i]].addr, 
    649                                    sizeof(pj_sockaddr_in)); 
     722        if (ns->addr.addr.sa_family == pj_AF_INET()) { 
     723            status = pj_ioqueue_sendto(resolver->udp_key, 
     724                                       &resolver->udp_op_tx_key, 
     725                                       resolver->udp_tx_pkt, &sent, 0, 
     726                                       &ns->addr, 
     727                                       pj_sockaddr_get_len(&ns->addr)); 
     728        } 
     729#if PJ_HAS_IPV6 
     730        else { 
     731            status = pj_ioqueue_sendto(resolver->udp6_key, 
     732                                       &resolver->udp6_op_tx_key, 
     733                                       resolver->udp_tx_pkt, &sent, 0, 
     734                                       &ns->addr, 
     735                                       pj_sockaddr_get_len(&ns->addr)); 
     736        } 
     737#endif 
    650738 
    651739        PJ_PERROR(4,(resolver->name.ptr, status, 
     
    653741                  (q->transmit_cnt==0? "Transmitting":"Re-transmitting"), 
    654742                  (int)pkt_size, servers[i], 
    655                   pj_inet_ntop2(pj_AF_INET(), &ns->addr.sin_addr, addr, 
    656                                 sizeof(addr)), 
    657                   (int)pj_ntohs(ns->addr.sin_port), 
     743                  pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 
     744                  pj_sockaddr_get_port(&ns->addr), 
    658745                  pj_dns_get_type_name(q->key.qtype),  
    659746                  q->key.name)); 
     
    10291116 
    10301117 
     1118/*  
     1119 * DNS response containing A and/or AAAA packet.  
     1120 */ 
     1121PJ_DEF(pj_status_t) pj_dns_parse_addr_response( 
     1122                                            const pj_dns_parsed_packet *pkt, 
     1123                                            pj_dns_addr_record *rec) 
     1124{ 
     1125    enum { MAX_SEARCH = 20 }; 
     1126    pj_str_t hostname, alias = {NULL, 0}, *resname; 
     1127    pj_size_t bufstart = 0; 
     1128    pj_size_t bufleft; 
     1129    unsigned i, ansidx, cnt=0; 
     1130 
     1131    PJ_ASSERT_RETURN(pkt && rec, PJ_EINVAL); 
     1132 
     1133    /* Init the record */ 
     1134    pj_bzero(rec, sizeof(*rec)); 
     1135 
     1136    bufleft = sizeof(rec->buf_); 
     1137 
     1138    /* Return error if there's error in the packet. */ 
     1139    if (PJ_DNS_GET_RCODE(pkt->hdr.flags)) 
     1140        return PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_GET_RCODE(pkt->hdr.flags)); 
     1141 
     1142    /* Return error if there's no query section */ 
     1143    if (pkt->hdr.qdcount == 0) 
     1144        return PJLIB_UTIL_EDNSINANSWER; 
     1145 
     1146    /* Return error if there's no answer */ 
     1147    if (pkt->hdr.anscount == 0) 
     1148        return PJLIB_UTIL_EDNSNOANSWERREC; 
     1149 
     1150    /* Get the hostname from the query. */ 
     1151    hostname = pkt->q[0].name; 
     1152 
     1153    /* Copy hostname to the record */ 
     1154    if (hostname.slen > (int)bufleft) { 
     1155        return PJ_ENAMETOOLONG; 
     1156    } 
     1157 
     1158    pj_memcpy(&rec->buf_[bufstart], hostname.ptr, hostname.slen); 
     1159    rec->name.ptr = &rec->buf_[bufstart]; 
     1160    rec->name.slen = hostname.slen; 
     1161 
     1162    bufstart += hostname.slen; 
     1163    bufleft -= hostname.slen; 
     1164 
     1165    /* Find the first RR which name matches the hostname. */ 
     1166    for (ansidx=0; ansidx < pkt->hdr.anscount; ++ansidx) { 
     1167        if (pj_stricmp(&pkt->ans[ansidx].name, &hostname)==0) 
     1168            break; 
     1169    } 
     1170 
     1171    if (ansidx == pkt->hdr.anscount) 
     1172        return PJLIB_UTIL_EDNSNOANSWERREC; 
     1173 
     1174    resname = &hostname; 
     1175 
     1176    /* Keep following CNAME records. */ 
     1177    while (pkt->ans[ansidx].type == PJ_DNS_TYPE_CNAME && 
     1178           cnt++ < MAX_SEARCH) 
     1179    { 
     1180        resname = &pkt->ans[ansidx].rdata.cname.name; 
     1181 
     1182        if (!alias.slen) 
     1183            alias = *resname; 
     1184 
     1185        for (i=0; i < pkt->hdr.anscount; ++i) { 
     1186            if (pj_stricmp(resname, &pkt->ans[i].name)==0) 
     1187                break; 
     1188        } 
     1189 
     1190        if (i==pkt->hdr.anscount) 
     1191            return PJLIB_UTIL_EDNSNOANSWERREC; 
     1192 
     1193        ansidx = i; 
     1194    } 
     1195 
     1196    if (cnt >= MAX_SEARCH) 
     1197        return PJLIB_UTIL_EDNSINANSWER; 
     1198 
     1199    if (pkt->ans[ansidx].type != PJ_DNS_TYPE_A && 
     1200        pkt->ans[ansidx].type != PJ_DNS_TYPE_AAAA) 
     1201    { 
     1202        return PJLIB_UTIL_EDNSINANSWER; 
     1203    } 
     1204 
     1205    /* Copy alias to the record, if present. */ 
     1206    if (alias.slen) { 
     1207        if (alias.slen > (int)bufleft) 
     1208            return PJ_ENAMETOOLONG; 
     1209 
     1210        pj_memcpy(&rec->buf_[bufstart], alias.ptr, alias.slen); 
     1211        rec->alias.ptr = &rec->buf_[bufstart]; 
     1212        rec->alias.slen = alias.slen; 
     1213 
     1214        bufstart += alias.slen; 
     1215        bufleft -= alias.slen; 
     1216    } 
     1217 
     1218    /* Get the IP addresses. */ 
     1219    cnt = 0; 
     1220    for (i=0; i < pkt->hdr.anscount && cnt < PJ_DNS_MAX_IP_IN_A_REC ; ++i) { 
     1221        if ((pkt->ans[i].type == PJ_DNS_TYPE_A || 
     1222             pkt->ans[i].type == PJ_DNS_TYPE_AAAA) && 
     1223            pj_stricmp(&pkt->ans[i].name, resname)==0) 
     1224        { 
     1225            if (pkt->ans[i].type == PJ_DNS_TYPE_A) { 
     1226                rec->addr[cnt].af = pj_AF_INET(); 
     1227                rec->addr[cnt].ip.v4 = pkt->ans[i].rdata.a.ip_addr; 
     1228            } else { 
     1229                rec->addr[cnt].af = pj_AF_INET6(); 
     1230                rec->addr[cnt].ip.v6 = pkt->ans[i].rdata.aaaa.ip_addr; 
     1231            } 
     1232            ++cnt; 
     1233        } 
     1234    } 
     1235    rec->addr_count = cnt; 
     1236 
     1237    if (cnt == 0) 
     1238        return PJLIB_UTIL_EDNSNOANSWERREC; 
     1239 
     1240    return PJ_SUCCESS; 
     1241} 
     1242 
     1243 
    10311244/* Set nameserver state */ 
    10321245static void set_nameserver_state(pj_dns_resolver *resolver, 
     
    10371250    struct nameserver *ns = &resolver->ns[index]; 
    10381251    enum ns_state old_state = ns->state; 
    1039     char addr[PJ_INET_ADDRSTRLEN]; 
     1252    char addr[PJ_INET6_ADDRSTRLEN]; 
    10401253 
    10411254    ns->state = state; 
     
    10511264 
    10521265    PJ_LOG(5, (resolver->name.ptr, "Nameserver %s:%d state changed %s --> %s", 
    1053                pj_inet_ntop2(pj_AF_INET(), &ns->addr.sin_addr, addr, 
    1054                              sizeof(addr)), 
    1055                (int)pj_ntohs(ns->addr.sin_port), 
     1266               pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 
     1267               pj_sockaddr_get_port(&ns->addr), 
    10561268               state_names[old_state], state_names[state])); 
    10571269} 
     
    11321344/* Update name server status */ 
    11331345static void report_nameserver_status(pj_dns_resolver *resolver, 
    1134                                      const pj_sockaddr_in *ns_addr, 
     1346                                     const pj_sockaddr *ns_addr, 
    11351347                                     const pj_dns_parsed_packet *pkt) 
    11361348{ 
     
    11691381        struct nameserver *ns = &resolver->ns[i]; 
    11701382 
    1171         if (ns->addr.sin_addr.s_addr == ns_addr->sin_addr.s_addr && 
    1172             ns->addr.sin_port == ns_addr->sin_port && 
    1173             ns->addr.sin_family == ns_addr->sin_family) 
    1174         { 
     1383        if (pj_sockaddr_cmp(&ns->addr, ns_addr) == 0) { 
    11751384            if (q_id == ns->q_id) { 
    11761385                /* Calculate response time */ 
     
    13951604    pj_dns_parsed_packet *dns_pkt; 
    13961605    pj_dns_async_query *q; 
    1397     char addr[PJ_INET_ADDRSTRLEN]; 
     1606    char addr[PJ_INET6_ADDRSTRLEN]; 
     1607    pj_sockaddr *src_addr; 
     1608    int *src_addr_len; 
     1609    unsigned char *rx_pkt; 
     1610    pj_ssize_t rx_pkt_size; 
    13981611    pj_status_t status; 
    13991612    PJ_USE_EXCEPTION; 
     
    14011614 
    14021615    resolver = (pj_dns_resolver *) pj_ioqueue_get_user_data(key); 
     1616    pj_assert(resolver); 
     1617 
     1618#if PJ_HAS_IPV6 
     1619    if (key == resolver->udp6_key) { 
     1620        src_addr = &resolver->udp6_src_addr; 
     1621        src_addr_len = &resolver->udp6_addr_len; 
     1622        rx_pkt = resolver->udp6_rx_pkt; 
     1623        rx_pkt_size = sizeof(resolver->udp6_rx_pkt); 
     1624    } else  
     1625#endif 
     1626    { 
     1627        src_addr = &resolver->udp_src_addr; 
     1628        src_addr_len = &resolver->udp_addr_len; 
     1629        rx_pkt = resolver->udp_rx_pkt; 
     1630        rx_pkt_size = sizeof(resolver->udp_rx_pkt); 
     1631    } 
     1632 
    14031633    pj_mutex_lock(resolver->mutex); 
    14041634 
     
    14121642        PJ_LOG(4,(resolver->name.ptr,  
    14131643                  "DNS resolver read error from %s:%d: %s",  
    1414                   pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 
    1415                                 addr, sizeof(addr)),  
    1416                   pj_ntohs(resolver->udp_src_addr.sin_port), 
     1644                  pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1645                  pj_sockaddr_get_port(src_addr), 
    14171646                  errmsg)); 
    14181647 
     
    14231652              "Received %d bytes DNS response from %s:%d", 
    14241653              (int)bytes_read,  
    1425               pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 
    1426                             addr, sizeof(addr)),  
    1427               pj_ntohs(resolver->udp_src_addr.sin_port))); 
     1654              pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1655              pj_sockaddr_get_port(src_addr))); 
    14281656 
    14291657 
     
    14401668    dns_pkt = NULL; 
    14411669    PJ_TRY { 
    1442         status = pj_dns_parse_packet(pool, resolver->udp_rx_pkt,  
     1670        status = pj_dns_parse_packet(pool, rx_pkt,  
    14431671                                     (unsigned)bytes_read, &dns_pkt); 
    14441672    } 
     
    14491677 
    14501678    /* Update nameserver status */ 
    1451     report_nameserver_status(resolver, &resolver->udp_src_addr, dns_pkt); 
     1679    report_nameserver_status(resolver, src_addr, dns_pkt); 
    14521680 
    14531681    /* Handle parse error */ 
     
    14581686        PJ_LOG(3,(resolver->name.ptr,  
    14591687                  "Error parsing DNS response from %s:%d: %s",  
    1460                   pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 
    1461                                 addr, sizeof(addr)), 
    1462                   pj_ntohs(resolver->udp_src_addr.sin_port),  
     1688                  pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1689                  pj_sockaddr_get_port(src_addr), 
    14631690                  errmsg)); 
    14641691        goto read_next_packet; 
     
    14721699        PJ_LOG(5,(resolver->name.ptr,  
    14731700                  "DNS response from %s:%d id=%d discarded", 
    1474                   pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 
    1475                                 addr, sizeof(addr)),  
    1476                   pj_ntohs(resolver->udp_src_addr.sin_port), 
     1701                  pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1702                  pj_sockaddr_get_port(src_addr), 
    14771703                  (unsigned)dns_pkt->hdr.id)); 
    14781704        goto read_next_packet; 
     
    15371763        pj_pool_release(pool); 
    15381764    } 
    1539     bytes_read = sizeof(resolver->udp_rx_pkt); 
    1540     resolver->udp_addr_len = sizeof(resolver->udp_src_addr); 
    1541     status = pj_ioqueue_recvfrom(resolver->udp_key, op_key,  
    1542                                  resolver->udp_rx_pkt, 
    1543                                  &bytes_read, PJ_IOQUEUE_ALWAYS_ASYNC, 
    1544                                  &resolver->udp_src_addr,  
    1545                                  &resolver->udp_addr_len); 
     1765 
     1766    status = pj_ioqueue_recvfrom(key, op_key, rx_pkt, &rx_pkt_size, 
     1767                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
     1768                                 src_addr, src_addr_len); 
     1769 
    15461770    if (status != PJ_EPENDING) { 
    15471771        char errmsg[PJ_ERR_MSG_SIZE]; 
     
    16431867    PJ_LOG(3,(resolver->name.ptr, "  Name servers:")); 
    16441868    for (i=0; i<resolver->ns_count; ++i) { 
    1645         char addr[PJ_INET_ADDRSTRLEN]; 
     1869        char addr[PJ_INET6_ADDRSTRLEN]; 
    16461870        struct nameserver *ns = &resolver->ns[i]; 
    16471871 
    16481872        PJ_LOG(3,(resolver->name.ptr, 
    16491873                  "   NS %d: %s:%d (state=%s until %ds, rtt=%d ms)", 
    1650                   i, pj_inet_ntop2(pj_AF_INET(), &ns->addr.sin_addr, addr, 
    1651                                    sizeof(addr)), 
    1652                   pj_ntohs(ns->addr.sin_port), 
     1874                  i, 
     1875                  pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 
     1876                  pj_sockaddr_get_port(&ns->addr), 
    16531877                  state_names[ns->state], 
    16541878                  ns->state_expiry.sec - now.sec, 
Note: See TracChangeset for help on using the changeset viewer.