summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/getnameinfo.c
diff options
context:
space:
mode:
authorderaadt <>1999-07-03 21:45:44 +0000
committerderaadt <>1999-07-03 21:45:44 +0000
commit0395bc5800143dafc68a0782a5243348d093419e (patch)
treea228bf063fbcb765aec27af54950c8defa19f79f /src/lib/libc/net/getnameinfo.c
parent11b6f12bb197a5b34ad2a1da38937da31e9410ac (diff)
downloadopenbsd-0395bc5800143dafc68a0782a5243348d093419e.tar.gz
openbsd-0395bc5800143dafc68a0782a5243348d093419e.tar.bz2
openbsd-0395bc5800143dafc68a0782a5243348d093419e.zip
cleaned up
Diffstat (limited to 'src/lib/libc/net/getnameinfo.c')
-rw-r--r--src/lib/libc/net/getnameinfo.c388
1 files changed, 210 insertions, 178 deletions
diff --git a/src/lib/libc/net/getnameinfo.c b/src/lib/libc/net/getnameinfo.c
index 1ae197c15a..62c4b9d928 100644
--- a/src/lib/libc/net/getnameinfo.c
+++ b/src/lib/libc/net/getnameinfo.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * %%% copyright-cmetz-96-bsd 2 * %%% copyright-cmetz-96-bsd
3 * Copyright (c) 1996-1999, Craig Metz, All rights reserved. 3 * Copyright (c) 1996-1999, Craig Metz, All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
@@ -17,7 +17,7 @@
17 * 4. Neither the name of the author nor the names of contributors 17 * 4. Neither the name of the author nor the names of contributors
18 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 19 * without specific prior written permission.
20 * 20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -36,197 +36,229 @@
36 36
37#include <sys/types.h> 37#include <sys/types.h>
38#include <sys/socket.h> 38#include <sys/socket.h>
39
40#include <netinet/in.h> 39#include <netinet/in.h>
41#include <sys/un.h> 40#include <sys/un.h>
42#include <sys/utsname.h> 41#include <sys/utsname.h>
43#include <netdb.h> 42#include <netdb.h>
43#include <arpa/inet.h>
44#include <errno.h> 44#include <errno.h>
45#include <string.h> 45#include <string.h>
46#include <resolv.h> 46#include <resolv.h>
47 47
48#ifndef AF_LOCAL 48#ifndef min
49#define AF_LOCAL AF_UNIX
50#endif /* AF_LOCAL */
51
52#ifndef min
53#define min(x,y) (((x) > (y)) ? (y) : (x)) 49#define min(x,y) (((x) > (y)) ? (y) : (x))
54#endif /* min */ 50#endif /* min */
55 51
56#define RETURN_ERROR(x) do { \ 52static int
57 rval = (x); \ 53netdb_lookup_name(int family, void *addr, int addrlen, char *name,
58 goto ret; \ 54 int namelen, int flags)
59 } while(0)
60
61static int netdb_lookup_name(int family, void *addr, int addrlen, char *name,
62 int namelen, int flags)
63{ 55{
64 struct hostent *hostent; 56 struct hostent *hostent;
65 char *c, *c2; 57 char *c, *c2;
66 int rval, i; 58 int i;
67
68 if (!(hostent = gethostbyaddr(addr, addrlen, family))) {
69 switch(h_errno) {
70 case NETDB_INTERNAL:
71 RETURN_ERROR(EAI_SYSTEM);
72 case HOST_NOT_FOUND:
73 RETURN_ERROR(1);
74 case TRY_AGAIN:
75 RETURN_ERROR(EAI_AGAIN);
76 case NO_RECOVERY:
77 RETURN_ERROR(EAI_FAIL);
78 case NO_DATA:
79 RETURN_ERROR(1);
80 default:
81 RETURN_ERROR(EAI_FAIL);
82 };
83 };
84
85 endhostent();
86
87 c = hostent->h_name;
88 if ((flags & NI_NOFQDN) && (_res.options & RES_INIT) && _res.defdname[0] &&
89 (c2 = strstr(c + 1, _res.defdname)) && (*(--c2) == '.')) {
90 *c2 = 0;
91 i = min(c2 - c, namelen) - 1;
92 strncpy(name, c, i);
93 } else
94 strncpy(name, c, namelen - 1);
95
96 rval = 0;
97 59
98ret: 60 if (!(hostent = gethostbyaddr(addr, addrlen, family))) {
99 return rval; 61 switch (h_errno) {
62 case NETDB_INTERNAL:
63 return(EAI_SYSTEM);
64 case HOST_NOT_FOUND:
65 return(1);
66 case TRY_AGAIN:
67 return(EAI_AGAIN);
68 case NO_RECOVERY:
69 return(EAI_FAIL);
70 case NO_DATA:
71 return(1);
72 default:
73 return(EAI_FAIL);
74 }
75 }
76
77 endhostent();
78
79 c = hostent->h_name;
80 if ((flags & NI_NOFQDN) && (_res.options & RES_INIT) && _res.defdname[0] &&
81 (c2 = strstr(c + 1, _res.defdname)) && (*(--c2) == '.')) {
82 *c2 = 0;
83 i = min(c2 - c, namelen);
84 strlcpy(name, c, i);
85 } else
86 strlcpy(name, c, namelen);
87 return 0;
100} 88}
101 89
102int getnameinfo(const struct sockaddr *sa, size_t addrlen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) 90int
91getnameinfo(const struct sockaddr *sa, size_t addrlen, char *host,
92 size_t hostlen, char *serv, size_t servlen, int flags)
103{ 93{
104 int rval; 94 int rval;
105 int serrno = errno; 95 int saved_errno;
106
107 if (!sa || (addrlen != SA_LEN(sa)))
108 RETURN_ERROR(EAI_FAIL);
109
110 if (host && (hostlen > 0))
111 switch(sa->sa_family) {
112 case AF_INET6:
113 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)sa)->sin6_addr)) {
114 if (flags & NI_NUMERICHOST)
115 goto inet6_noname;
116 else
117 strncpy(host, "*", hostlen - 1);
118 break;
119 };
120
121 if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)) {
122 struct sockaddr_in sin;
123 memset(&sin, 0, sizeof(struct sockaddr_in));
124 sin.sin_len = sizeof(struct sockaddr_in);
125 sin.sin_family = AF_INET;
126 sin.sin_port = ((struct sockaddr_in6 *)sa)->sin6_port;
127 sin.sin_addr.s_addr = ((u_int32_t *)&((struct sockaddr_in6 *)sa)->sin6_addr)[3];
128 if (!(rval = getnameinfo((struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, hostlen, serv, servlen, flags | NI_NAMEREQD)))
129 goto ret;
130 if (rval != EAI_NONAME)
131 goto ret;
132 goto inet6_noname;
133 };
134
135 if (flags & NI_NUMERICHOST)
136 goto inet6_noname;
137
138 if ((rval = netdb_lookup_name(AF_INET6,
139 &((struct sockaddr_in6 *)sa)->sin6_addr, sizeof(struct in6_addr),
140 host, hostlen, flags)) < 0)
141 goto ret;
142
143 if (!rval)
144 break;
145
146inet6_noname:
147 if (flags & NI_NAMEREQD)
148 RETURN_ERROR(EAI_NONAME);
149
150 if (!inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr, host, hostlen))
151 RETURN_ERROR(EAI_NONAME);
152
153 break;
154 case AF_INET:
155 if (flags & NI_NUMERICHOST)
156 goto inet_noname;
157
158 if (!((struct sockaddr_in *)sa)->sin_addr.s_addr) {
159 strncpy(host, "*", hostlen - 1);
160 break;
161 };
162
163 if ((rval = netdb_lookup_name(AF_INET,
164 &((struct sockaddr_in *)sa)->sin_addr, sizeof(struct in_addr),
165 host, hostlen, flags)) < 0)
166 goto ret;
167
168 if (!rval)
169 break;
170inet_noname:
171 if (flags & NI_NAMEREQD)
172 RETURN_ERROR(EAI_NONAME);
173
174 if (!inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, host, hostlen))
175 RETURN_ERROR(EAI_NONAME);
176
177 break;
178 case AF_LOCAL:
179 if (!(flags & NI_NUMERICHOST)) {
180 struct utsname utsname;
181
182 if (!uname(&utsname)) {
183 strncpy(host, utsname.nodename, hostlen - 1);
184 break;
185 };
186 };
187
188 if (flags & NI_NAMEREQD)
189 RETURN_ERROR(EAI_NONAME);
190
191 strncpy(host, "localhost", hostlen - 1);
192 break;
193 default:
194 RETURN_ERROR(EAI_FAMILY);
195 };
196
197 if (serv && (servlen > 0))
198 switch(sa->sa_family) {
199 case AF_INET:
200 case AF_INET6:
201 if (!(flags & NI_NUMERICSERV)) {
202 struct servent *s;
203 if (s = getservbyport(((struct sockaddr_in *)sa)->sin_port, (flags & NI_DGRAM) ? "udp" : "tcp")) {
204 strncpy(serv, s->s_name, servlen - 1);
205 break;
206 };
207 if (!((struct sockaddr_in *)sa)->sin_port) {
208 strncpy(serv, "*", servlen - 1);
209 break;
210 };
211 };
212 snprintf(serv, servlen - 1, "%d", ntohs(((struct sockaddr_in *)sa)->sin_port));
213 break;
214 case AF_LOCAL:
215 strncpy(serv, ((struct sockaddr_un *)sa)->sun_path, servlen - 1);
216 break;
217 };
218
219 if (host && (hostlen > 0))
220 host[hostlen-1] = 0;
221 if (serv && (servlen > 0))
222 serv[servlen-1] = 0;
223 rval = 0;
224 96
225ret: 97 if (sa == NULL || addrlen != sa->sa_len)
226 if (rval == 1) 98 return EAI_FAIL;
227 rval = EAI_FAIL; 99 saved_errno = errno;
100
101 if (host && hostlen > 0) {
102 switch (sa->sa_family) {
103 case AF_INET6:
104 {
105 struct sockaddr_in6 *sin6 = (void *)sa;
106
107 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
108 if (flags & NI_NUMERICHOST)
109 goto inet6_noname;
110 strlcpy(host, "*", hostlen);
111 break;
112 }
113
114 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
115 struct sockaddr_in sin;
116
117 memset(&sin, 0, sizeof(struct sockaddr_in));
118 sin.sin_len = sizeof(struct sockaddr_in);
119 sin.sin_family = AF_INET;
120 sin.sin_port = sin6->sin6_port;
121 sin.sin_addr.s_addr =
122 ((u_int32_t *)&sin6->sin6_addr)[3];
123 if (!(rval = getnameinfo((struct sockaddr *)&sin,
124 sizeof(struct sockaddr_in), host, hostlen,
125 serv, servlen, flags | NI_NAMEREQD)))
126 goto ret;
127 if (rval != EAI_NONAME)
128 goto ret;
129 goto inet6_noname;
130 }
131
132 if (flags & NI_NUMERICHOST)
133 goto inet6_noname;
134 if ((rval = netdb_lookup_name(AF_INET6,
135 &sin6->sin6_addr, sizeof(struct in6_addr),
136 host, hostlen, flags)) < 0)
137 goto ret;
228 138
229 errno = serrno; 139 if (!rval)
140 break;
141 inet6_noname:
142 if (flags & NI_NAMEREQD) {
143 rval = EAI_NONAME;
144 goto ret;
145 }
146 if (!inet_ntop(AF_INET6, &sin6->sin6_addr, host, hostlen)) {
147 rval = EAI_NONAME;
148 goto ret;
149 }
150 break;
151 }
152 case AF_INET:
153 {
154 struct sockaddr_in *sin = (void *)sa;
230 155
231 return rval; 156 if (flags & NI_NUMERICHOST)
232}; 157 goto inet_noname;
158
159 if (sin->sin_addr.s_addr == 0) {
160 strlcpy(host, "*", hostlen);
161 break;
162 }
163
164 if ((rval = netdb_lookup_name(AF_INET,
165 &sin->sin_addr, sizeof(struct in_addr),
166 host, hostlen, flags)) < 0)
167 goto ret;
168
169 if (!rval)
170 break;
171 inet_noname:
172 if (flags & NI_NAMEREQD) {
173 rval = EAI_NONAME;
174 goto ret;
175 }
176 if (!inet_ntop(AF_INET, &sin->sin_addr, host, hostlen)) {
177 rval = EAI_NONAME;
178 goto ret;
179 }
180 break;
181 }
182 case AF_LOCAL:
183 if (!(flags & NI_NUMERICHOST)) {
184 struct utsname utsname;
185
186 if (!uname(&utsname)) {
187 strlcpy(host, utsname.nodename, hostlen);
188 break;
189 }
190 }
191
192 if (flags & NI_NAMEREQD) {
193 rval = EAI_NONAME;
194 goto ret;
195 }
196
197 strlcpy(host, "localhost", hostlen);
198 break;
199 default:
200 rval = EAI_FAMILY;
201 goto ret;
202 }
203 }
204
205 if (serv && servlen > 0) {
206 switch (sa->sa_family) {
207 case AF_INET:
208 {
209 struct sockaddr_in *sin = (void *)sa;
210 struct servent *s;
211
212 if ((flags & NI_NUMERICSERV) == 0) {
213 s = getservbyport(sin->sin_port,
214 (flags & NI_DGRAM) ? "udp" : "tcp");
215 if (s) {
216 strlcpy(serv, s->s_name, servlen);
217 break;
218 }
219 if (sin->sin_port == 0) {
220 strlcpy(serv, "*", servlen);
221 break;
222 }
223 }
224 snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
225 break;
226 }
227 case AF_INET6:
228 {
229 struct sockaddr_in6 *sin6 = (void *)sa;
230 struct servent *s;
231
232 if ((flags & NI_NUMERICSERV) == 0) {
233
234 s = getservbyport(sin6->sin6_port,
235 (flags & NI_DGRAM) ? "udp" : "tcp");
236 if (s) {
237 strlcpy(serv, s->s_name, servlen);
238 break;
239 }
240 if (sin6->sin6_port == 0) {
241 strlcpy(serv, "*", servlen);
242 break;
243 }
244 }
245 snprintf(serv, servlen, "%d", ntohs(sin6->sin6_port));
246 break;
247 }
248 case AF_LOCAL:
249 {
250 struct sockaddr_un *sun = (void *)sa;
251
252 strlcpy(serv, sun->sun_path, servlen);
253 break;
254 }
255 }
256 }
257 rval = 0;
258
259ret:
260 if (rval == 1)
261 rval = EAI_FAIL;
262 errno = saved_errno;
263 return (rval);
264}