secondary cache feature in vm.
[minix.git] / lib / libc / ip / nameinfo.c
blob3444c291ff53ce7dc1d6c767ac34c6442c1a2e3f
1 #include <arpa/inet.h>
2 #include <assert.h>
3 #include <errno.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <netdb.h>
8 #include <unistd.h>
10 static size_t first_component_len(const char *s)
12 const char *first = s;
14 /* find the first dot or end of string */
15 while (*s && *s != '.')
16 s++;
18 /* return length */
19 return s - first;
22 static int getnameinfo_get_host(const struct sockaddr_in *sockaddr,
23 char *node, socklen_t nodelen, int flags)
25 struct hostent *hostent;
26 const char *ipaddr;
28 /* perform look-up */
29 if ((flags & NI_NUMERICHOST) != NI_NUMERICHOST)
31 hostent = gethostbyaddr(
32 (char *) &sockaddr->sin_addr,
33 sizeof(sockaddr->sin_addr),
34 AF_INET);
36 if (hostent && hostent->h_name)
38 /* return the hostname that was found */
39 if (nodelen <= strlen(hostent->h_name))
40 return EAI_OVERFLOW;
42 strcpy(node, hostent->h_name);
43 return 0;
47 if ((flags & NI_NAMEREQD) == NI_NAMEREQD)
48 return EAI_NONAME;
50 /* basic implementation to provide numeric values */
51 ipaddr = inet_ntoa(sockaddr->sin_addr);
52 if (nodelen <= strlen(ipaddr))
53 return EAI_OVERFLOW;
55 strcpy(node, ipaddr);
56 return 0;
59 static int getnameinfo_get_serv(const struct sockaddr_in *sockaddr,
60 char *service, socklen_t servicelen, int flags)
62 struct servent *servent;
63 unsigned short port;
65 /* perform look-up */
66 if ((flags & NI_NUMERICSERV) != NI_NUMERICSERV)
68 servent = getservbyport(sockaddr->sin_port,
69 ((flags & NI_DGRAM) == NI_DGRAM) ? "udp" : "tcp");
70 if (servent && servent->s_name)
72 /* return the service name that was found */
73 if (strlen(servent->s_name) >= servicelen)
74 return EAI_OVERFLOW;
76 strcpy(service, servent->s_name);
77 return 0;
81 /* return port number */
82 port = ntohs(sockaddr->sin_port);
83 if (snprintf(service, servicelen, "%u", port) >= servicelen)
84 return EAI_OVERFLOW;
86 return 0;
90 * getnameinfo is based on
91 * http://www.opengroup.org/onlinepubs/009695399/functions/getnameinfo.html
93 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
94 char *node, socklen_t nodelen, char *service,
95 socklen_t servicelen, int flags)
97 int r;
98 const struct sockaddr_in *sockaddr;
101 * The following flags are really supported:
102 * - NI_NUMERICHOST
103 * - NI_NAMEREQD
104 * - NI_NUMERICSERV
105 * - NI_DGRAM
107 * The following flag is not supported:
108 * - NI_NUMERICSCOPE
110 * The following flags could have been supported but is not implemented:
111 * - NI_NOFQDN
114 /* check for invalid parameters; only support IPv4 */
115 if (sa == NULL)
117 errno = EINVAL;
118 return EAI_SYSTEM;
121 if (sa->sa_family != AF_INET || salen != sizeof(struct sockaddr_in))
122 return EAI_FAMILY;
124 if (flags & ~(NI_NUMERICHOST | NI_NAMEREQD | NI_NUMERICSERV | NI_DGRAM))
125 return EAI_BADFLAGS;
127 if ((!node || !nodelen) && (!service || !servicelen))
128 return EAI_NONAME;
130 /* look up host */
131 sockaddr = (const struct sockaddr_in *) sa;
132 if (node && nodelen > 0)
134 r = getnameinfo_get_host(sockaddr, node, nodelen, flags);
135 if (r)
136 return r;
139 /* look up service */
140 if (service && servicelen > 0)
142 r = getnameinfo_get_serv(sockaddr, service, servicelen, flags);
143 if (r)
144 return r;
147 return 0;