From baa2f7d1c0e83897cc89fd8a02846af9f1eca4e6 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Mon, 31 Dec 2007 11:26:21 +0000 Subject: Fixed IPv6/IPv4 address issue in Symbian: Symbian, at least 9.1, seems to have dual stack IP, so IPv4 address can be returned as a mapped IPv6 address git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1647 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib/src/pj/addr_resolv_symbian.cpp | 76 +++++++++++++++++++++++++----------- pjlib/src/pj/ip_helper_symbian.cpp | 31 ++++++++++++--- pjlib/src/pj/os_symbian.h | 15 +++++-- pjlib/src/pj/sock_common.c | 51 +++++++++++------------- pjlib/src/pj/sock_symbian.cpp | 4 +- 5 files changed, 115 insertions(+), 62 deletions(-) diff --git a/pjlib/src/pj/addr_resolv_symbian.cpp b/pjlib/src/pj/addr_resolv_symbian.cpp index d3698b51..9a28cbb9 100644 --- a/pjlib/src/pj/addr_resolv_symbian.cpp +++ b/pjlib/src/pj/addr_resolv_symbian.cpp @@ -20,12 +20,15 @@ #include #include #include +#include #include #include #include #include "os_symbian.h" +#define THIS_FILE "addr_resolv_symbian.cpp" +#define TRACE_ME 0 // PJLIB API: resolve hostname @@ -86,32 +89,59 @@ static pj_status_t getaddrinfo_by_af(int af, const pj_str_t *name, i = 0; while (reqStatus == KErrNone && i < *count) { - // Get the resolved TInetAddr - TInetAddr inetAddr(nameEntry().iAddr); - int addrlen; + // Get the resolved TInetAddr + TInetAddr inetAddr(nameEntry().iAddr); + int addrlen; - // Ignore if this is not the same address family - if (inetAddr.Family() != (unsigned)af) { - resv.Next(nameEntry, reqStatus); - User::WaitForRequest(reqStatus); - continue; - } - - // Convert the official address to ANSI. - pj_unicode_to_ansi((const wchar_t*)nameEntry().iName.Ptr(), - nameEntry().iName.Length(), - ai[i].ai_canonname, sizeof(ai[i].ai_canonname)); +#if TRACE_ME + if (1) { + pj_sockaddr a; + char ipaddr[PJ_INET6_ADDRSTRLEN+2]; + int namelen; + + namelen = sizeof(pj_sockaddr); + if (PjSymbianOS::Addr2pj(inetAddr, a, &namelen, + PJ_FALSE) == PJ_SUCCESS) + { + PJ_LOG(5,(THIS_FILE, "resolve %.*s: %s", + (int)name->slen, name->ptr, + pj_sockaddr_print(&a, ipaddr, sizeof(ipaddr), 2))); + } + } +#endif + + // Ignore if this is not the same address family + // Not a good idea, as Symbian mapps IPv4 to IPv6. + //fam = inetAddr.Family(); + //if (fam != af) { + // resv.Next(nameEntry, reqStatus); + // User::WaitForRequest(reqStatus); + // continue; + //} + + // Convert IP address first to get IPv4 mapped address + addrlen = sizeof(ai[i].ai_addr); + status = PjSymbianOS::Addr2pj(inetAddr, ai[i].ai_addr, + &addrlen, PJ_TRUE); + if (status != PJ_SUCCESS) + return status; + + // Ignore if address family doesn't match + if (ai[i].ai_addr.addr.sa_family != af) { + resv.Next(nameEntry, reqStatus); + User::WaitForRequest(reqStatus); + continue; + } - // Convert IP address - addrlen = sizeof(ai[i].ai_addr); - status = PjSymbianOS::Addr2pj(inetAddr, ai[i].ai_addr, &addrlen); - if (status != PJ_SUCCESS) - return status; + // Convert the official address to ANSI. + pj_unicode_to_ansi((const wchar_t*)nameEntry().iName.Ptr(), + nameEntry().iName.Length(), + ai[i].ai_canonname, sizeof(ai[i].ai_canonname)); - // Next - ++i; - resv.Next(nameEntry, reqStatus); - User::WaitForRequest(reqStatus); + // Next + ++i; + resv.Next(nameEntry, reqStatus); + User::WaitForRequest(reqStatus); } *count = i; diff --git a/pjlib/src/pj/ip_helper_symbian.cpp b/pjlib/src/pj/ip_helper_symbian.cpp index 44b8012c..f10c57da 100644 --- a/pjlib/src/pj/ip_helper_symbian.cpp +++ b/pjlib/src/pj/ip_helper_symbian.cpp @@ -20,12 +20,16 @@ #include #include #include +#include #include #include #include "os_symbian.h" +#define THIS_FILE "ip_helper_symbian.cpp" +#define TRACE_ME 0 + static pj_status_t rsock_enum_interface(int af, unsigned *p_cnt, pj_sockaddr ifs[]) @@ -58,14 +62,31 @@ static pj_status_t rsock_enum_interface(int af, { TInetAddr &iAddress = info().iAddress; int namelen; - - if (iAddress.Family() != (unsigned)af) { - continue; - } + +#if TRACE_ME + if (1) { + pj_sockaddr a; + char ipaddr[PJ_INET6_ADDRSTRLEN+2]; + + namelen = sizeof(pj_sockaddr); + if (PjSymbianOS::Addr2pj(iAddress, a, &namelen, + PJ_FALSE) == PJ_SUCCESS) + { + PJ_LOG(5,(THIS_FILE, "Enum: found address %s", + pj_sockaddr_print(&a, ipaddr, sizeof(ipaddr), 2))); + } + } +#endif namelen = sizeof(ifs[i]); - if (PjSymbianOS::Addr2pj(iAddress, ifs[i], &namelen) != PJ_SUCCESS) + if (PjSymbianOS::Addr2pj(iAddress, ifs[i], &namelen, + PJ_TRUE) != PJ_SUCCESS) + { continue; + } + + if (ifs[i].addr.sa_family != af) + continue; ++i; } diff --git a/pjlib/src/pj/os_symbian.h b/pjlib/src/pj/os_symbian.h index 36ecb653..c0e2045a 100644 --- a/pjlib/src/pj/os_symbian.h +++ b/pjlib/src/pj/os_symbian.h @@ -239,18 +239,25 @@ public: // Convert TInetAddr to pj_sockaddr_in static inline pj_status_t Addr2pj(const TInetAddr & sym_addr, pj_sockaddr &pj_addr, - int *addr_len) + int *addr_len, + pj_bool_t convert_ipv4_mapped_addr = PJ_FALSE) { + TUint fam = sym_addr.Family(); pj_bzero(&pj_addr, *addr_len); - pj_addr.addr.sa_family = (pj_uint16_t)sym_addr.Family(); - if (pj_addr.addr.sa_family == PJ_AF_INET) { + if (fam == PJ_AF_INET || + (convert_ipv4_mapped_addr && + fam == PJ_AF_INET6 && + sym_addr.IsV4Mapped())) + { + pj_addr.addr.sa_family = PJ_AF_INET; PJ_ASSERT_RETURN(*addr_len>=(int)sizeof(pj_sockaddr_in), PJ_ETOOSMALL); pj_addr.ipv4.sin_addr.s_addr = pj_htonl(sym_addr.Address()); pj_addr.ipv4.sin_port = pj_htons((pj_uint16_t) sym_addr.Port()); *addr_len = sizeof(pj_sockaddr_in); - } else if (pj_addr.addr.sa_family == PJ_AF_INET6) { + } else if (fam == PJ_AF_INET6) { PJ_ASSERT_RETURN(*addr_len>=(int)sizeof(pj_sockaddr_in6), PJ_ETOOSMALL); const TIp6Addr & ip6 = sym_addr.Ip6Address(); + pj_addr.addr.sa_family = PJ_AF_INET6; pj_memcpy(&pj_addr.ipv6.sin6_addr, ip6.u.iAddr8, 16); pj_addr.ipv6.sin6_port = pj_htons((pj_uint16_t) sym_addr.Port()); pj_addr.ipv6.sin6_scope_id = pj_htonl(sym_addr.Scope()); diff --git a/pjlib/src/pj/sock_common.c b/pjlib/src/pj/sock_common.c index 71cd02e7..a91b3c61 100644 --- a/pjlib/src/pj/sock_common.c +++ b/pjlib/src/pj/sock_common.c @@ -455,9 +455,8 @@ PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr) count = 1; status = pj_getaddrinfo(af, pj_gethostname(), &count, &ai); if (status == PJ_SUCCESS) { - pj_memcpy(pj_sockaddr_get_addr(addr), - pj_sockaddr_get_addr(&ai.ai_addr), - pj_sockaddr_get_addr_len(&ai.ai_addr)); + pj_assert(ai.ai_addr.addr.sa_family == (pj_uint16_t)af); + pj_sockaddr_copy_addr(addr, &ai.ai_addr); } @@ -465,37 +464,35 @@ PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr) * interface to connect to some public host. */ if (status != PJ_SUCCESS || !pj_sockaddr_has_addr(addr) || - (af==PJ_AF_INET && (pj_ntohl(addr->ipv4.sin_addr.s_addr) >> 24)==127)) + (af==PJ_AF_INET && (pj_ntohl(addr->ipv4.sin_addr.s_addr) >> 24)==127)) { - status = pj_getdefaultipinterface(af, addr); + status = pj_getdefaultipinterface(af, addr); } /* If failed, get the first available interface */ if (status != PJ_SUCCESS) { - pj_sockaddr itf[1]; - unsigned count = PJ_ARRAY_SIZE(itf); - - status = pj_enum_ip_interface(af, &count, itf); - if (status == PJ_SUCCESS) { - itf[0].addr.sa_family = (pj_uint16_t)af; - pj_memcpy(pj_sockaddr_get_addr(addr), - pj_sockaddr_get_addr(&itf[0]), - pj_sockaddr_get_addr_len(&itf[0])); - } + pj_sockaddr itf[1]; + unsigned count = PJ_ARRAY_SIZE(itf); + + status = pj_enum_ip_interface(af, &count, itf); + if (status == PJ_SUCCESS) { + pj_assert(itf[0].addr.sa_family == (pj_uint16_t)af); + pj_sockaddr_copy_addr(addr, &itf[0]); + } } /* If else fails, returns loopback interface as the last resort */ if (status != PJ_SUCCESS) { - if (af==PJ_AF_INET) { - addr->ipv4.sin_addr.s_addr = pj_htonl (0x7f000001); - } else { - pj_in6_addr *s6_addr; - - s6_addr = (pj_in6_addr*) pj_sockaddr_get_addr(addr); - pj_bzero(s6_addr, sizeof(pj_in6_addr)); - s6_addr->s6_addr[15] = 1; - } - status = PJ_SUCCESS; + if (af==PJ_AF_INET) { + addr->ipv4.sin_addr.s_addr = pj_htonl (0x7f000001); + } else { + pj_in6_addr *s6_addr; + + s6_addr = (pj_in6_addr*) pj_sockaddr_get_addr(addr); + pj_bzero(s6_addr, sizeof(pj_in6_addr)); + s6_addr->s6_addr[15] = 1; + } + status = PJ_SUCCESS; } return status; @@ -552,9 +549,7 @@ PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr) return PJ_ENOTFOUND; } - pj_memcpy(pj_sockaddr_get_addr(addr), - pj_sockaddr_get_addr(&a), - pj_sockaddr_get_addr_len(&a)); + pj_sockaddr_copy_addr(addr, &a); /* Success */ return PJ_SUCCESS; diff --git a/pjlib/src/pj/sock_symbian.cpp b/pjlib/src/pj/sock_symbian.cpp index f53f657e..aab6d4d8 100644 --- a/pjlib/src/pj/sock_symbian.cpp +++ b/pjlib/src/pj/sock_symbian.cpp @@ -405,7 +405,7 @@ PJ_DEF(pj_status_t) pj_inet_ntop(int af, const void *src, TBuf str16; pj_in_addr inaddr; - if (size <= PJ_INET_ADDRSTRLEN) + if (size < PJ_INET_ADDRSTRLEN) return PJ_ETOOSMALL; pj_memcpy(&inaddr, src, 4); @@ -421,7 +421,7 @@ PJ_DEF(pj_status_t) pj_inet_ntop(int af, const void *src, } else if (af==PJ_AF_INET6) { TBuf str16; - if (size <= PJ_INET6_ADDRSTRLEN) + if (size < PJ_INET6_ADDRSTRLEN) return PJ_ETOOSMALL; TIp6Addr ip6; -- cgit v1.2.3