getnameinfo.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  3. * 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. Neither the name of the project nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /*
  30. * Issues to be discussed:
  31. * - Thread safe-ness must be checked
  32. * - Return values. There seems to be no standard for return value (RFC2133)
  33. * but INRIA implementation returns EAI_xxx defined for getaddrinfo().
  34. */
  35. #if 0
  36. #include <sys/types.h>
  37. #include <sys/socket.h>
  38. #include <netinet/in.h>
  39. #include <arpa/inet.h>
  40. #include <arpa/nameser.h>
  41. #include <netdb.h>
  42. #include <resolv.h>
  43. #include <string.h>
  44. #include <stddef.h>
  45. #include "addrinfo.h"
  46. #endif
  47. #ifdef HAVE_NETDB_H
  48. #define HAVE_GETNAMEINFO 1
  49. #define SUCCESS 0
  50. #define YES 1
  51. #define NO 0
  52. static struct gni_afd {
  53. int a_af;
  54. int a_addrlen;
  55. int a_socklen;
  56. int a_off;
  57. } gni_afdl [] = {
  58. #ifdef ENABLE_IPV6
  59. {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
  60. offsetof(struct sockaddr_in6, sin6_addr)},
  61. #endif
  62. {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
  63. offsetof(struct sockaddr_in, sin_addr)},
  64. {0, 0, 0},
  65. };
  66. struct gni_sockinet {
  67. u_char si_len;
  68. u_char si_family;
  69. u_short si_port;
  70. };
  71. #define ENI_NOSOCKET 0
  72. #define ENI_NOSERVNAME 1
  73. #define ENI_NOHOSTNAME 2
  74. #define ENI_MEMORY 3
  75. #define ENI_SYSTEM 4
  76. #define ENI_FAMILY 5
  77. #define ENI_SALEN 6
  78. /* forward declaration to make gcc happy */
  79. int getnameinfo(const struct sockaddr *, size_t, char *, size_t,
  80. char *, size_t, int);
  81. int
  82. getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
  83. const struct sockaddr *sa;
  84. size_t salen;
  85. char *host;
  86. size_t hostlen;
  87. char *serv;
  88. size_t servlen;
  89. int flags;
  90. {
  91. struct gni_afd *gni_afd;
  92. struct servent *sp;
  93. struct hostent *hp;
  94. u_short port;
  95. int family, len, i;
  96. char *addr, *p;
  97. u_long v4a;
  98. #ifdef ENABLE_IPV6
  99. u_char pfx;
  100. int h_error;
  101. #endif
  102. char numserv[512];
  103. char numaddr[512];
  104. if (sa == NULL)
  105. return ENI_NOSOCKET;
  106. #ifdef HAVE_SOCKADDR_SA_LEN
  107. len = sa->sa_len;
  108. if (len != salen) return ENI_SALEN;
  109. #else
  110. len = salen;
  111. #endif
  112. family = sa->sa_family;
  113. for (i = 0; gni_afdl[i].a_af; i++)
  114. if (gni_afdl[i].a_af == family) {
  115. gni_afd = &gni_afdl[i];
  116. goto found;
  117. }
  118. return ENI_FAMILY;
  119. found:
  120. if (len != gni_afd->a_socklen) return ENI_SALEN;
  121. port = ((struct gni_sockinet *)sa)->si_port; /* network byte order */
  122. addr = (char *)sa + gni_afd->a_off;
  123. if (serv == NULL || servlen == 0) {
  124. /* what we should do? */
  125. } else if (flags & NI_NUMERICSERV) {
  126. sprintf(numserv, "%d", ntohs(port));
  127. if (strlen(numserv) > servlen)
  128. return ENI_MEMORY;
  129. strcpy(serv, numserv);
  130. } else {
  131. sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
  132. if (sp) {
  133. if (strlen(sp->s_name) > servlen)
  134. return ENI_MEMORY;
  135. strcpy(serv, sp->s_name);
  136. } else
  137. return ENI_NOSERVNAME;
  138. }
  139. switch (sa->sa_family) {
  140. case AF_INET:
  141. v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
  142. if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
  143. flags |= NI_NUMERICHOST;
  144. v4a >>= IN_CLASSA_NSHIFT;
  145. if (v4a == 0 || v4a == IN_LOOPBACKNET)
  146. flags |= NI_NUMERICHOST;
  147. break;
  148. #ifdef ENABLE_IPV6
  149. case AF_INET6:
  150. pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
  151. if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
  152. flags |= NI_NUMERICHOST;
  153. break;
  154. #endif
  155. }
  156. if (host == NULL || hostlen == 0) {
  157. /* what should we do? */
  158. } else if (flags & NI_NUMERICHOST) {
  159. if (inet_ntop(gni_afd->a_af, addr, numaddr, sizeof(numaddr))
  160. == NULL)
  161. return ENI_SYSTEM;
  162. if (strlen(numaddr) > hostlen)
  163. return ENI_MEMORY;
  164. strcpy(host, numaddr);
  165. } else {
  166. #ifdef ENABLE_IPV6
  167. hp = getipnodebyaddr(addr, gni_afd->a_addrlen, gni_afd->a_af, &h_error);
  168. #else
  169. hp = gethostbyaddr(addr, gni_afd->a_addrlen, gni_afd->a_af);
  170. #endif
  171. if (hp) {
  172. if (flags & NI_NOFQDN) {
  173. p = strchr(hp->h_name, '.');
  174. if (p) *p = '\0';
  175. }
  176. if (strlen(hp->h_name) > hostlen) {
  177. #ifdef ENABLE_IPV6
  178. freehostent(hp);
  179. #endif
  180. return ENI_MEMORY;
  181. }
  182. strcpy(host, hp->h_name);
  183. #ifdef ENABLE_IPV6
  184. freehostent(hp);
  185. #endif
  186. } else {
  187. if (flags & NI_NAMEREQD)
  188. return ENI_NOHOSTNAME;
  189. if (inet_ntop(gni_afd->a_af, addr, numaddr, sizeof(numaddr))
  190. == NULL)
  191. return ENI_NOHOSTNAME;
  192. if (strlen(numaddr) > hostlen)
  193. return ENI_MEMORY;
  194. strcpy(host, numaddr);
  195. }
  196. }
  197. return SUCCESS;
  198. }
  199. #endif // HAVE_NETDB_H