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