diff options
author | cmetz <> | 1999-06-23 21:55:29 +0000 |
---|---|---|
committer | cmetz <> | 1999-06-23 21:55:29 +0000 |
commit | bdf7624d67f3bba1a3faed9abf0d2d27291c1cce (patch) | |
tree | 5cb85a83aaa8913b4f148b657a99b1fb4982d71d /src/lib/libc/net/getnameinfo.c | |
parent | 119cda95bf950cdcba7a16178e7f48fdf84f58d0 (diff) | |
download | openbsd-bdf7624d67f3bba1a3faed9abf0d2d27291c1cce.tar.gz openbsd-bdf7624d67f3bba1a3faed9abf0d2d27291c1cce.tar.bz2 openbsd-bdf7624d67f3bba1a3faed9abf0d2d27291c1cce.zip |
Added some protocol independent interfaces (supposedly IPv6 support APIs, but
ones that are useful for all protocols, not just IPv6).
Diffstat (limited to 'src/lib/libc/net/getnameinfo.c')
-rw-r--r-- | src/lib/libc/net/getnameinfo.c | 562 |
1 files changed, 562 insertions, 0 deletions
diff --git a/src/lib/libc/net/getnameinfo.c b/src/lib/libc/net/getnameinfo.c new file mode 100644 index 0000000000..15aa67d464 --- /dev/null +++ b/src/lib/libc/net/getnameinfo.c | |||
@@ -0,0 +1,562 @@ | |||
1 | /* | ||
2 | * %%% copyright-cmetz-96-bsd | ||
3 | * Copyright (c) 1996-1999, Craig Metz, All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * 2. Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * 3. All advertising materials mentioning features or use of this software | ||
14 | * must display the following acknowledgement: | ||
15 | * This product includes software developed by Craig Metz and | ||
16 | * by other 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 | ||
19 | * without specific prior written permission. | ||
20 | * | ||
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 | ||
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
31 | * SUCH DAMAGE. | ||
32 | * | ||
33 | * Redistribution and use in source and binary forms, with or without | ||
34 | * modification, are permitted provided that the following conditions | ||
35 | * are met: | ||
36 | * 1. Redistributions of source code must retain the above copyright | ||
37 | * notice, this list of conditions and the following disclaimer. | ||
38 | * 2. Redistributions in binary form must reproduce the above copyright | ||
39 | * notice, this list of conditions and the following disclaimer in the | ||
40 | * documentation and/or other materials provided with the distribution. | ||
41 | * 3. All advertising materials mentioning features or use of this software | ||
42 | * must display the following acknowledgement: | ||
43 | * This product includes software developed by Craig Metz and | ||
44 | * by other contributors. | ||
45 | * 4. Neither the name of the author nor the names of contributors | ||
46 | * may be used to endorse or promote products derived from this software | ||
47 | * without specific prior written permission. | ||
48 | * | ||
49 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
50 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
51 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
55 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
59 | * SUCH DAMAGE. | ||
60 | * | ||
61 | * Redistribution and use in source and binary forms, with or without | ||
62 | * modification, are permitted provided that the following conditions | ||
63 | * are met: | ||
64 | * 1. Redistributions of source code must retain the above copyright | ||
65 | * notice, this list of conditions and the following disclaimer. | ||
66 | * 2. Redistributions in binary form must reproduce the above copyright | ||
67 | * notice, this list of conditions and the following disclaimer in the | ||
68 | * documentation and/or other materials provided with the distribution. | ||
69 | * 3. All advertising materials mentioning features or use of this software | ||
70 | * must display the following acknowledgement: | ||
71 | * This product includes software developed by Craig Metz and | ||
72 | * by other contributors. | ||
73 | * 4. Neither the name of the author nor the names of contributors | ||
74 | * may be used to endorse or promote products derived from this software | ||
75 | * without specific prior written permission. | ||
76 | * | ||
77 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
78 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
79 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
80 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
81 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
82 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
83 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
84 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
85 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
86 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
87 | * SUCH DAMAGE. | ||
88 | */ | ||
89 | |||
90 | /* getnameinfo() v1.38 */ | ||
91 | |||
92 | /* To enable debugging support (REQUIRES NRL support library), define: */ | ||
93 | /* #define DEBUG 1 */ | ||
94 | |||
95 | #ifdef __OpenBSD__ | ||
96 | #define HAVE_POSIX1G_TYPES 1 | ||
97 | #define INET6 1 | ||
98 | #define LOCAL 1 | ||
99 | #define NETDB 1 | ||
100 | #define SALEN 1 | ||
101 | #undef RESOLVER | ||
102 | #undef HOSTTABLE | ||
103 | #undef DEBUG | ||
104 | #undef HAVE_GETSERVBYNAME_R | ||
105 | #undef HAVE_GETHOSTBYNAME2_R | ||
106 | #endif /* __OpenBSD__ */ | ||
107 | |||
108 | #include <sys/types.h> | ||
109 | #include <sys/socket.h> | ||
110 | |||
111 | #include <netinet/in.h> | ||
112 | #if LOCAL | ||
113 | #include <sys/un.h> | ||
114 | #include <sys/utsname.h> | ||
115 | #endif /* LOCAL */ | ||
116 | #include <netdb.h> | ||
117 | #include <errno.h> | ||
118 | #include <string.h> | ||
119 | #if RESOLVER | ||
120 | #include <arpa/nameser.h> | ||
121 | #include <resolv.h> | ||
122 | #endif /* RESOLVER */ | ||
123 | |||
124 | #include "support.h" | ||
125 | |||
126 | #ifndef AF_LOCAL | ||
127 | #define AF_LOCAL AF_UNIX | ||
128 | #endif /* AF_LOCAL */ | ||
129 | |||
130 | #ifndef min | ||
131 | #define min(x,y) (((x) > (y)) ? (y) : (x)) | ||
132 | #endif /* min */ | ||
133 | |||
134 | #if DEBUG | ||
135 | #if RESOLVER | ||
136 | #define DEBUG_MESSAGES (_res.options & RES_DEBUG) | ||
137 | #else /* RESOLVER */ | ||
138 | int __getnameinfo_debug = 0; | ||
139 | #define DEBUG_MESSAGES (__getnameinfo_debug) | ||
140 | #endif /* RESOLVER */ | ||
141 | #endif /* DEBUG */ | ||
142 | |||
143 | #if DEBUG | ||
144 | #define RETURN_ERROR(x) do { \ | ||
145 | if (DEBUG_MESSAGES) \ | ||
146 | fprintf(stderr, "%s:%d: returning %s\n", __FILE__, __LINE__, #x); \ | ||
147 | rval = (x); \ | ||
148 | goto ret; \ | ||
149 | } while(0) | ||
150 | #else /* DEBUG */ | ||
151 | #define RETURN_ERROR(x) do { \ | ||
152 | rval = (x); \ | ||
153 | goto ret; \ | ||
154 | } while(0) | ||
155 | #endif /* DEBUG */ | ||
156 | |||
157 | #if HOSTTABLE | ||
158 | static int hosttable_lookup_name(int family, void *addr, char *name, int namelen, int flags) | ||
159 | { | ||
160 | int rval; | ||
161 | FILE *f; | ||
162 | char buffer[1024]; | ||
163 | char addrbuf[16]; | ||
164 | char *c, *c2; | ||
165 | int i; | ||
166 | char *prevcname = NULL; | ||
167 | |||
168 | if (!(f = fopen("/etc/hosts", "r"))) | ||
169 | RETURN_ERROR(EAI_SYSTEM); | ||
170 | |||
171 | while(fgets(buffer, sizeof(buffer), f)) { | ||
172 | if (c = strchr(buffer, '#')) | ||
173 | *c = 0; | ||
174 | |||
175 | c = buffer; | ||
176 | while(*c && !isspace(*c)) c++; | ||
177 | if (!*c) | ||
178 | continue; | ||
179 | |||
180 | *(c++) = 0; | ||
181 | |||
182 | if (family == AF_INET) | ||
183 | if (inet_pton(AF_INET, buffer, addrbuf) > 0) | ||
184 | if (!memcmp(addrbuf, addr, sizeof(struct in_addr))) | ||
185 | goto build; | ||
186 | |||
187 | #if INET6 | ||
188 | if (family == AF_INET6) | ||
189 | if (inet_pton(AF_INET6, buffer, addrbuf) > 0) | ||
190 | if (!memcmp(addrbuf, addr, sizeof(struct in6_addr))) | ||
191 | goto build; | ||
192 | #endif /* INET6 */ | ||
193 | |||
194 | continue; | ||
195 | |||
196 | build: | ||
197 | while(*c && isspace(*c)) c++; | ||
198 | if (!*c) | ||
199 | continue; | ||
200 | |||
201 | c2 = c; | ||
202 | while(*c2 && !isspace(*c2)) c2++; | ||
203 | if (!*c2) | ||
204 | continue; | ||
205 | *c2 = 0; | ||
206 | |||
207 | if ((flags & NI_NOFQDN) && (_res.options & RES_INIT) && _res.defdname[0] && (c2 = strstr(c + 1, _res.defdname)) && (*(--c2) == '.')) { | ||
208 | *c2 = 0; | ||
209 | i = min(c2 - c, namelen) - 1; | ||
210 | strncpy(name, c, i); | ||
211 | } else | ||
212 | strncpy(name, c, namelen - 1); | ||
213 | |||
214 | rval = 0; | ||
215 | goto ret; | ||
216 | }; | ||
217 | |||
218 | RETURN_ERROR(1); | ||
219 | |||
220 | ret: | ||
221 | fclose(f); | ||
222 | return rval; | ||
223 | }; | ||
224 | #endif /* HOSTTABLE */ | ||
225 | |||
226 | #if RESOLVER | ||
227 | #if INET6 | ||
228 | static char hextab[] = { '0', '1', '2', '3', '4', '5', '6', '7', | ||
229 | '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; | ||
230 | #endif /* INET6 */ | ||
231 | |||
232 | struct rrheader { | ||
233 | int16_t type; | ||
234 | int16_t class; | ||
235 | u_int32_t ttl; | ||
236 | int16_t size; | ||
237 | }; | ||
238 | #define RRHEADER_SZ 10 | ||
239 | |||
240 | int resolver_lookup_name(const char *ptrname, char *name, int namelen, int flags) | ||
241 | { | ||
242 | int rval; | ||
243 | char answer[PACKETSZ]; | ||
244 | int answerlen; | ||
245 | char dn[MAXDNAME]; | ||
246 | char *prevcname = NULL; | ||
247 | void *p, *ep; | ||
248 | int answers, i; | ||
249 | uint16_t rtype, rclass; | ||
250 | |||
251 | if ((answerlen = res_search(ptrname, C_IN, T_PTR, answer, sizeof(answer))) < 0) { | ||
252 | switch(h_errno) { | ||
253 | case NETDB_INTERNAL: | ||
254 | RETURN_ERROR(EAI_SYSTEM); | ||
255 | case HOST_NOT_FOUND: | ||
256 | RETURN_ERROR(1); | ||
257 | case TRY_AGAIN: | ||
258 | RETURN_ERROR(EAI_AGAIN); | ||
259 | case NO_RECOVERY: | ||
260 | RETURN_ERROR(EAI_FAIL); | ||
261 | case NO_DATA: | ||
262 | RETURN_ERROR(1); | ||
263 | default: | ||
264 | RETURN_ERROR(EAI_FAIL); | ||
265 | }; | ||
266 | }; | ||
267 | |||
268 | p = answer; | ||
269 | ep = answer + answerlen; | ||
270 | |||
271 | if (answerlen < sizeof(HEADER)) | ||
272 | RETURN_ERROR(EAI_FAIL); | ||
273 | |||
274 | { | ||
275 | HEADER *h = (HEADER *)p; | ||
276 | if (!h->qr || (h->opcode != QUERY) || (h->qdcount != htons(1)) || !h->ancount) | ||
277 | RETURN_ERROR(EAI_FAIL); | ||
278 | |||
279 | answers = ntohs(h->ancount); | ||
280 | }; | ||
281 | p += sizeof(HEADER); | ||
282 | |||
283 | if ((i = dn_expand(answer, ep, p, dn, sizeof(dn))) < 0) | ||
284 | RETURN_ERROR(EAI_FAIL); | ||
285 | |||
286 | p += i; | ||
287 | |||
288 | if (p + 2*sizeof(u_int16_t) >= ep) | ||
289 | RETURN_ERROR(EAI_FAIL); | ||
290 | |||
291 | GETSHORT(rtype, p); | ||
292 | GETSHORT(rclass, p); | ||
293 | |||
294 | if ((rtype != T_PTR) || (rclass != C_IN)) | ||
295 | RETURN_ERROR(EAI_FAIL); | ||
296 | |||
297 | while(answers--) { | ||
298 | if ((i = dn_expand(answer, ep, p, dn, sizeof(dn))) < 0) | ||
299 | RETURN_ERROR(EAI_FAIL); | ||
300 | |||
301 | p += i; | ||
302 | |||
303 | if (p + RRHEADER_SZ >= ep) | ||
304 | RETURN_ERROR(EAI_FAIL); | ||
305 | |||
306 | GETSHORT(rtype, p); | ||
307 | GETSHORT(rclass, p); | ||
308 | p += sizeof(uint32_t); | ||
309 | if (rclass != C_IN) | ||
310 | RETURN_ERROR(EAI_FAIL); | ||
311 | GETSHORT(rclass, p); | ||
312 | i = rclass; | ||
313 | |||
314 | if (p + i > ep) | ||
315 | RETURN_ERROR(EAI_FAIL); | ||
316 | |||
317 | if (rtype == T_PTR) { | ||
318 | if (dn_expand(answer, ep, p, dn, sizeof(dn)) != i) | ||
319 | RETURN_ERROR(EAI_FAIL); | ||
320 | |||
321 | { | ||
322 | char *c2; | ||
323 | |||
324 | if ((flags & NI_NOFQDN) && (_res.options & RES_INIT) && _res.defdname[0] && (c2 = strstr(dn + 1, _res.defdname)) && (*(--c2) == '.')) { | ||
325 | *c2 = 0; | ||
326 | strncpy(name, dn, min(c2 - dn, namelen) - 1); | ||
327 | } else | ||
328 | strncpy(name, dn, namelen - 1); | ||
329 | }; | ||
330 | }; | ||
331 | p += i; | ||
332 | }; | ||
333 | |||
334 | rval = 0; | ||
335 | |||
336 | ret: | ||
337 | return rval; | ||
338 | }; | ||
339 | #endif /* RESOLVER */ | ||
340 | |||
341 | #if NETDB | ||
342 | static int netdb_lookup_name(int family, void *addr, int addrlen, char *name, | ||
343 | int namelen) | ||
344 | { | ||
345 | struct hostent *hostent; | ||
346 | char *c, *c2; | ||
347 | int rval, i; | ||
348 | |||
349 | if (!(hostent = gethostbyaddr(addr, addrlen, family))) { | ||
350 | switch(h_errno) { | ||
351 | case NETDB_INTERNAL: | ||
352 | RETURN_ERROR(EAI_SYSTEM); | ||
353 | case HOST_NOT_FOUND: | ||
354 | RETURN_ERROR(1); | ||
355 | case TRY_AGAIN: | ||
356 | RETURN_ERROR(EAI_AGAIN); | ||
357 | case NO_RECOVERY: | ||
358 | RETURN_ERROR(EAI_FAIL); | ||
359 | case NO_DATA: | ||
360 | RETURN_ERROR(1); | ||
361 | default: | ||
362 | RETURN_ERROR(EAI_FAIL); | ||
363 | }; | ||
364 | }; | ||
365 | |||
366 | endhostent(); | ||
367 | |||
368 | c = hostent->h_name; | ||
369 | if ((flags & NI_NOFQDN) && (_res.options & RES_INIT) && _res.defdname[0] && | ||
370 | (c2 = strstr(c + 1, _res.defdname)) && (*(--c2) == '.')) { | ||
371 | *c2 = 0; | ||
372 | i = min(c2 - c, namelen) - 1; | ||
373 | strncpy(name, c, i); | ||
374 | } else | ||
375 | strncpy(name, c, namelen - 1); | ||
376 | |||
377 | rval = 0; | ||
378 | |||
379 | ret: | ||
380 | return rval; | ||
381 | } | ||
382 | #endif /* NETDB */ | ||
383 | |||
384 | int getnameinfo(const struct sockaddr *sa, size_t addrlen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) | ||
385 | { | ||
386 | int rval; | ||
387 | int serrno = errno; | ||
388 | |||
389 | if (!sa || (addrlen != SA_LEN(sa))) | ||
390 | RETURN_ERROR(EAI_FAIL); | ||
391 | |||
392 | if (host && (hostlen > 0)) | ||
393 | switch(sa->sa_family) { | ||
394 | #if INET6 | ||
395 | case AF_INET6: | ||
396 | if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)sa)->sin6_addr)) { | ||
397 | if (flags & NI_NUMERICHOST) | ||
398 | goto inet6_noname; | ||
399 | else | ||
400 | strncpy(host, "*", hostlen - 1); | ||
401 | break; | ||
402 | }; | ||
403 | |||
404 | if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)) { | ||
405 | struct sockaddr_in sin; | ||
406 | memset(&sin, 0, sizeof(struct sockaddr_in)); | ||
407 | #if SALEN | ||
408 | sin.sin_len = sizeof(struct sockaddr_in); | ||
409 | #endif /* SALEN */ | ||
410 | sin.sin_family = AF_INET; | ||
411 | sin.sin_port = ((struct sockaddr_in6 *)sa)->sin6_port; | ||
412 | sin.sin_addr.s_addr = ((u_int32_t *)&((struct sockaddr_in6 *)sa)->sin6_addr)[3]; | ||
413 | if (!(rval = getnameinfo((struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, hostlen, serv, servlen, flags | NI_NAMEREQD))) | ||
414 | goto ret; | ||
415 | if (rval != EAI_NONAME) | ||
416 | goto ret; | ||
417 | goto inet6_noname; | ||
418 | }; | ||
419 | |||
420 | if (flags & NI_NUMERICHOST) | ||
421 | goto inet6_noname; | ||
422 | |||
423 | #if HOSTTABLE | ||
424 | if ((rval = hosttable_lookup_name(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr, host, hostlen, flags)) < 0) | ||
425 | goto ret; | ||
426 | |||
427 | if (!rval) | ||
428 | break; | ||
429 | #endif /* HOSTTABLE */ | ||
430 | #if RESOLVER | ||
431 | { | ||
432 | char ptrname[sizeof("0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.int.")]; | ||
433 | { | ||
434 | int i; | ||
435 | char *c = ptrname; | ||
436 | u_int8_t *p = (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr + sizeof(struct in6_addr) - 1; | ||
437 | |||
438 | for (i = sizeof(struct in6_addr) / sizeof(u_int8_t); i > 0; i--, p--) { | ||
439 | *(c++) = hextab[*p & 0x0f]; | ||
440 | *(c++) = '.'; | ||
441 | *(c++) = hextab[(*p & 0xf0) >> 4]; | ||
442 | *(c++) = '.'; | ||
443 | }; | ||
444 | strcpy(c, "ip6.int."); | ||
445 | }; | ||
446 | |||
447 | if ((rval = resolver_lookup_name(ptrname, host, hostlen, flags)) < 0) | ||
448 | goto ret; | ||
449 | |||
450 | if (!rval) | ||
451 | break; | ||
452 | }; | ||
453 | #endif /* RESOLVER */ | ||
454 | |||
455 | inet6_noname: | ||
456 | if (flags & NI_NAMEREQD) | ||
457 | RETURN_ERROR(EAI_NONAME); | ||
458 | |||
459 | if (!inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr, host, hostlen)) | ||
460 | RETURN_ERROR(EAI_NONAME); | ||
461 | |||
462 | break; | ||
463 | #endif /* INET6 */ | ||
464 | case AF_INET: | ||
465 | if (flags & NI_NUMERICHOST) | ||
466 | goto inet_noname; | ||
467 | |||
468 | if (!((struct sockaddr_in *)sa)->sin_addr.s_addr) { | ||
469 | strncpy(host, "*", hostlen - 1); | ||
470 | break; | ||
471 | }; | ||
472 | |||
473 | #if HOSTTABLE | ||
474 | if ((rval = hosttable_lookup_name(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, host, hostlen, flags)) < 0) | ||
475 | goto ret; | ||
476 | |||
477 | if (!rval) | ||
478 | break; | ||
479 | #endif /* HOSTTABLE */ | ||
480 | #if RESOLVER | ||
481 | { | ||
482 | char ptrname[30]; | ||
483 | u_int8_t *p = (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr; | ||
484 | sprintf(ptrname, "%d.%d.%d.%d.in-addr.arpa.", p[3], p[2], p[1], p[0]); | ||
485 | |||
486 | if ((rval = resolver_lookup_name(ptrname, host, hostlen, flags)) < 0) | ||
487 | goto ret; | ||
488 | |||
489 | if (!rval) | ||
490 | break; | ||
491 | }; | ||
492 | #endif /* RESOLVER */ | ||
493 | |||
494 | inet_noname: | ||
495 | if (flags & NI_NAMEREQD) | ||
496 | RETURN_ERROR(EAI_NONAME); | ||
497 | |||
498 | if (!inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, host, hostlen)) | ||
499 | RETURN_ERROR(EAI_NONAME); | ||
500 | |||
501 | break; | ||
502 | #if LOCAL | ||
503 | case AF_LOCAL: | ||
504 | if (!(flags & NI_NUMERICHOST)) { | ||
505 | struct utsname utsname; | ||
506 | |||
507 | if (!uname(&utsname)) { | ||
508 | strncpy(host, utsname.nodename, hostlen - 1); | ||
509 | break; | ||
510 | }; | ||
511 | }; | ||
512 | |||
513 | if (flags & NI_NAMEREQD) | ||
514 | RETURN_ERROR(EAI_NONAME); | ||
515 | |||
516 | strncpy(host, "localhost", hostlen - 1); | ||
517 | break; | ||
518 | #endif /* LOCAL */ | ||
519 | default: | ||
520 | RETURN_ERROR(EAI_FAMILY); | ||
521 | }; | ||
522 | |||
523 | if (serv && (servlen > 0)) | ||
524 | switch(sa->sa_family) { | ||
525 | case AF_INET: | ||
526 | #if INET6 | ||
527 | case AF_INET6: | ||
528 | #endif /* INET6 */ | ||
529 | if (!(flags & NI_NUMERICSERV)) { | ||
530 | struct servent *s; | ||
531 | if (s = getservbyport(((struct sockaddr_in *)sa)->sin_port, (flags & NI_DGRAM) ? "udp" : "tcp")) { | ||
532 | strncpy(serv, s->s_name, servlen - 1); | ||
533 | break; | ||
534 | }; | ||
535 | if (!((struct sockaddr_in *)sa)->sin_port) { | ||
536 | strncpy(serv, "*", servlen - 1); | ||
537 | break; | ||
538 | }; | ||
539 | }; | ||
540 | snprintf(serv, servlen - 1, "%d", ntohs(((struct sockaddr_in *)sa)->sin_port)); | ||
541 | break; | ||
542 | #if LOCAL | ||
543 | case AF_LOCAL: | ||
544 | strncpy(serv, ((struct sockaddr_un *)sa)->sun_path, servlen - 1); | ||
545 | break; | ||
546 | #endif /* LOCAL */ | ||
547 | }; | ||
548 | |||
549 | if (host && (hostlen > 0)) | ||
550 | host[hostlen-1] = 0; | ||
551 | if (serv && (servlen > 0)) | ||
552 | serv[servlen-1] = 0; | ||
553 | rval = 0; | ||
554 | |||
555 | ret: | ||
556 | if (rval == 1) | ||
557 | rval = EAI_FAIL; | ||
558 | |||
559 | errno = serrno; | ||
560 | |||
561 | return rval; | ||
562 | }; | ||