1214152Sed#define _GNU_SOURCE
2214152Sed#include "lookup.h"
3214152Sed#include <errno.h>
4214152Sed#include <inttypes.h>
5222656Sed#include <netdb.h>
6222656Sed#include <netinet/in.h>
7214152Sed#include <string.h>
8214152Sed#include <sys/socket.h>
9214152Sed
10214152Sed#define ALIGN        \
11214152Sed    (sizeof(struct { \
12214152Sed         char a;     \
13214152Sed         char* b;    \
14214152Sed     }) -            \
15214152Sed     sizeof(char*))
16229135Sed
17214152Sedint getservbyname_r(const char* name, const char* prots, struct servent* se, char* buf,
18214152Sed                    size_t buflen, struct servent** res) {
19214152Sed    struct service servs[MAXSERVS];
20214152Sed    int cnt, proto, align;
21214152Sed
22214152Sed    /* Align buffer */
23214152Sed    align = -(uintptr_t)buf & (ALIGN - 1);
24214152Sed    if (buflen < 2 * sizeof(char*) + align)
25214152Sed        return ERANGE;
26214152Sed    buf += align;
27214152Sed
28214152Sed    if (!prots)
29214152Sed        proto = 0;
30229135Sed    else if (!strcmp(prots, "tcp"))
31214152Sed        proto = IPPROTO_TCP;
32214152Sed    else if (!strcmp(prots, "udp"))
33229135Sed        proto = IPPROTO_UDP;
34214152Sed    else
35229135Sed        return EINVAL;
36229135Sed
37229135Sed    cnt = __lookup_serv(servs, name, proto, 0, 0);
38229135Sed    if (cnt < 0)
39229135Sed        switch (cnt) {
40229135Sed        case EAI_MEMORY:
41214152Sed        case EAI_SYSTEM:
42214152Sed            return ENOMEM;
43229135Sed        default:
44214152Sed            return ENOENT;
45229135Sed        }
46229135Sed
47229135Sed    se->s_name = (char*)name;
48229135Sed    se->s_aliases = (void*)buf;
49229135Sed    se->s_aliases[0] = se->s_name;
50229135Sed    se->s_aliases[1] = 0;
51214152Sed    se->s_port = htons(servs[0].port);
52214152Sed    se->s_proto = (char*)(servs[0].proto == IPPROTO_TCP ? "tcp" : "udp");
53229135Sed
54229135Sed    *res = se;
55214152Sed    return 0;
56229135Sed}
57229135Sed