tb_bool_t tb_addrinfo_addr(tb_char_t const* name, tb_ipaddr_ref_t addr) { // check tb_assert_and_check_return_val(name && addr, tb_false); #ifndef TB_CONFIG_MICRO_ENABLE // attempt to get address using dns looker if (tb_ipaddr_family(addr) != TB_IPADDR_FAMILY_IPV6 && tb_dns_looker_done(name, addr)) return tb_true; #endif #if defined(TB_CONFIG_POSIX_HAVE_GETADDRINFO) // done tb_bool_t ok = tb_false; struct addrinfo* answer = tb_null; do { // init hints struct addrinfo hints = {0}; hints.ai_family = tb_addrinfo_ai_family(addr); hints.ai_socktype = SOCK_STREAM; // init service tb_char_t service[32] = {0}; tb_uint16_t port = tb_ipaddr_port(addr); if (port) tb_snprintf(service, sizeof(service), "%u", port); // get address info if (getaddrinfo(name, port? service : tb_null, &hints, &answer)) break; tb_assert_and_check_break(answer && answer->ai_addr); // save address ok = tb_sockaddr_save(addr, (struct sockaddr_storage const*)answer->ai_addr) != 0; } while (0); // exit answer if (answer) freeaddrinfo(answer); answer = tb_null; // ok? return ok; #elif defined(TB_CONFIG_POSIX_HAVE_GETHOSTBYNAME) // not support ipv6 tb_assert_and_check_return_val(tb_ipaddr_family(addr) != TB_IPADDR_FAMILY_IPV6, tb_false); // get first host address struct hostent* hostaddr = gethostbyname(name); tb_check_return_val(hostaddr && hostaddr->h_addr && hostaddr->h_addrtype == AF_INET, tb_false); // save family tb_ipaddr_family_set(addr, TB_IPADDR_FAMILY_IPV4); // make ipv4 tb_ipv4_t ipv4; ipv4.u32 = (tb_uint32_t)((struct in_addr const*)hostaddr->h_addr)->s_addr; // save ipv4 tb_ipaddr_ipv4_set(addr, &ipv4); // ok return tb_true; #else tb_trace_noimpl(); return tb_false; #endif }
static tb_size_t tb_ifaddrs_netlink_ipaddr_save(tb_ipaddr_ref_t ipaddr, tb_size_t family, tb_size_t scope_id, tb_cpointer_t saddr) { // check tb_assert_and_check_return_val(ipaddr && saddr, 0); // clear address tb_ipaddr_clear(ipaddr); // done tb_size_t size = 0; switch (family) { case AF_INET: { // the ipv4 ipaddr struct in_addr* addr4 = (struct in_addr*)saddr; // save family tb_ipaddr_family_set(ipaddr, TB_IPADDR_FAMILY_IPV4); // make ipv4 tb_ipv4_t ipv4; ipv4.u32 = (tb_uint32_t)addr4->s_addr; // save ipv4 tb_ipaddr_ipv4_set(ipaddr, &ipv4); // save size size = sizeof(struct in_addr); } break; case AF_INET6: { // the ipv6 ipaddr struct in6_addr* addr6 = (struct in6_addr*)saddr; // check tb_assert_static(sizeof(ipaddr->u.ipv6.addr.u8) == sizeof(addr6->s6_addr)); tb_assert_static(tb_arrayn(ipaddr->u.ipv6.addr.u8) == tb_arrayn(addr6->s6_addr)); // save family tb_ipaddr_family_set(ipaddr, TB_IPADDR_FAMILY_IPV6); // make ipv6 tb_ipv6_t ipv6; tb_memcpy(ipv6.addr.u8, addr6->s6_addr, sizeof(ipv6.addr.u8)); // save scope id ipv6.scope_id = 0; if (IN6_IS_ADDR_LINKLOCAL(addr6) || IN6_IS_ADDR_MC_LINKLOCAL(addr6)) ipv6.scope_id = (tb_uint32_t)scope_id; // save ipv6 tb_ipaddr_ipv6_set(ipaddr, &ipv6); // save size size = sizeof(struct in6_addr); } break; default: tb_assert(0); break; } // ok? return size; }