From 2e7c2feace463e9dc191465271866b51d79e4f1f Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Mon, 4 Jan 2010 16:54:50 +0000 Subject: Ticket #1010: - Fixed bug in some APIs of address resolver and IP helper to reset sin_len member of sockaddr. - Added purity test of sin_len member checking in pjlib test. - Fixed bug in pj_getaddrinfo() when address family param set to PJ_AF_UNSPEC (assertion raised as it called pj_sockaddr_get_addr() with PJ_AF_UNSPEC too). git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3044 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib/src/pj/addr_resolv_sock.c | 62 +++++++++++++++++++---------- pjlib/src/pj/ip_helper_generic.c | 3 ++ pjlib/src/pjlib-test/sock.c | 84 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 20 deletions(-) (limited to 'pjlib') diff --git a/pjlib/src/pj/addr_resolv_sock.c b/pjlib/src/pj/addr_resolv_sock.c index c88cc8f5..57bcd8f1 100644 --- a/pjlib/src/pj/addr_resolv_sock.c +++ b/pjlib/src/pj/addr_resolv_sock.c @@ -73,18 +73,28 @@ PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename, /* Check if nodename is IP address */ pj_bzero(&ai[0], sizeof(ai[0])); - ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af; - if (pj_inet_pton(af, nodename, pj_sockaddr_get_addr(&ai[0].ai_addr)) - == PJ_SUCCESS) - { - pj_str_t tmp; + if (af == PJ_AF_UNSPEC) { + if (pj_inet_pton(PJ_AF_INET, nodename, + &ai[0].ai_addr.ipv4.sin_addr) == PJ_SUCCESS) + { + af = PJ_AF_INET; + } + else if (pj_inet_pton(PJ_AF_INET6, nodename, + &ai[0].ai_addr.ipv6.sin6_addr) == PJ_SUCCESS) + { + af = PJ_AF_INET6; + } - tmp.ptr = ai[0].ai_canonname; - pj_strncpy_with_null(&tmp, nodename, PJ_MAX_HOSTNAME); - ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af; - *count = 1; + if (af != PJ_AF_UNSPEC) { + pj_str_t tmp; - return PJ_SUCCESS; + tmp.ptr = ai[0].ai_canonname; + pj_strncpy_with_null(&tmp, nodename, PJ_MAX_HOSTNAME); + ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af; + *count = 1; + + return PJ_SUCCESS; + } } /* Copy node name to null terminated string. */ @@ -121,6 +131,7 @@ PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename, /* Store address */ PJ_ASSERT_ON_FAIL(res->ai_addrlen <= sizeof(pj_sockaddr), continue); pj_memcpy(&ai[i].ai_addr, res->ai_addr, res->ai_addrlen); + PJ_SOCKADDR_RESET_LEN(&ai[i].ai_addr); /* Next slot */ ++i; @@ -139,18 +150,28 @@ PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename, /* Check if nodename is IP address */ pj_bzero(&ai[0], sizeof(ai[0])); - ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af; - if (pj_inet_pton(af, nodename, pj_sockaddr_get_addr(&ai[0].ai_addr)) - == PJ_SUCCESS) - { - pj_str_t tmp; + if (af == PJ_AF_UNSPEC) { + if (pj_inet_pton(PJ_AF_INET, nodename, + &ai[0].ai_addr.ipv4.sin_addr) == PJ_SUCCESS) + { + af = PJ_AF_INET; + } + else if (pj_inet_pton(PJ_AF_INET6, nodename, + &ai[0].ai_addr.ipv6.sin6_addr) == PJ_SUCCESS) + { + af = PJ_AF_INET6; + } - tmp.ptr = ai[0].ai_canonname; - pj_strncpy_with_null(&tmp, nodename, PJ_MAX_HOSTNAME); - ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af; - *count = 1; + if (af != PJ_AF_UNSPEC) { + pj_str_t tmp; - return PJ_SUCCESS; + tmp.ptr = ai[0].ai_canonname; + pj_strncpy_with_null(&tmp, nodename, PJ_MAX_HOSTNAME); + ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af; + *count = 1; + + return PJ_SUCCESS; + } } if (af == PJ_AF_INET || af == PJ_AF_UNSPEC) { @@ -180,6 +201,7 @@ PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename, ai[*count].ai_addr.ipv4.sin_family = PJ_AF_INET; pj_memcpy(&ai[*count].ai_addr.ipv4.sin_addr, he.h_addr_list[i], he.h_length); + PJ_SOCKADDR_RESET_LEN(&ai[*count].ai_addr); (*count)++; } diff --git a/pjlib/src/pj/ip_helper_generic.c b/pjlib/src/pj/ip_helper_generic.c index 79c2edaa..331579c0 100644 --- a/pjlib/src/pj/ip_helper_generic.c +++ b/pjlib/src/pj/ip_helper_generic.c @@ -121,6 +121,7 @@ static pj_status_t if_enum_by_af(int af, pj_bzero(&ifs[*p_cnt], sizeof(ifs[0])); pj_memcpy(&ifs[*p_cnt], ad, pj_sockaddr_get_len(ad)); + PJ_SOCKADDR_RESET_LEN(&ifs[*p_cnt]); (*p_cnt)++; } @@ -215,6 +216,7 @@ static pj_status_t if_enum_by_af(int af, pj_bzero(&ifs[*p_cnt], sizeof(ifs[0])); pj_memcpy(&ifs[*p_cnt], ad, pj_sockaddr_get_len(ad)); + PJ_SOCKADDR_RESET_LEN(&ifs[*p_cnt]); (*p_cnt)++; } @@ -305,6 +307,7 @@ static pj_status_t if_enum_by_af(int af, unsigned *p_cnt, pj_sockaddr ifs[]) pj_bzero(&ifs[*p_cnt], sizeof(ifs[0])); pj_memcpy(&ifs[*p_cnt], ad, pj_sockaddr_get_len(ad)); + PJ_SOCKADDR_RESET_LEN(&ifs[*p_cnt]); (*p_cnt)++; } diff --git a/pjlib/src/pjlib-test/sock.c b/pjlib/src/pjlib-test/sock.c index 30c87711..d64586bc 100644 --- a/pjlib/src/pjlib-test/sock.c +++ b/pjlib/src/pjlib-test/sock.c @@ -72,6 +72,18 @@ static char bigdata[BIG_DATA_LEN]; static char bigbuffer[BIG_DATA_LEN]; +/* Macro for checking the value of "sin_len" member of sockaddr + * (it must always be zero). + */ +#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0 +# define CHECK_SA_ZERO_LEN(addr, ret) \ + if (((pj_addr_hdr*)(addr))->sa_zero_len != 0) \ + return ret +#else +# define CHECK_SA_ZERO_LEN(addr, ret) +#endif + + static int format_test(void) { pj_str_t s = pj_str(ADDRESS); @@ -284,6 +296,9 @@ static int parse_test(void) return -10; } + /* Check "sin_len" member of parse result */ + CHECK_SA_ZERO_LEN(&addr, -20); + /* Build the correct result */ status = pj_sockaddr_init(valid_tests[i].result_af, &result, @@ -312,6 +327,9 @@ static int parse_test(void) return -50; } + /* Check "sin_len" member of parse result */ + CHECK_SA_ZERO_LEN(&addr, -55); + /* Compare the result again */ if (pj_sockaddr_cmp(&addr, &result) != 0) { PJ_LOG(1,("test", ".... parsed result mismatched for %s", @@ -351,6 +369,68 @@ static int parse_test(void) return 0; } +static int purity_test(void) +{ + PJ_LOG(3,("test", "...purity_test()")); + +#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0 + /* Check on "sin_len" member of sockaddr */ + { + const pj_str_t str_ip = {"1.1.1.1", 7}; + pj_sockaddr addr[16]; + pj_addrinfo ai[16]; + unsigned cnt; + pj_status_t rc; + + /* pj_enum_ip_interface() */ + cnt = PJ_ARRAY_SIZE(addr); + rc = pj_enum_ip_interface(pj_AF_UNSPEC(), &cnt, addr); + if (rc == PJ_SUCCESS) { + while (cnt--) + CHECK_SA_ZERO_LEN(&addr[cnt], -10); + } + + /* pj_gethostip() on IPv4 */ + rc = pj_gethostip(pj_AF_INET(), &addr[0]); + if (rc == PJ_SUCCESS) + CHECK_SA_ZERO_LEN(&addr[0], -20); + + /* pj_gethostip() on IPv6 */ + rc = pj_gethostip(pj_AF_INET6(), &addr[0]); + if (rc == PJ_SUCCESS) + CHECK_SA_ZERO_LEN(&addr[0], -30); + + /* pj_getdefaultipinterface() on IPv4 */ + rc = pj_getdefaultipinterface(pj_AF_INET(), &addr[0]); + if (rc == PJ_SUCCESS) + CHECK_SA_ZERO_LEN(&addr[0], -40); + + /* pj_getdefaultipinterface() on IPv6 */ + rc = pj_getdefaultipinterface(pj_AF_INET6(), &addr[0]); + if (rc == PJ_SUCCESS) + CHECK_SA_ZERO_LEN(&addr[0], -50); + + /* pj_getaddrinfo() on a host name */ + cnt = PJ_ARRAY_SIZE(ai); + rc = pj_getaddrinfo(pj_AF_UNSPEC(), pj_gethostname(), &cnt, ai); + if (rc == PJ_SUCCESS) { + while (cnt--) + CHECK_SA_ZERO_LEN(&ai[cnt].ai_addr, -60); + } + + /* pj_getaddrinfo() on an IP address */ + cnt = PJ_ARRAY_SIZE(ai); + rc = pj_getaddrinfo(pj_AF_UNSPEC(), &str_ip, &cnt, ai); + if (rc == PJ_SUCCESS) { + pj_assert(cnt == 1); + CHECK_SA_ZERO_LEN(&ai[0].ai_addr, -70); + } + } +#endif + + return 0; +} + static int simple_sock_test(void) { int types[2]; @@ -760,6 +840,10 @@ int sock_test() if (rc != 0) return rc; + rc = purity_test(); + if (rc != 0) + return rc; + rc = gethostbyname_test(); if (rc != 0) return rc; -- cgit v1.2.3