From a6b0f937434ed52347c92deca87f75f9926aeca2 Mon Sep 17 00:00:00 2001
From: deuce <>
Date: Sat, 31 Aug 2013 10:14:56 +0000
Subject: [PATCH] Add some handy IPv6 related functions to sockwrap for
 extracting data from a generic struct sockaddr.

Add a xpms_add_list() for adding a str_list_t full of host[:port] definitions
for when reading a str_list_t from the INI file of interfaces to listen on.
---
 src/xpdev/multisock.c | 35 +++++++++++++++++++++++++++++++++++
 src/xpdev/multisock.h |  4 ++++
 src/xpdev/sockwrap.c  | 24 ++++++++++++++++++++++++
 src/xpdev/sockwrap.h  |  2 ++
 4 files changed, 65 insertions(+)

diff --git a/src/xpdev/multisock.c b/src/xpdev/multisock.c
index a74038cbc0..0e85842af7 100644
--- a/src/xpdev/multisock.c
+++ b/src/xpdev/multisock.c
@@ -134,6 +134,40 @@ BOOL xpms_add(struct xpms_set *xpms_set, int domain, int type,
 	return FALSE;
 }
 
+BOOL xpms_add_list(struct xpms_set *xpms_set, int domain, int type,
+	int protocol, str_list_t list, uint16_t default_port, const char *prot, 
+	void (*sock_init)(SOCKET, void *), int(*bind_init)(BOOL), void *cbdata)
+{
+	char	**iface;
+	char	*host;
+	char	*p, *p2;
+	BOOL	one_good=FALSE;
+	
+	for(iface=list; iface && *iface; iface++) {
+		host=strdup(*iface);
+		WORD	port=default_port;
+
+		if(xpms_set->lprintf)
+			xpms_set->lprintf(LOG_INFO, "Adding %s listening socket on %s", prot, host);
+		p = strrchr(host, ':');
+		if(host[0]=='[') {
+			p2=strrchr(host,']');
+			if(p2)
+				*p2=0;
+			if(p2 > p)
+				p=NULL;
+		}
+		if(p!=NULL) {
+			*(p++)=0;
+			sscanf(p, "%hu", &port);
+		}
+		if(xpms_add(xpms_set, PF_UNSPEC, SOCK_STREAM, 0, host, port, prot, sock_init, bind_init, NULL))
+			one_good=TRUE;
+		free(host);
+	}
+	return one_good;
+}
+
 SOCKET xpms_accept(struct xpms_set *xpms_set, struct sockaddr * addr, 
 	socklen_t * addrlen, unsigned int timeout, void **cb_data)
 {
@@ -184,3 +218,4 @@ SOCKET xpms_accept(struct xpms_set *xpms_set, struct sockaddr * addr,
 
 	return INVALID_SOCKET;
 }
+
diff --git a/src/xpdev/multisock.h b/src/xpdev/multisock.h
index ea73fa19e4..782104f38f 100644
--- a/src/xpdev/multisock.h
+++ b/src/xpdev/multisock.h
@@ -2,6 +2,7 @@
 #define MULTISOCK_H
 
 #include <sys/limits.h>
+#include <str_list.h>
 
 struct xpms_sockdef
 {
@@ -35,6 +36,9 @@ void xpms_destroy(struct xpms_set *xpms_set);
 BOOL xpms_add(struct xpms_set *xpms_set, int domain, int type,
 	int protocol, const char *addr, uint16_t port, const char *prot, 
 	void (*sock_init)(SOCKET, void *), int(*bind_init)(BOOL), void *cbdata);
+BOOL xpms_add_list(struct xpms_set *xpms_set, int domain, int type,
+	int protocol, str_list_t list, uint16_t default_port, const char *prot, 
+	void (*sock_init)(SOCKET, void *), int(*bind_init)(BOOL), void *cbdata);
 SOCKET xpms_accept(struct xpms_set *, struct sockaddr * addr, 
 	socklen_t * addrlen, unsigned int timeout, void **cb_data);
 
diff --git a/src/xpdev/sockwrap.c b/src/xpdev/sockwrap.c
index cfb9ac15ba..eb91b239c4 100644
--- a/src/xpdev/sockwrap.c
+++ b/src/xpdev/sockwrap.c
@@ -386,3 +386,27 @@ int nonblocking_connect(SOCKET sock, struct sockaddr* addr, size_t size, unsigne
 	}
 	return result;
 }
+
+const char *inet_addrtop(SOCKADDR *in, char *dest, size_t size)
+{
+	switch(in->sa_family) {
+		case AF_INET:
+			return inet_ntop(in->sa_family, &((struct sockaddr_in *)in)->sin_addr, dest, size);
+		case AF_INET6:
+			return inet_ntop(in->sa_family, &((struct sockaddr_in6 *)in)->sin6_addr, dest, size);
+		default:
+			return NULL;
+	}
+}
+
+uint16_t inet_addrport(SOCKADDR *in)
+{
+	switch(in->sa_family) {
+		case AF_INET:
+			return ntohs(((struct sockaddr_in *)in)->sin_port);
+		case AF_INET6:
+			return ntohs(((struct sockaddr_in6 *)in)->sin6_port);
+		default:
+			return 0;
+	}
+}
diff --git a/src/xpdev/sockwrap.h b/src/xpdev/sockwrap.h
index f94ee97b64..43412dd10d 100644
--- a/src/xpdev/sockwrap.h
+++ b/src/xpdev/sockwrap.h
@@ -193,6 +193,8 @@ int 	retry_bind(SOCKET s, const struct sockaddr *addr, socklen_t addrlen
 				   ,uint retries, uint wait_secs, const char* prot
 				   ,int (*lprintf)(int level, const char *fmt, ...));
 int		nonblocking_connect(SOCKET, struct sockaddr*, size_t, unsigned timeout /* seconds */);
+const char *inet_addrtop(SOCKADDR *in, char *dest, size_t size);
+uint16_t inet_addrport(SOCKADDR *in);
 
 #ifdef __cplusplus
 }
-- 
GitLab