mirror of
git://git.musl-libc.org/musl
synced 2025-03-06 20:48:29 +01:00
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.
This commit is contained in:
parent
e8f39ca489
commit
af7c308ee6
2 changed files with 16 additions and 22 deletions
|
@ -4,7 +4,7 @@
|
|||
struct servent *getservbyname(const char *name, const char *prots)
|
||||
{
|
||||
static struct servent se;
|
||||
static long buf[32/sizeof(long)];
|
||||
static char *buf[2];
|
||||
struct servent *res;
|
||||
if (getservbyname_r(name, prots, &se, (void *)buf, sizeof buf, &res))
|
||||
return 0;
|
||||
|
|
|
@ -5,49 +5,43 @@
|
|||
#include <inttypes.h>
|
||||
#include <errno.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,
|
||||
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 */
|
||||
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;
|
||||
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;
|
||||
|
||||
switch (getaddrinfo(0, name, &hint, &ai)) {
|
||||
cnt = __lookup_serv(servs, name, proto, 0);
|
||||
if (cnt<0) switch (cnt) {
|
||||
case EAI_MEMORY:
|
||||
case EAI_SYSTEM:
|
||||
return ENOMEM;
|
||||
default:
|
||||
return ENOENT;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
se->s_name = (char *)name;
|
||||
se->s_aliases = (void *)buf;
|
||||
se->s_aliases[0] = se->s_name;
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue