1 /***********************************************************************/
5 /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
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. */
12 /***********************************************************************/
14 /* $Id: gethost.c 7619 2006-09-20 11:14:37Z doligez $ */
22 #include "unixsupport.h"
26 #include "socketaddr.h"
28 #include <sys/types.h>
32 #define NETDB_BUFFER_SIZE 10000
35 #define GETHOSTBYADDR_IS_REENTRANT 1
36 #define GETHOSTBYNAME_IS_REENTRANT 1
39 static int entry_h_length;
41 extern int socket_domain_table[];
43 static value alloc_one_addr(char const *a)
47 struct in6_addr addr6;
48 if (entry_h_length == 16) {
49 memmove(&addr6, a, 16);
50 return alloc_inet6_addr(&addr6);
53 memmove (&addr, a, 4);
54 return alloc_inet_addr(&addr);
57 static value alloc_host_entry(struct hostent *entry)
60 value name = Val_unit, aliases = Val_unit;
61 value addr_list = Val_unit, adr = Val_unit;
63 Begin_roots4 (name, aliases, addr_list, adr);
64 name = copy_string((char *)(entry->h_name));
65 /* PR#4043: protect against buggy implementations of gethostbyname()
66 that return a NULL pointer in h_aliases */
68 aliases = copy_string_array((const char**)entry->h_aliases);
71 entry_h_length = entry->h_length;
73 addr_list = alloc_array(alloc_one_addr, (const char**)entry->h_addr_list);
75 adr = alloc_one_addr(entry->h_addr);
76 addr_list = alloc_small(1, 0);
77 Field(addr_list, 0) = adr;
79 res = alloc_small(4, 0);
81 Field(res, 1) = aliases;
82 switch (entry->h_addrtype) {
83 case PF_UNIX: Field(res, 2) = Val_int(0); break;
84 case PF_INET: Field(res, 2) = Val_int(1); break;
85 default: /*PF_INET6 */ Field(res, 2) = Val_int(2); break;
87 Field(res, 3) = addr_list;
92 CAMLprim value unix_gethostbyaddr(value a)
94 struct in_addr adr = GET_INET_ADDR(a);
96 #if HAS_GETHOSTBYADDR_R == 7
98 char buffer[NETDB_BUFFER_SIZE];
100 enter_blocking_section();
101 hp = gethostbyaddr_r((char *) &adr, 4, AF_INET,
102 &h, buffer, sizeof(buffer), &h_errnop);
103 leave_blocking_section();
104 #elif HAS_GETHOSTBYADDR_R == 8
106 char buffer[NETDB_BUFFER_SIZE];
108 enter_blocking_section();
109 rc = gethostbyaddr_r((char *) &adr, 4, AF_INET,
110 &h, buffer, sizeof(buffer), &hp, &h_errnop);
111 leave_blocking_section();
112 if (rc != 0) hp = NULL;
114 #ifdef GETHOSTBYADDR_IS_REENTRANT
115 enter_blocking_section();
117 hp = gethostbyaddr((char *) &adr, 4, AF_INET);
118 #ifdef GETHOSTBYADDR_IS_REENTRANT
119 leave_blocking_section();
122 if (hp == (struct hostent *) NULL) raise_not_found();
123 return alloc_host_entry(hp);
126 CAMLprim value unix_gethostbyname(value name)
131 #if HAS_GETHOSTBYNAME_R || GETHOSTBYNAME_IS_REENTRANT
132 hostname = stat_alloc(string_length(name) + 1);
133 strcpy(hostname, String_val(name));
135 hostname = String_val(name);
138 #if HAS_GETHOSTBYNAME_R == 5
141 char buffer[NETDB_BUFFER_SIZE];
143 enter_blocking_section();
144 hp = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &h_errno);
145 leave_blocking_section();
147 #elif HAS_GETHOSTBYNAME_R == 6
150 char buffer[NETDB_BUFFER_SIZE];
152 enter_blocking_section();
153 rc = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &hp, &h_errno);
154 leave_blocking_section();
155 if (rc != 0) hp = NULL;
158 #ifdef GETHOSTBYNAME_IS_REENTRANT
159 enter_blocking_section();
161 hp = gethostbyname(hostname);
162 #ifdef GETHOSTBYNAME_IS_REENTRANT
163 leave_blocking_section();
167 #if HAS_GETHOSTBYNAME_R || GETHOSTBYNAME_IS_REENTRANT
171 if (hp == (struct hostent *) NULL) raise_not_found();
172 return alloc_host_entry(hp);
177 CAMLprim value unix_gethostbyaddr(value name)
178 { invalid_argument("gethostbyaddr not implemented"); }
180 CAMLprim value unix_gethostbyname(value name)
181 { invalid_argument("gethostbyname not implemented"); }