* java/net/natInetAddress.cc (java::net::InetAddress::aton):
[official-gcc.git] / libjava / java / net / natInetAddress.cc
blob627fd3c6eea3e7040b37b13765e8ec43da66c278
1 // natInetAddress.cc
3 /* Copyright (C) 1998, 1999, 2000 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 #include <config.h>
13 #ifdef USE_WINSOCK
15 #include <windows.h>
16 #include <winsock.h>
18 #ifndef MAXHOSTNAMELEN
19 #define MAXHOSTNAMELEN 64
20 #endif /* MAXHOSTNAMELEN */
22 #else
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #include <string.h>
28 #include <errno.h>
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #ifdef HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>
34 #endif
35 #ifdef HAVE_NETINET_IN_H
36 #include <netinet/in.h>
37 #endif
38 #ifdef HAVE_ARPA_INET_H
39 #include <arpa/inet.h>
40 #endif
41 #ifdef HAVE_NETDB_H
42 #include <netdb.h>
43 #endif
45 #endif /* USE_WINSOCK */
47 #include <gcj/cni.h>
48 #include <jvm.h>
49 #include <java/net/InetAddress.h>
50 #include <java/net/UnknownHostException.h>
51 #include <java/lang/SecurityException.h>
53 #if defined(HAVE_UNAME) && ! defined(HAVE_GETHOSTNAME)
54 #include <sys/utsname.h>
55 #endif
57 #ifndef HAVE_GETHOSTNAME_DECL
58 extern "C" int gethostname (char *name, int namelen);
59 #endif
61 #ifdef DISABLE_JAVA_NET
63 jbyteArray
64 java::net::InetAddress::aton (jstring)
66 return NULL;
69 jint
70 java::net::InetAddress::getFamily (jbyteArray bytes)
72 return 0;
75 JArray<java::net::InetAddress*> *
76 java::net::InetAddress::lookup (jstring, java::net::InetAddress *, jboolean)
78 return NULL;
81 jstring
82 java::net::InetAddress::getLocalHostname ()
84 return NULL;
87 #else /* DISABLE_JAVA_NET */
89 jbyteArray
90 java::net::InetAddress::aton (jstring host)
92 char *hostname;
93 char buf[100];
94 int len = JvGetStringUTFLength(host);
95 if (len < 100)
96 hostname = buf;
97 else
98 hostname = (char*) _Jv_AllocBytesChecked (len+1);
99 JvGetStringUTFRegion (host, 0, host->length(), hostname);
100 buf[len] = '\0';
101 char* bytes = NULL;
102 int blen = 0;
103 #ifdef HAVE_INET_ATON
104 struct in_addr laddr;
105 if (inet_aton (hostname, &laddr))
107 bytes = (char*) &laddr;
108 blen = 4;
110 #elif defined(HAVE_INET_ADDR)
111 #if ! HAVE_IN_ADDR_T
112 typedef jint in_addr_t;
113 #endif
114 in_addr_t laddr = inet_addr (hostname);
115 if (laddr != (in_addr_t)(-1))
117 bytes = (char*) &laddr;
118 blen = 4;
120 #endif
121 #if defined (HAVE_INET_PTON) && defined (HAVE_INET6)
122 char inet6_addr[16];
123 if (len == 0 && inet_pton (AF_INET6, hostname, inet6_addr) > 0)
125 bytes = inet6_addr;
126 blen = 16;
128 #endif
129 if (blen == 0)
130 return NULL;
131 jbyteArray result = JvNewByteArray (blen);
132 memcpy (elements (result), bytes, blen);
133 return result;
136 jint
137 java::net::InetAddress::getFamily (jbyteArray bytes)
139 int len = bytes->length;
140 if (len == 4)
141 return AF_INET;
142 #ifdef HAVE_INET6
143 else if (len == 16)
144 return AF_INET6;
145 #endif /* HAVE_INET6 */
146 else
147 JvFail ("unrecognized size");
151 JArray<java::net::InetAddress*> *
152 java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr,
153 jboolean all)
155 struct hostent *hptr = NULL;
156 #if defined (HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR_R)
157 struct hostent hent_r;
158 #if HAVE_STRUCT_HOSTENT_DATA
159 struct hostent_data fixed_buffer, *buffer_r = &fixed_buffer;
160 #else
161 #if defined (__GLIBC__)
162 // FIXME: in glibc, gethostbyname_r returns NETDB_INTERNAL to herr and
163 // ERANGE to errno if the buffer size is too small, rather than what is
164 // expected here. We work around this by setting a bigger buffer size and
165 // hoping that it is big enough.
166 char fixed_buffer[1024];
167 #else
168 char fixed_buffer[200];
169 #endif
170 char *buffer_r = fixed_buffer;
171 int size_r = sizeof (fixed_buffer);
172 #endif
173 #endif
175 if (host != NULL)
177 char *hostname;
178 char buf[100];
179 int len = JvGetStringUTFLength(host);
180 if (len < 100)
181 hostname = buf;
182 else
183 hostname = (char*) _Jv_AllocBytesChecked (len+1);
184 JvGetStringUTFRegion (host, 0, host->length(), hostname);
185 buf[len] = '\0';
186 #ifdef HAVE_GETHOSTBYNAME_R
187 while (true)
189 int ok;
190 #if HAVE_STRUCT_HOSTENT_DATA
191 ok = ! gethostbyname_r (hostname, &hent_r, buffer_r);
192 #else
193 int herr = 0;
194 #ifdef GETHOSTBYNAME_R_RETURNS_INT
195 ok = ! gethostbyname_r (hostname, &hent_r, buffer_r, size_r,
196 &hptr, &herr);
197 #else
198 hptr = gethostbyname_r (hostname, &hent_r, buffer_r, size_r, &herr);
199 ok = hptr != NULL;
200 #endif /* GETHOSTNAME_R_RETURNS_INT */
201 if (! ok && herr == ERANGE)
203 size_r *= 2;
204 buffer_r = (char *) _Jv_AllocBytesChecked (size_r);
206 else
207 #endif /* HAVE_STRUCT_HOSTENT_DATA */
208 break;
210 #else
211 // FIXME: this is insufficient if some other piece of code calls
212 // this gethostbyname.
213 JvSynchronize sync (java::net::InetAddress::localhostAddress);
214 hptr = gethostbyname (hostname);
215 #endif /* HAVE_GETHOSTBYNAME_R */
217 else
219 jbyteArray bytes = iaddr->addr;
220 char *chars = (char*) elements (bytes);
221 int len = bytes->length;
222 int type;
223 char *val;
224 if (len == 4)
226 val = chars;
227 type = iaddr->family = AF_INET;
229 #ifdef HAVE_INET6
230 else if (len == 16)
232 val = (char *) &chars;
233 type = iaddr->family = AF_INET6;
235 #endif /* HAVE_INET6 */
236 else
237 JvFail ("unrecognized size");
239 #ifdef HAVE_GETHOSTBYADDR_R
240 while (true)
242 int ok;
243 #if HAVE_STRUCT_HOSTENT_DATA
244 ok = ! gethostbyaddr_r (val, len, type, &hent_r, buffer_r);
245 #else
246 int herr = 0;
247 #ifdef GETHOSTBYADDR_R_RETURNS_INT
248 ok = ! gethostbyaddr_r (val, len, type, &hent_r,
249 buffer_r, size_r, &hptr, &herr);
250 #else
251 hptr = gethostbyaddr_r (val, len, type, &hent_r,
252 buffer_r, size_r, &herr);
253 ok = hptr != NULL;
254 #endif /* GETHOSTBYADDR_R_RETURNS_INT */
255 if (! ok && herr == ERANGE)
257 size_r *= 2;
258 buffer_r = (char *) _Jv_AllocBytesChecked (size_r);
260 else
261 #endif /* HAVE_STRUCT_HOSTENT_DATA */
262 break;
264 #else /* HAVE_GETHOSTBYADDR_R */
265 // FIXME: this is insufficient if some other piece of code calls
266 // this gethostbyaddr.
267 JvSynchronize sync (java::net::InetAddress::localhostAddress);
268 hptr = gethostbyaddr (val, len, type);
269 #endif /* HAVE_GETHOSTBYADDR_R */
271 if (hptr != NULL)
273 if (!all)
274 host = JvNewStringUTF (hptr->h_name);
275 java::lang::SecurityException *ex = checkConnect (host);
276 if (ex != NULL)
278 if (iaddr == NULL || iaddr->addr == NULL)
279 throw ex;
280 hptr = NULL;
283 if (hptr == NULL)
285 if (iaddr != NULL && iaddr->addr != NULL)
287 iaddr->hostName = iaddr->getHostAddress();
288 return NULL;
290 else
291 throw new java::net::UnknownHostException(host);
293 int count;
294 if (all)
296 char** ptr = hptr->h_addr_list;
297 count = 0;
298 while (*ptr++) count++;
300 else
301 count = 1;
302 JArray<java::net::InetAddress*> *result;
303 java::net::InetAddress** iaddrs;
304 if (all)
306 result = java::net::InetAddress::allocArray (count);
307 iaddrs = elements (result);
309 else
311 result = NULL;
312 iaddrs = &iaddr;
315 for (int i = 0; i < count; i++)
317 if (iaddrs[i] == NULL)
318 iaddrs[i] = new java::net::InetAddress (NULL, NULL);
319 if (iaddrs[i]->hostName == NULL)
320 iaddrs[i]->hostName = host;
321 if (iaddrs[i]->addr == NULL)
323 char *bytes = hptr->h_addr_list[i];
324 iaddrs[i]->addr = JvNewByteArray (hptr->h_length);
325 iaddrs[i]->family = getFamily (iaddrs[i]->addr);
326 memcpy (elements (iaddrs[i]->addr), bytes, hptr->h_length);
329 return result;
332 jstring
333 java::net::InetAddress::getLocalHostname ()
335 char *chars;
336 #ifdef HAVE_GETHOSTNAME
337 char buffer[MAXHOSTNAMELEN];
338 if (gethostname (buffer, MAXHOSTNAMELEN))
339 return NULL;
340 chars = buffer;
341 #elif HAVE_UNAME
342 struct utsname stuff;
343 if (uname (&stuff) != 0)
344 return NULL;
345 chars = stuff.nodename;
346 #else
347 return NULL;
348 #endif
349 // It is admittedly non-optimal to convert the hostname to Unicode
350 // only to convert it back in getByName, but simplicity wins. Note
351 // that unless there is a SecurityManager, we only get called once
352 // anyway, thanks to the InetAddress.localhost cache.
353 return JvNewStringUTF (chars);
356 #endif /* DISABLE_JAVA_NET */