bool IpAddr::isValid(const std::string &address, pj_uint16_t family) { pj_str_t pjstring; pj_cstr(&pjstring, address.c_str()); pj_str_t ret_str; pj_uint16_t ret_port; int ret_family; auto status = pj_sockaddr_parse2(pj_AF_UNSPEC(), 0, &pjstring, &ret_str, &ret_port, &ret_family); if (status != PJ_SUCCESS || (family != pj_AF_UNSPEC() && ret_family != family)) return false; char buf[PJ_INET6_ADDRSTRLEN]; pj_str_t addr_with_null = {buf, 0}; pj_strncpy_with_null(&addr_with_null, &ret_str, sizeof(buf)); struct sockaddr sa; return inet_pton(ret_family==pj_AF_INET6()?AF_INET6:AF_INET, buf, &(sa.sa_data)) == 1; }
/* * Parse address */ PJ_DEF(pj_status_t) pj_sockaddr_parse( int af, unsigned options, const pj_str_t *str, pj_sockaddr *addr) { pj_str_t hostpart; pj_uint16_t port; pj_status_t status; PJ_ASSERT_RETURN(addr, PJ_EINVAL); PJ_ASSERT_RETURN(af==PJ_AF_UNSPEC || af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL); PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); status = pj_sockaddr_parse2(af, options, str, &hostpart, &port, &af); if (status != PJ_SUCCESS) return status; #if !defined(PJ_HAS_IPV6) || !PJ_HAS_IPV6 if (af==PJ_AF_INET6) return PJ_EIPV6NOTSUP; #endif status = pj_sockaddr_init(af, addr, &hostpart, port); #if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6 if (status != PJ_SUCCESS && af == PJ_AF_INET6) { /* Parsing does not yield valid address. Try to treat the last * portion after the colon as port number. */ const char *last_colon_pos=NULL, *p; const char *end = str->ptr + str->slen; unsigned long long_port; pj_str_t port_part; int i; /* Parse as IPv6:port */ for (p=str->ptr; p!=end; ++p) { if (*p == ':') last_colon_pos = p; } if (last_colon_pos == NULL) return status; hostpart.ptr = (char*)str->ptr; hostpart.slen = last_colon_pos - str->ptr; port_part.ptr = (char*)last_colon_pos + 1; port_part.slen = end - port_part.ptr; /* Make sure port number is valid */ for (i=0; i<port_part.slen; ++i) { if (!pj_isdigit(port_part.ptr[i])) return status; } long_port = pj_strtoul(&port_part); if (long_port > 65535) return status; port = (pj_uint16_t)long_port; status = pj_sockaddr_init(PJ_AF_INET6, addr, &hostpart, port); } #endif return status; }