![]() ![]() | ![]() |
Passage de la branche 4.1 en branche stable.
1: /* 2: ================================================================================ 3: RPL/2 (R) version 4.1.0 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