1: /*
2: ================================================================================
3: RPL/2 (R) version 4.0.18
4: Copyright (C) 1989-2010 Dr. BERTRAND Joël
5:
6: This file is part of RPL/2.
7:
8: RPL/2 is free software; you can redistribute it and/or modify it
9: under the terms of the CeCILL V2 License as published by the french
10: CEA, CNRS and INRIA.
11:
12: RPL/2 is distributed in the hope that it will be useful, but WITHOUT
13: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14: FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License
15: for more details.
16:
17: You should have received a copy of the CeCILL License
18: along with RPL/2. If not, write to info@cecill.info.
19: ================================================================================
20: */
21:
22: #ifdef OS2
23:
24: /*
25: * Copyright (c) 2001, 02 Motoyuki Kasahara
26: *
27: * Redistribution and use in source and binary forms, with or without
28: * modification, are permitted provided that the following conditions
29: * are met:
30: * 1. Redistributions of source code must retain the above copyright
31: * notice, this list of conditions and the following disclaimer.
32: * 2. Redistributions in binary form must reproduce the above copyright
33: * notice, this list of conditions and the following disclaimer in the
34: * documentation and/or other materials provided with the distribution.
35: * 3. Neither the name of the project nor the names of its contributors
36: * may be used to endorse or promote products derived from this software
37: * without specific prior written permission.
38: *
39: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
40: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
43: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
45: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
48: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49: * SUCH DAMAGE.
50: */
51:
52: /*
53: * This program provides getaddrinfo() and getnameinfo() described in
54: * RFC2133, 2553 and 3493. These functions are mainly used for IPv6
55: * application to resolve hostname or address.
56: *
57: * This program is designed to be working on traditional IPv4 systems
58: * which don't have those functions. Therefore, this implementation
59: * supports IPv4 only.
60: *
61: * This program is useful for application which should support both IPv6
62: * and traditional IPv4 systems. Use genuine getaddrinfo() and getnameinfo()
63: * provided by system if the system supports IPv6. Otherwise, use this
64: * implementation.
65: *
66: * This program is intended to be used in combination with GNU Autoconf.
67: *
68: * This program also provides freeaddrinfo() and gai_strerror().
69: *
70: * To use this program in your application, insert the following lines to
71: * C source files after including `sys/types.h', `sys/socket.h' and
72: * `netdb.h'. `getaddrinfo.h' defines `struct addrinfo' and AI_, NI_,
73: * EAI_ macros.
74: *
75: * #ifndef HAVE_GETADDRINFO
76: * #include "getaddrinfo.h"
77: * #endif
78: *
79: * Restriction:
80: * getaddrinfo() and getnameinfo() of this program are NOT thread
81: * safe, unless the cpp macro ENABLE_PTHREAD is defined.
82: */
83:
84: /*
85: * Add the following code to your configure.ac (or configure.in).
86: * AC_C_CONST
87: * AC_HEADER_STDC
88: * AC_CHECK_HEADERS(string.h memory.h stdlib.h)
89: * AC_CHECK_FUNCS(memcpy)
90: * AC_REPLACE_FUNCS(memset)
91: * AC_TYPE_SOCKLEN_T
92: * AC_TYPE_IN_PORT_T
93: * AC_DECL_H_ERRNO
94: *
95: * AC_CHECK_FUNCS(getaddrinfo getnameinfo)
96: * if test "$ac_cv_func_getaddrinfo$ac_cv_func_getnameinfo" != yesyes ; then
97: * LIBOBJS="$LIBOBJS getaddrinfo.$ac_objext"
98: * fi
99: */
100:
101: #ifdef HAVE_CONFIG_H
102: #include "config.h"
103: #endif
104:
105: #ifdef __OS2__
106: #define ENABLE_PTHREAD
107: #endif
108:
109: #include <sys/types.h>
110: #include <stdio.h>
111:
112: #ifdef WIN32
113: #include <time.h>
114: #include <winsock2.h>
115: #ifdef DO_IPV6
116: #include <ws2tcpip.h>
117: #endif /* DO_IPV6 */
118: #include <windows.h>
119: #else
120: #include <sys/socket.h>
121: #endif
122:
123:
124: #include <netinet/in.h>
125: #include <arpa/inet.h>
126: #include <netdb.h>
127:
128: #if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
129: #include <string.h>
130: #if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
131: #include <memory.h>
132: #endif /* not STDC_HEADERS and HAVE_MEMORY_H */
133: #else /* not STDC_HEADERS and not HAVE_STRING_H */
134: #include <strings.h>
135: #endif /* not STDC_HEADERS and not HAVE_STRING_H */
136:
137: #ifdef HAVE_STDLIB_H
138: #include <stdlib.h>
139: #endif
140:
141: #ifdef ENABLE_PTHREAD
142: #include <pthread.h>
143: #endif
144:
145: #ifdef ENABLE_NLS
146: #include <libintl.h>
147: #endif
148:
149: #ifndef HAVE_MEMCPY
150: #define memcpy(d, s, n) bcopy((s), (d), (n))
151: #ifdef __STDC__
152: void *memchr(const void *, int, size_t);
153: int memcmp(const void *, const void *, size_t);
154: void *memmove(void *, const void *, size_t);
155: void *memset(void *, int, size_t);
156: #else /* not __STDC__ */
157: char *memchr();
158: int memcmp();
159: char *memmove();
160: char *memset();
161: #endif /* not __STDC__ */
162: #endif /* not HAVE_MEMCPY */
163:
164: #ifndef H_ERRNO_DECLARED
165: extern int h_errno;
166: #endif
167:
168: #include "getaddrinfo.h"
169:
170: #ifdef ENABLE_NLS
171: #define _(string) gettext(string)
172: #ifdef gettext_noop
173: #define N_(string) gettext_noop(string)
174: #else
175: #define N_(string) (string)
176: #endif
177: #else
178: #define gettext(string) (string)
179: #define _(string) (string)
180: #define N_(string) (string)
181: #endif
182:
183: /*
184: * Error messages for gai_strerror().
185: */
186: static char *eai_errlist[] = {
187: N_("Success"),
188:
189: /* EAI_ADDRFAMILY */
190: N_("Address family for hostname not supported"),
191:
192: /* EAI_AGAIN */
193: N_("Temporary failure in name resolution"),
194:
195: /* EAI_BADFLAGS */
196: N_("Invalid value for ai_flags"),
197:
198: /* EAI_FAIL */
199: N_("Non-recoverable failure in name resolution"),
200:
201: /* EAI_FAMILY */
202: N_("ai_family not supported"),
203:
204: /* EAI_MEMORY */
205: N_("Memory allocation failure"),
206:
207: /* EAI_NONAME */
208: N_("hostname nor servname provided, or not known"),
209:
210: /* EAI_OVERFLOW */
211: N_("An argument buffer overflowed"),
212:
213: /* EAI_SERVICE */
214: N_("servname not supported for ai_socktype"),
215:
216: /* EAI_SOCKTYPE */
217: N_("ai_socktype not supported"),
218:
219: /* EAI_SYSTEM */
220: N_("System error returned in errno")
221: };
222:
223: /*
224: * Default hints for getaddrinfo().
225: */
226: static struct addrinfo default_hints = {
227: 0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL
228: };
229:
230: /*
231: * Mutex.
232: */
233: #ifdef ENABLE_PTHREAD
234: static pthread_mutex_t gai_mutex = PTHREAD_MUTEX_INITIALIZER;
235: #endif
236:
237: /*
238: * Declaration of static functions.
239: */
240: #ifdef __STDC__
241: static int is_integer(const char *);
242: static int is_address(const char *);
243: static int itoa_length(int);
244: #else
245: static int is_integer();
246: static int is_address();
247: static int itoa_length();
248: #endif
249:
250: /*
251: * gai_strerror().
252: */
253: const char *
254: gai_strerror(int ecode)
255: {
256: if (ecode < 0 || ecode > EAI_SYSTEM)
257: return _("Unknown error");
258:
259: return gettext(eai_errlist[ecode]);
260: }
261:
262: /*
263: * freeaddrinfo().
264: */
265: void
266: freeaddrinfo(struct addrinfo *ai)
267: {
268: struct addrinfo *next_ai;
269:
270: while (ai != NULL) {
271: if (ai->ai_canonname != NULL)
272: free(ai->ai_canonname);
273: if (ai->ai_addr != NULL)
274: free(ai->ai_addr);
275: next_ai = ai->ai_next;
276: free(ai);
277: ai = next_ai;
278: }
279: }
280:
281: /*
282: * Return 1 if the string `s' represents an integer.
283: */
284: static int
285: is_integer(const char *s)
286: {
287: if (*s == '-' || *s == '+')
288: s++;
289: if (*s < '0' || '9' < *s)
290: return 0;
291:
292: s++;
293: while ('0' <= *s && *s <= '9')
294: s++;
295:
296: return (*s == '\0');
297: }
298:
299: /*
300: * Return 1 if the string `s' represents an IPv4 address.
301: * Unlike inet_addr(), it doesn't permit malformed nortation such
302: * as "192.168".
303: */
304: static int
305: is_address(const char *s)
306: {
307: static const char delimiters[] = {'.', '.', '.', '\0'};
308: int i, j;
309: int octet;
310:
311: for (i = 0; i < 4; i++) {
312: if (*s == '0' && *(s + 1) != delimiters[i])
313: return 0;
314: for (j = 0, octet = 0; '0' <= *s && *s <= '9' && j < 3; s++, j++)
315: octet = octet * 10 + (*s - '0');
316: if (j == 0 || octet > 255 || *s != delimiters[i])
317: return 0;
318: s++;
319: }
320:
321: return 1;
322: }
323:
324: /*
325: * Calcurate length of the string `s', where `s' is set by
326: * sprintf(s, "%d", n).
327: */
328: static int
329: itoa_length(int n)
330: {
331: int result = 1;
332:
333: if (n < 0) {
334: n = -n;
335: result++;
336: }
337:
338: while (n >= 10) {
339: result++;
340: n /= 10;
341: }
342:
343: return result;
344: }
345:
346: /*
347: * getaddrinfo().
348: */
349: int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints,
350: struct addrinfo **res)
351: {
352: struct addrinfo *head_res = NULL;
353: struct addrinfo *tail_res = NULL;
354: struct addrinfo *new_res;
355: struct sockaddr_in *sa_in;
356: struct in_addr **addr_list;
357: struct in_addr *addr_list_buf[2];
358: struct in_addr addr_buf;
359: struct in_addr **ap;
360: struct servent *servent;
361: struct hostent *hostent;
362: const char *canonname = NULL;
363: in_port_t port;
364: int saved_h_errno;
365: int result = 0;
366:
367: #ifdef ENABLE_PTHREAD
368: pthread_mutex_lock(&gai_mutex);
369: #endif
370:
371: saved_h_errno = h_errno;
372:
373: if (nodename == NULL && servname == NULL) {
374: result = EAI_NONAME;
375: goto end;
376: }
377:
378: if (hints != NULL) {
379: if (hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC) {
380: result = EAI_FAMILY;
381: goto end;
382: }
383: if (hints->ai_socktype != SOCK_DGRAM
384: && hints->ai_socktype != SOCK_STREAM
385: && hints->ai_socktype != 0) {
386: result = EAI_SOCKTYPE;
387: goto end;
388: }
389: } else {
390: hints = &default_hints;
391: }
392:
393: if (servname != NULL) {
394: if (is_integer(servname))
395: port = htons(atoi(servname));
396: else {
397: if (hints->ai_flags & AI_NUMERICSERV) {
398: result = EAI_NONAME;
399: goto end;
400: }
401:
402: if (hints->ai_socktype == SOCK_DGRAM)
403: servent = getservbyname(servname, "udp");
404: else if (hints->ai_socktype == SOCK_STREAM)
405: servent = getservbyname(servname, "tcp");
406: else if (hints->ai_socktype == 0)
407: servent = getservbyname(servname, "tcp");
408: else {
409: result = EAI_SOCKTYPE;
410: goto end;
411: }
412:
413: if (servent == NULL) {
414: result = EAI_SERVICE;
415: goto end;
416: }
417: port = servent->s_port;
418: }
419: } else {
420: port = htons(0);
421: }
422:
423: if (nodename != NULL) {
424: if (is_address(nodename)) {
425: addr_buf.s_addr = inet_addr(nodename);
426: addr_list_buf[0] = &addr_buf;
427: addr_list_buf[1] = NULL;
428: addr_list = addr_list_buf;
429:
430: if (hints->ai_flags & AI_CANONNAME
431: && !(hints->ai_flags & AI_NUMERICHOST)) {
432: hostent = gethostbyaddr((char *)&addr_buf,
433: sizeof(struct in_addr), AF_INET);
434: if (hostent != NULL)
435: canonname = hostent->h_name;
436: else
437: canonname = nodename;
438: }
439: } else {
440: if (hints->ai_flags & AI_NUMERICHOST) {
441: result = EAI_NONAME;
442: goto end;
443: }
444:
445: hostent = gethostbyname(nodename);
446: if (hostent == NULL) {
447: switch (h_errno) {
448: case HOST_NOT_FOUND:
449: case NO_DATA:
450: result = EAI_NONAME;
451: goto end;
452: case TRY_AGAIN:
453: result = EAI_AGAIN;
454: goto end;
455: default:
456: result = EAI_FAIL;
457: goto end;
458: }
459: }
460: addr_list = (struct in_addr **)hostent->h_addr_list;
461:
462: if (hints->ai_flags & AI_CANONNAME)
463: canonname = hostent->h_name;
464: }
465: } else {
466: if (hints->ai_flags & AI_PASSIVE)
467: addr_buf.s_addr = htonl(INADDR_ANY);
468: else
469: addr_buf.s_addr = htonl(0x7F000001);
470: addr_list_buf[0] = &addr_buf;
471: addr_list_buf[1] = NULL;
472: addr_list = addr_list_buf;
473: }
474:
475: for (ap = addr_list; *ap != NULL; ap++) {
476: new_res = (struct addrinfo *)malloc(sizeof(struct addrinfo));
477: if (new_res == NULL) {
478: if (head_res != NULL)
479: freeaddrinfo(head_res);
480: result = EAI_MEMORY;
481: goto end;
482: }
483:
484: new_res->ai_family = PF_INET;
485: new_res->ai_socktype = hints->ai_socktype;
486: new_res->ai_protocol = hints->ai_protocol;
487: new_res->ai_addr = NULL;
488: new_res->ai_addrlen = sizeof(struct sockaddr_in);
489: new_res->ai_canonname = NULL;
490: new_res->ai_next = NULL;
491:
492: new_res->ai_addr = (struct sockaddr *)
493: malloc(sizeof(struct sockaddr_in));
494: if (new_res->ai_addr == NULL) {
495: free(new_res);
496: if (head_res != NULL)
497: freeaddrinfo(head_res);
498: result = EAI_MEMORY;
499: goto end;
500: }
501:
502: sa_in = (struct sockaddr_in *)new_res->ai_addr;
503: memset(sa_in, 0, sizeof(struct sockaddr_in));
504: sa_in->sin_family = PF_INET;
505: sa_in->sin_port = port;
506: memcpy(&sa_in->sin_addr, *ap, sizeof(struct in_addr));
507:
508: if (head_res == NULL)
509: head_res = new_res;
510: else
511: tail_res->ai_next = new_res;
512: tail_res = new_res;
513: }
514:
515: if (canonname != NULL && head_res != NULL) {
516: head_res->ai_canonname = (char *)malloc(strlen(canonname) + 1);
517: if (head_res->ai_canonname != NULL)
518: strcpy(head_res->ai_canonname, canonname);
519: }
520:
521: *res = head_res;
522:
523: end:
524: h_errno = saved_h_errno;
525: #ifdef ENABLE_PTHREAD
526: pthread_mutex_unlock(&gai_mutex);
527: #endif
528: return result;
529: }
530:
531: /*
532: * getnameinfo().
533: */
534: int
535: getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *serv, socklen_t servlen,int flags)
536: {
537: const struct sockaddr_in *sa_in = (const struct sockaddr_in *)sa;
538: struct hostent *hostent;
539: struct servent *servent;
540: char *ntoa_address;
541: int saved_h_errno;
542: int result = 0;
543:
544: #ifdef ENABLE_PTHREAD
545: pthread_mutex_lock(&gai_mutex);
546: #endif
547:
548: saved_h_errno = h_errno;
549:
550: if (sa_in->sin_family != PF_INET) {
551: result = EAI_FAMILY;
552: goto end;
553: } else if (node == NULL && serv == NULL) {
554: result = EAI_NONAME;
555: goto end;
556: }
557:
558: if (serv != NULL && servlen > 0) {
559: if (flags & NI_NUMERICSERV)
560: servent = NULL;
561: else if (flags & NI_DGRAM)
562: servent = getservbyport(sa_in->sin_port, "udp");
563: else
564: servent = getservbyport(sa_in->sin_port, "tcp");
565:
566: if (servent != NULL) {
567: if (servlen <= strlen(servent->s_name)) {
568: result = EAI_OVERFLOW;
569: goto end;
570: }
571: strcpy(serv, servent->s_name);
572: } else {
573: if (servlen <= itoa_length(ntohs(sa_in->sin_port))) {
574: result = EAI_OVERFLOW;
575: goto end;
576: }
577: sprintf(serv, "%d", ntohs(sa_in->sin_port));
578: }
579: }
580:
581: if (node != NULL && nodelen > 0) {
582: if (flags & NI_NUMERICHOST)
583: hostent = NULL;
584: else {
585: hostent = gethostbyaddr((char *)&sa_in->sin_addr,
586: sizeof(struct in_addr), AF_INET);
587: }
588: if (hostent != NULL) {
589: if (nodelen <= strlen(hostent->h_name)) {
590: result = EAI_OVERFLOW;
591: goto end;
592: }
593: strcpy(node, hostent->h_name);
594: } else {
595: if (flags & NI_NAMEREQD) {
596: result = EAI_NONAME;
597: goto end;
598: }
599: ntoa_address = inet_ntoa(sa_in->sin_addr);
600: if (nodelen <= strlen(ntoa_address)) {
601: result = EAI_OVERFLOW;
602: goto end;
603: }
604: strcpy(node, ntoa_address);
605: }
606:
607: }
608:
609: end:
610: h_errno = saved_h_errno;
611: #ifdef ENABLE_PTHREAD
612: pthread_mutex_unlock(&gai_mutex);
613: #endif
614: return result;
615: }
616:
617: #endif
618:
619: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>