about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/network/getaddrinfo.c34
-rw-r--r--src/network/getservbyname_r.c2
-rw-r--r--src/network/lookup.h4
-rw-r--r--src/network/lookup_serv.c36
4 files changed, 42 insertions, 34 deletions
diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c
index d9913445..c88d558c 100644
--- a/src/network/getaddrinfo.c
+++ b/src/network/getaddrinfo.c
@@ -11,7 +11,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 	struct address addrs[MAXADDRS];
 	char canon[256], *outcanon;
 	int nservs, naddrs, nais, canon_len, i, j, k;
-	int family = AF_UNSPEC, flags = 0, proto = 0;
+	int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0;
 	struct aibuf {
 		struct addrinfo ai;
 		union sa {
@@ -24,6 +24,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 		family = hint->ai_family;
 		flags = hint->ai_flags;
 		proto = hint->ai_protocol;
+		socktype = hint->ai_socktype;
 
 		const int mask = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST |
 			AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG | AI_NUMERICSERV;
@@ -38,35 +39,9 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 		default:
 			return EAI_FAMILY;
 		}
-
-		switch (hint->ai_socktype) {
-		case SOCK_STREAM:
-			switch (proto) {
-			case 0:
-				proto = IPPROTO_TCP;
-			case IPPROTO_TCP:
-				break;
-			default:
-				return EAI_SERVICE;
-			}
-			break;
-		case SOCK_DGRAM:
-			switch (proto) {
-			case 0:
-				proto = IPPROTO_UDP;
-			case IPPROTO_UDP:
-				break;
-			default:
-				return EAI_SERVICE;
-			}
-		case 0:
-			break;
-		default:
-			return EAI_SOCKTYPE;
-		}
 	}
 
-	nservs = __lookup_serv(ports, serv, proto, flags);
+	nservs = __lookup_serv(ports, serv, proto, socktype, flags);
 	if (nservs < 0) return nservs;
 
 	naddrs = __lookup_name(addrs, canon, host, family, flags);
@@ -87,8 +62,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 	for (k=i=0; i<naddrs; i++) for (j=0; j<nservs; j++, k++) {
 		out[k].ai = (struct addrinfo){
 			.ai_family = addrs[i].family,
-			.ai_socktype = ports[j].proto == IPPROTO_TCP
-				? SOCK_STREAM : SOCK_DGRAM,
+			.ai_socktype = ports[j].socktype,
 			.ai_protocol = ports[j].proto,
 			.ai_addrlen = addrs[i].family == AF_INET
 				? sizeof(struct sockaddr_in)
diff --git a/src/network/getservbyname_r.c b/src/network/getservbyname_r.c
index 8cdf622c..056c2f33 100644
--- a/src/network/getservbyname_r.c
+++ b/src/network/getservbyname_r.c
@@ -26,7 +26,7 @@ int getservbyname_r(const char *name, const char *prots,
 	else if (!strcmp(prots, "udp")) proto = IPPROTO_UDP;
 	else return EINVAL;
 
-	cnt = __lookup_serv(servs, name, proto, 0);
+	cnt = __lookup_serv(servs, name, proto, 0, 0);
 	if (cnt<0) switch (cnt) {
 	case EAI_MEMORY:
 	case EAI_SYSTEM:
diff --git a/src/network/lookup.h b/src/network/lookup.h
index 4e45d869..69419115 100644
--- a/src/network/lookup.h
+++ b/src/network/lookup.h
@@ -12,7 +12,7 @@ struct address {
 
 struct service {
 	uint16_t port;
-	char proto;
+	unsigned char proto, socktype;
 };
 
 /* The limit of 48 results is a non-sharp bound on the number of addresses
@@ -21,7 +21,7 @@ struct service {
 #define MAXADDRS 48
 #define MAXSERVS 2
 
-int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int flags);
+int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int socktype, int flags);
 int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags);
 int __lookup_ipliteral(struct address buf[static 1], const char *name, int family);
 
diff --git a/src/network/lookup_serv.c b/src/network/lookup_serv.c
index a9be0f3d..4faa5bc7 100644
--- a/src/network/lookup_serv.c
+++ b/src/network/lookup_serv.c
@@ -7,13 +7,43 @@
 #include "lookup.h"
 #include "stdio_impl.h"
 
-int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int flags)
+int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int socktype, int flags)
 {
 	char line[128];
 	int cnt = 0;
 	char *p, *z = "";
 	unsigned long port = 0;
 
+	switch (socktype) {
+	case SOCK_STREAM:
+		switch (proto) {
+		case 0:
+			proto = IPPROTO_TCP;
+		case IPPROTO_TCP:
+			break;
+		default:
+			return EAI_SERVICE;
+		}
+		break;
+	case SOCK_DGRAM:
+		switch (proto) {
+		case 0:
+			proto = IPPROTO_UDP;
+		case IPPROTO_UDP:
+			break;
+		default:
+			return EAI_SERVICE;
+		}
+	case 0:
+		break;
+	default:
+		if (name) return EAI_SERVICE;
+		buf[0].port = 0;
+		buf[0].proto = proto;
+		buf[0].socktype = socktype;
+		return 1;
+	}
+
 	if (name) {
 		if (!*name) return EAI_SERVICE;
 		port = strtoul(name, &z, 10);
@@ -22,10 +52,12 @@ int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int pro
 		if (port > 65535) return EAI_SERVICE;
 		if (proto != IPPROTO_UDP) {
 			buf[cnt].port = port;
+			buf[cnt].socktype = SOCK_STREAM;
 			buf[cnt++].proto = IPPROTO_TCP;
 		}
 		if (proto != IPPROTO_TCP) {
 			buf[cnt].port = port;
+			buf[cnt].socktype = SOCK_DGRAM;
 			buf[cnt++].proto = IPPROTO_UDP;
 		}
 		return cnt;
@@ -58,11 +90,13 @@ int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int pro
 		if (!strncmp(z, "/udp", 4)) {
 			if (proto == IPPROTO_TCP) continue;
 			buf[cnt].port = port;
+			buf[cnt].socktype = SOCK_DGRAM;
 			buf[cnt++].proto = IPPROTO_UDP;
 		}
 		if (!strncmp(z, "/tcp", 4)) {
 			if (proto == IPPROTO_UDP) continue;
 			buf[cnt].port = port;
+			buf[cnt].socktype = SOCK_STREAM;
 			buf[cnt++].proto = IPPROTO_TCP;
 		}
 	}