sock: add connect_addr that takes the destination address directly

Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
3 files changed, 35 insertions(+), 0 deletions(-)

M include/jeffpc/sock.h
M mapfile-vers
M sock.c
M include/jeffpc/sock.h +1 -0
@@ 55,6 55,7 @@ extern void xsockaddr_copy(union xsockad
 extern int xsockaddr_get_inet_port(const union xsockaddr *u, uint16_t *port_r);
 extern int xsockaddr_set_inet_port(union xsockaddr *u, uint16_t port);
 
+extern int connect_addr(const union xsockaddr *addr, enum ip_type type);
 extern int connect_ip(const char *host, uint16_t port, bool v4, bool v6,
 		      enum ip_type type);
 

          
M mapfile-vers +1 -0
@@ 262,6 262,7 @@ JEFFPC_0.10 {
 		sexpr_parse;
 
 		# sock
+		connect_addr;
 		connect_ip;
 		xgethostname;
 		xsockaddr_cmp;

          
M sock.c +33 -0
@@ 71,6 71,39 @@ unknown:
 	return "<unknown>";
 }
 
+int connect_addr(const union xsockaddr *addr, enum ip_type type)
+{
+	size_t addrlen;
+	int sock;
+
+	if (!addr || (type != IP_TCP))
+		return -EINVAL;
+
+	switch (addr->sa.sa_family) {
+		case AF_INET:
+			addrlen = sizeof(addr->inet);
+			break;
+		case AF_INET6:
+			addrlen = sizeof(addr->inet6);
+			break;
+		default:
+			return -ENOTSUP;
+	}
+
+	sock = socket(addr->sa.sa_family, SOCK_STREAM, 0);
+	if (sock == -1)
+		return -errno;
+
+	if (connect(sock, &addr->sa, addrlen) == -1) {
+		const int tmp = -errno;
+
+		close(sock);
+		sock = tmp;
+	}
+
+	return sock;
+}
+
 int connect_ip(const char *host, uint16_t port, bool v4, bool v6, enum ip_type type)
 {
 	struct addrinfo hints, *res, *p;