PageRenderTime 33ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/otherlibs/unix/gethost.c

http://github.com/thelema/ocaml-community
C | 181 lines | 147 code | 20 blank | 14 comment | 18 complexity | eeee531ad25c983f455e734f3f19a6fa MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0
  1. /***********************************************************************/
  2. /* */
  3. /* OCaml */
  4. /* */
  5. /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
  6. /* */
  7. /* Copyright 1996 Institut National de Recherche en Informatique et */
  8. /* en Automatique. All rights reserved. This file is distributed */
  9. /* under the terms of the GNU Library General Public License, with */
  10. /* the special exception on linking described in file ../../LICENSE. */
  11. /* */
  12. /***********************************************************************/
  13. #include <string.h>
  14. #include <mlvalues.h>
  15. #include <alloc.h>
  16. #include <fail.h>
  17. #include <memory.h>
  18. #include <signals.h>
  19. #include "unixsupport.h"
  20. #ifdef HAS_SOCKETS
  21. #include "socketaddr.h"
  22. #ifndef _WIN32
  23. #include <sys/types.h>
  24. #include <netdb.h>
  25. #endif
  26. #define NETDB_BUFFER_SIZE 10000
  27. #ifdef _WIN32
  28. #define GETHOSTBYADDR_IS_REENTRANT 1
  29. #define GETHOSTBYNAME_IS_REENTRANT 1
  30. #endif
  31. static int entry_h_length;
  32. extern int socket_domain_table[];
  33. static value alloc_one_addr(char const *a)
  34. {
  35. struct in_addr addr;
  36. #ifdef HAS_IPV6
  37. struct in6_addr addr6;
  38. if (entry_h_length == 16) {
  39. memmove(&addr6, a, 16);
  40. return alloc_inet6_addr(&addr6);
  41. }
  42. #endif
  43. memmove (&addr, a, 4);
  44. return alloc_inet_addr(&addr);
  45. }
  46. static value alloc_host_entry(struct hostent *entry)
  47. {
  48. value res;
  49. value name = Val_unit, aliases = Val_unit;
  50. value addr_list = Val_unit, adr = Val_unit;
  51. Begin_roots4 (name, aliases, addr_list, adr);
  52. name = copy_string((char *)(entry->h_name));
  53. /* PR#4043: protect against buggy implementations of gethostbyname()
  54. that return a NULL pointer in h_aliases */
  55. if (entry->h_aliases)
  56. aliases = copy_string_array((const char**)entry->h_aliases);
  57. else
  58. aliases = Atom(0);
  59. entry_h_length = entry->h_length;
  60. #ifdef h_addr
  61. addr_list = alloc_array(alloc_one_addr, (const char**)entry->h_addr_list);
  62. #else
  63. adr = alloc_one_addr(entry->h_addr);
  64. addr_list = alloc_small(1, 0);
  65. Field(addr_list, 0) = adr;
  66. #endif
  67. res = alloc_small(4, 0);
  68. Field(res, 0) = name;
  69. Field(res, 1) = aliases;
  70. switch (entry->h_addrtype) {
  71. case PF_UNIX: Field(res, 2) = Val_int(0); break;
  72. case PF_INET: Field(res, 2) = Val_int(1); break;
  73. default: /*PF_INET6 */ Field(res, 2) = Val_int(2); break;
  74. }
  75. Field(res, 3) = addr_list;
  76. End_roots();
  77. return res;
  78. }
  79. CAMLprim value unix_gethostbyaddr(value a)
  80. {
  81. struct in_addr adr = GET_INET_ADDR(a);
  82. struct hostent * hp;
  83. #if HAS_GETHOSTBYADDR_R == 7
  84. struct hostent h;
  85. char buffer[NETDB_BUFFER_SIZE];
  86. int h_errnop;
  87. enter_blocking_section();
  88. hp = gethostbyaddr_r((char *) &adr, 4, AF_INET,
  89. &h, buffer, sizeof(buffer), &h_errnop);
  90. leave_blocking_section();
  91. #elif HAS_GETHOSTBYADDR_R == 8
  92. struct hostent h;
  93. char buffer[NETDB_BUFFER_SIZE];
  94. int h_errnop, rc;
  95. enter_blocking_section();
  96. rc = gethostbyaddr_r((char *) &adr, 4, AF_INET,
  97. &h, buffer, sizeof(buffer), &hp, &h_errnop);
  98. leave_blocking_section();
  99. if (rc != 0) hp = NULL;
  100. #else
  101. #ifdef GETHOSTBYADDR_IS_REENTRANT
  102. enter_blocking_section();
  103. #endif
  104. hp = gethostbyaddr((char *) &adr, 4, AF_INET);
  105. #ifdef GETHOSTBYADDR_IS_REENTRANT
  106. leave_blocking_section();
  107. #endif
  108. #endif
  109. if (hp == (struct hostent *) NULL) raise_not_found();
  110. return alloc_host_entry(hp);
  111. }
  112. CAMLprim value unix_gethostbyname(value name)
  113. {
  114. struct hostent * hp;
  115. char * hostname;
  116. #if HAS_GETHOSTBYNAME_R || GETHOSTBYNAME_IS_REENTRANT
  117. hostname = stat_alloc(string_length(name) + 1);
  118. strcpy(hostname, String_val(name));
  119. #else
  120. hostname = String_val(name);
  121. #endif
  122. #if HAS_GETHOSTBYNAME_R == 5
  123. {
  124. struct hostent h;
  125. char buffer[NETDB_BUFFER_SIZE];
  126. int h_errno;
  127. enter_blocking_section();
  128. hp = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &h_errno);
  129. leave_blocking_section();
  130. }
  131. #elif HAS_GETHOSTBYNAME_R == 6
  132. {
  133. struct hostent h;
  134. char buffer[NETDB_BUFFER_SIZE];
  135. int h_errno, rc;
  136. enter_blocking_section();
  137. rc = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &hp, &h_errno);
  138. leave_blocking_section();
  139. if (rc != 0) hp = NULL;
  140. }
  141. #else
  142. #ifdef GETHOSTBYNAME_IS_REENTRANT
  143. enter_blocking_section();
  144. #endif
  145. hp = gethostbyname(hostname);
  146. #ifdef GETHOSTBYNAME_IS_REENTRANT
  147. leave_blocking_section();
  148. #endif
  149. #endif
  150. #if HAS_GETHOSTBYNAME_R || GETHOSTBYNAME_IS_REENTRANT
  151. stat_free(hostname);
  152. #endif
  153. if (hp == (struct hostent *) NULL) raise_not_found();
  154. return alloc_host_entry(hp);
  155. }
  156. #else
  157. CAMLprim value unix_gethostbyaddr(value name)
  158. { invalid_argument("gethostbyaddr not implemented"); }
  159. CAMLprim value unix_gethostbyname(value name)
  160. { invalid_argument("gethostbyname not implemented"); }
  161. #endif