#include "module.h"
#include "network.h"
+#include <sys/un.h>
+
#ifndef INADDR_NONE
# define INADDR_NONE INADDR_BROADCAST
#endif
setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE,
(char *) &opt, sizeof(opt));
- /* set our own address, ignore if bind() fails */
+ /* set our own address */
if (my_ip != NULL) {
sin_set_ip(&so, my_ip);
- bind(handle, &so.sa, SIZEOF_SOCKADDR(so));
+ if (bind(handle, &so.sa, SIZEOF_SOCKADDR(so)) == -1) {
+ /* failed, set it back to INADDR_ANY */
+ sin_set_ip(&so, NULL);
+ bind(handle, &so.sa, SIZEOF_SOCKADDR(so));
+ }
}
/* connect */
ret = connect(handle, &so.sa, SIZEOF_SOCKADDR(so));
#ifndef WIN32
- if (ret < 0 && errno != EINPROGRESS) {
+ if (ret < 0 && errno != EINPROGRESS)
#else
- if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) {
+ if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
+#endif
+ {
+ int old_errno = errno;
+ close(handle);
+ errno = old_errno;
+ return NULL;
+ }
+
+ return g_io_channel_new(handle);
+}
+
+/* Connect to named UNIX socket */
+GIOChannel *net_connect_unix(const char *path)
+{
+ struct sockaddr_un sa;
+ int handle, ret;
+
+ /* create the socket */
+ handle = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (handle == -1)
+ return NULL;
+
+ /* set socket options */
+#ifndef WIN32
+ fcntl(handle, F_SETFL, O_NONBLOCK);
#endif
+
+ /* connect */
+ memset(&sa, 0, sizeof(sa));
+ sa.sun_family = AF_UNIX;
+ strncpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
+ sa.sun_path[sizeof(sa.sun_path)-1] = '\0';
+
+ ret = connect(handle, (struct sockaddr *) &sa, sizeof(sa));
+ if (ret < 0 && errno != EINPROGRESS) {
+ int old_errno = errno;
close(handle);
+ errno = old_errno;
return NULL;
}
/* create the socket */
handle = socket(so.sin.sin_family, SOCK_STREAM, 0);
#ifdef HAVE_IPV6
- if (handle == -1 && errno == EINVAL) {
+ if (handle == -1 && (errno == EINVAL || errno == EAFNOSUPPORT)) {
/* IPv6 is not supported by OS */
so.sin.sin_family = AF_INET;
so.sin.sin_addr.s_addr = INADDR_ANY;
{
#ifdef HAVE_IPV6
union sockaddr_union *so;
- struct addrinfo hints, *ai, *origai;
- char hbuf[NI_MAXHOST];
- int host_error, count;
+ struct addrinfo hints, *ai, *ailist;
+ int ret, count;
#else
struct hostent *hp;
#endif
hints.ai_socktype = SOCK_STREAM;
/* save error to host_error for later use */
- host_error = getaddrinfo(addr, NULL, &hints, &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;
+ ret = getaddrinfo(addr, NULL, &hints, &ailist);
+ if (ret != 0)
+ return ret;
- origai = ai; count = 0;
- while (ai != NULL && count < 2) {
+ 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, ip4);
count++;
}
- ai = ai->ai_next;
}
- freeaddrinfo(origai);
+ freeaddrinfo(ailist);
+ return count > 0 ? 0 : 1;
#else
hp = gethostbyname(addr);
- if (hp == NULL) return h_errno;
+ if (hp == NULL)
+ return h_errno;
ip4->family = AF_INET;
memcpy(&ip4->ip, hp->h_addr, 4);
-#endif
return 0;
+#endif
}
/* Get name for host, *name should be g_free()'d unless it's NULL.
#ifdef HAVE_IPV6
struct addrinfo req, *ai;
int host_error;
+ char hostname[NI_MAXHOST];
+ char ipname[MAX_IP_LEN];
#else
struct hostent *hp;
#endif
- char ipname[MAX_IP_LEN];
g_return_val_if_fail(ip != NULL, -1);
g_return_val_if_fail(name != NULL, -1);
- net_ip2host(ip, ipname);
-
*name = NULL;
#ifdef HAVE_IPV6
+ net_ip2host(ip, ipname);
+
memset(&req, 0, sizeof(struct addrinfo));
req.ai_socktype = SOCK_STREAM;
req.ai_flags = AI_CANONNAME;
host_error = getaddrinfo(ipname, NULL, &req, &ai);
if (host_error != 0)
return host_error;
- *name = g_strdup(ai->ai_canonname);
+ host_error = getnameinfo(ai->ai_addr, ai->ai_addrlen,
+ hostname, NI_MAXHOST, NULL, 0, 0);
+ if (host_error != 0) {
+ freeaddrinfo(ai);
+ return host_error;
+ }
+
+ *name = g_strdup(hostname);
freeaddrinfo(ai);
#else
- hp = gethostbyaddr(ipname, strlen(ipname), AF_INET);
+ if (ip->family != AF_INET) return -1;
+ hp = gethostbyaddr(&ip->ip, 4, AF_INET);
if (hp == NULL) return -1;
*name = g_strdup(hp->h_name);
#else
unsigned long ip4;
- ip4 = ntohl(ip->ip.s_addr);
- g_snprintf(host, MAX_IP_LEN, "%lu.%lu.%lu.%lu",
- (ip4 & 0xff000000UL) >> 24,
- (ip4 & 0x00ff0000) >> 16,
- (ip4 & 0x0000ff00) >> 8,
- (ip4 & 0x000000ff));
+ if (ip->family != AF_INET) {
+ strcpy(host, "0.0.0.0");
+ } else {
+ ip4 = ntohl(ip->ip.s_addr);
+ g_snprintf(host, MAX_IP_LEN, "%lu.%lu.%lu.%lu",
+ (ip4 & 0xff000000UL) >> 24,
+ (ip4 & 0x00ff0000) >> 16,
+ (ip4 & 0x0000ff00) >> 8,
+ (ip4 & 0x000000ff));
+ }
#endif
return 0;
}
{
unsigned long addr;
-#ifdef HAVE_IPV6
if (strchr(host, ':') != NULL) {
/* IPv6 */
ip->family = AF_INET6;
+#ifdef HAVE_IPV6
if (inet_pton(AF_INET6, host, &ip->ip) == 0)
return -1;
- } else
+#else
+ ip->ip.s_addr = 0;
#endif
- {
+ } else {
/* IPv4 */
ip->family = AF_INET;
#ifdef HAVE_INET_ATON
int is_ipv4_address(const char *host)
{
while (*host != '\0') {
- if (*host != '.' && !isdigit(*host))
+ if (*host != '.' && !i_isdigit(*host))
return 0;
host++;
}
int is_ipv6_address(const char *host)
{
while (*host != '\0') {
- if (*host != ':' && !isxdigit(*host))
+ if (*host != ':' && !i_isxdigit(*host))
return 0;
host++;
}