File:
[local] /
rpl /
src /
getaddrinfo.c
Revision
1.12:
download - view:
text,
annotated -
select for diffs -
revision graph
Tue Jun 21 15:26:29 2011 UTC (13 years, 10 months ago) by
bertrand
Branches:
MAIN
CVS tags:
HEAD
Correction d'une réinitialisation sauvage de la pile des variables par niveau
dans la copie de la structure de description du processus. Cela corrige
la fonction SPAWN qui échouait sur un segmentation fault car la pile des
variables par niveau était vide alors même que l'arbre des variables contenait
bien les variables. Passage à la prerelease 2.
1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.0.prerelease.2
4: Copyright (C) 1989-2011 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>