/* Get IP addresses for host, both IPv4 and IPv6 if possible. If ip->family is 0, the address wasn't found. Returns 0 = ok, others = error code for net_gethosterror() */ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) { #ifdef HAVE_IPV6 union sockaddr_union *so; struct addrinfo hints, *ai, *ailist; int ret, count; #else struct hostent *hp; #endif g_return_val_if_fail(addr != NULL, -1); memset(ip4, 0, sizeof(IPADDR)); memset(ip6, 0, sizeof(IPADDR)); #ifdef HAVE_IPV6 memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; /* save error to host_error for later use */ ret = getaddrinfo(addr, NULL, &hints, &ailist); if (ret != 0) return ret; count = 0; for (ai = ailist; ai != NULL && count < 2; ai = ai->ai_next) { so = (union sockaddr_union *) ai->ai_addr; if (ai->ai_family == AF_INET6 && ip6->family == 0) { sin_get_ip(so, ip6); count++; } else if (ai->ai_family == AF_INET && ip4->family == 0) { sin_get_ip(so, ip4); count++; } } freeaddrinfo(ailist); return count > 0 ? 0 : 1; #else hp = gethostbyname(addr); if (hp == NULL) return -1; //return h_errno; ip4->family = AF_INET; memcpy(&ip4->ip, hp->h_addr, 4); return 0; #endif }
/* Get socket address/port */ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port) { union sockaddr_union so; socklen_t addrlen; g_return_val_if_fail(handle != NULL, -1); g_return_val_if_fail(addr != NULL, -1); addrlen = sizeof(so); if (getsockname(g_io_channel_unix_get_fd(handle), (struct sockaddr *) &so, &addrlen) == -1) return -1; sin_get_ip(&so, addr); if (port) *port = sin_get_port(&so); return 0; }
/* Accept a connection on a socket */ int net_accept(int handle, IPADDR *addr, int *port) { union sockaddr_union so; int ret; socklen_t addrlen; g_return_val_if_fail(handle != -1, -1); addrlen = sizeof(so); ret = accept(handle, &so.sa, &addrlen); if (ret < 0) return -1; if (addr != NULL) sin_get_ip(&so, addr); if (port != NULL) *port = sin_get_port(&so); fcntl(ret, F_SETFL, O_NONBLOCK); return ret; }
/* Accept a connection on a socket */ GIOChannel *net_accept(GIOChannel *handle, IPADDR *addr, int *port) { union sockaddr_union so; int ret; socklen_t addrlen; g_return_val_if_fail(handle != NULL, NULL); addrlen = sizeof(so); ret = accept(g_io_channel_unix_get_fd(handle), &so.sa, &addrlen); if (ret < 0) return NULL; if (addr != NULL) sin_get_ip(&so, addr); if (port != NULL) *port = sin_get_port(&so); #ifndef WIN32 fcntl(ret, F_SETFL, O_NONBLOCK); #endif return g_io_channel_new(ret); }
/* Get IP address for host, returns 0 = ok, others = error code for net_gethosterror() */ int net_gethostbyname(const char *addr, IPADDR *ip) { #ifdef HAVE_IPV6 union sockaddr_union *so; struct addrinfo req, *ai; char hbuf[NI_MAXHOST]; int host_error; #else struct hostent *hp; #endif g_return_val_if_fail(addr != NULL, -1); #ifdef HAVE_IPV6 memset(ip, 0, sizeof(IPADDR)); memset(&req, 0, sizeof(struct addrinfo)); req.ai_socktype = SOCK_STREAM; /* save error to host_error for later use */ host_error = getaddrinfo(addr, NULL, &req, &ai); if (host_error != 0) return host_error; if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) return 1; so = (union sockaddr_union *) ai->ai_addr; sin_get_ip(so, ip); freeaddrinfo(ai); #else hp = gethostbyname(addr); if (hp == NULL) return -1; ip->family = AF_INET; memcpy(&ip->addr, hp->h_addr, 4); #endif return 0; }
/* Get socket address/port */ int net_getsockname(int handle, IPADDR *addr, int *port) { union sockaddr_union so; #ifdef HAVE_IPV6 socklen_t len = sizeof(so.sin6); #else socklen_t len = sizeof(so.sin); #endif g_return_val_if_fail(handle != -1, -1); g_return_val_if_fail(addr != NULL, -1); #ifdef HAVE_IPV6 if (getsockname(handle, &so.sin6, &len) == -1) #else if (getsockname(handle, &so.sin, &len) == -1) #endif return -1; sin_get_ip(&so, addr); if (port) *port = sin_get_port(&so); return 0; }
/* Get IP addresses for host, both IPv4 and IPv6 if possible. If ip->family is 0, the address wasn't found. Returns 0 = ok, others = error code for net_gethosterror() */ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) { #ifdef HAVE_IPV6 union sockaddr_union *so; struct addrinfo hints, *ai, *ailist; int ret, count_v4, count_v6, use_v4, use_v6; #else struct hostent *hp; int count; #endif g_return_val_if_fail(addr != NULL, -1); memset(ip4, 0, sizeof(IPADDR)); memset(ip6, 0, sizeof(IPADDR)); #ifdef HAVE_IPV6 memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; /* save error to host_error for later use */ ret = getaddrinfo(addr, NULL, &hints, &ailist); if (ret != 0) return ret; /* count IPs */ count_v4 = count_v6 = 0; for (ai = ailist; ai != NULL; ai = ai->ai_next) { if (ai->ai_family == AF_INET) count_v4++; else if (ai->ai_family == AF_INET6) count_v6++; } if (count_v4 == 0 && count_v6 == 0) return HOST_NOT_FOUND; /* shouldn't happen? */ /* if there are multiple addresses, return random one */ use_v4 = count_v4 <= 1 ? 0 : rand() % count_v4; use_v6 = count_v6 <= 1 ? 0 : rand() % count_v6; count_v4 = count_v6 = 0; for (ai = ailist; ai != NULL; ai = ai->ai_next) { so = (union sockaddr_union *) ai->ai_addr; if (ai->ai_family == AF_INET) { if (use_v4 == count_v4) sin_get_ip(so, ip4); count_v4++; } else if (ai->ai_family == AF_INET6) { if (use_v6 == count_v6) sin_get_ip(so, ip6); count_v6++; } } freeaddrinfo(ailist); return 0; #else hp = gethostbyname(addr); if (hp == NULL) return h_errno; /* count IPs */ count = 0; while (hp->h_addr_list[count] != NULL) count++; if (count == 0) return HOST_NOT_FOUND; /* shouldn't happen? */ /* if there are multiple addresses, return random one */ ip4->family = AF_INET; memcpy(&ip4->ip, hp->h_addr_list[rand() % count], 4); return 0; #endif }