Bläddra i källkod

improve getservbyname_r using new resolver backend

now that host and service lookup have been separated in the backend,
there's no need for service lookup functions to pull in the host
lookup code. moreover, dynamic allocation is no longer needed, so this
function should now be async-signal-safe. it's also significantly
smaller.

one change in getservbyname is also made: knowing that getservbyname_r
needs only two character pointers in the caller-provided buffer, some
wasted bss can be avoided.
Rich Felker 10 år sedan
förälder
incheckning
af7c308ee6
2 ändrade filer med 16 tillägg och 22 borttagningar
  1. 1 1
      src/network/getservbyname.c
  2. 15 21
      src/network/getservbyname_r.c

+ 1 - 1
src/network/getservbyname.c

@@ -4,7 +4,7 @@
 struct servent *getservbyname(const char *name, const char *prots)
 struct servent *getservbyname(const char *name, const char *prots)
 {
 {
 	static struct servent se;
 	static struct servent se;
-	static long buf[32/sizeof(long)];
+	static char *buf[2];
 	struct servent *res;
 	struct servent *res;
 	if (getservbyname_r(name, prots, &se, (void *)buf, sizeof buf, &res))
 	if (getservbyname_r(name, prots, &se, (void *)buf, sizeof buf, &res))
 		return 0;
 		return 0;

+ 15 - 21
src/network/getservbyname_r.c

@@ -5,49 +5,43 @@
 #include <inttypes.h>
 #include <inttypes.h>
 #include <errno.h>
 #include <errno.h>
 #include <string.h>
 #include <string.h>
+#include "lookup.h"
+
+#define ALIGN (sizeof(struct { char a; char *b; }) - sizeof(char *))
 
 
 int getservbyname_r(const char *name, const char *prots,
 int getservbyname_r(const char *name, const char *prots,
 	struct servent *se, char *buf, size_t buflen, struct servent **res)
 	struct servent *se, char *buf, size_t buflen, struct servent **res)
 {
 {
-	struct addrinfo *ai, hint = { .ai_family = AF_INET };
-	int i;
-
-	if (!prots) {
-		int r = getservbyname_r(name, "tcp", se, buf, buflen, res);
-		if (r) r = getservbyname_r(name, "udp", se, buf, buflen, res);
-		return r;
-	}
+	struct service servs[MAXSERVS];
+	int cnt, proto, align;
 
 
 	/* Align buffer */
 	/* Align buffer */
-	i = (uintptr_t)buf & sizeof(char *)-1;
-	if (!i) i = sizeof(char *);
-	if (buflen < 3*sizeof(char *)-i)
+	align = -(uintptr_t)buf & ALIGN-1;
+	if (buflen < 2*sizeof(char *)+align)
 		return ERANGE;
 		return ERANGE;
-	buf += sizeof(char *)-i;
-	buflen -= sizeof(char *)-i;
+	buf += align;
 
 
-	if (!strcmp(prots, "tcp")) hint.ai_protocol = IPPROTO_TCP;
-	else if (!strcmp(prots, "udp")) hint.ai_protocol = IPPROTO_UDP;
+	if (!prots) proto = 0;
+	else if (!strcmp(prots, "tcp")) proto = IPPROTO_TCP;
+	else if (!strcmp(prots, "udp")) proto = IPPROTO_UDP;
 	else return EINVAL;
 	else return EINVAL;
 
 
-	switch (getaddrinfo(0, name, &hint, &ai)) {
+	cnt = __lookup_serv(servs, name, proto, 0);
+	if (cnt<0) switch (cnt) {
 	case EAI_MEMORY:
 	case EAI_MEMORY:
 	case EAI_SYSTEM:
 	case EAI_SYSTEM:
 		return ENOMEM;
 		return ENOMEM;
 	default:
 	default:
 		return ENOENT;
 		return ENOENT;
-	case 0:
-		break;
 	}
 	}
 
 
 	se->s_name = (char *)name;
 	se->s_name = (char *)name;
 	se->s_aliases = (void *)buf;
 	se->s_aliases = (void *)buf;
 	se->s_aliases[0] = se->s_name;
 	se->s_aliases[0] = se->s_name;
 	se->s_aliases[1] = 0;
 	se->s_aliases[1] = 0;
-	se->s_port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
-	se->s_proto = (char *)prots;
+	se->s_port = htons(servs[0].port);
+	se->s_proto = servs[0].proto == IPPROTO_TCP ? "tcp" : "udp";
 
 
-	freeaddrinfo(ai);
 	*res = se;
 	*res = se;
 	return 0;
 	return 0;
 }
 }