2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / java / net / natInetAddressPosix.cc
blobb97502e19b0002c4934f4483589dbd868d5f0aee
1 /* Copyright (C) 2003 Free Software Foundation
3 This file is part of libgcj.
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
7 details. */
9 #include <config.h>
11 #ifdef HAVE_UNISTD_H
12 #include <unistd.h>
13 #endif
14 #include <string.h>
15 #include <errno.h>
17 #include <sys/param.h>
18 #include <sys/types.h>
19 #ifdef HAVE_SYS_SOCKET_H
20 #include <sys/socket.h>
21 #endif
22 #ifdef HAVE_NETINET_IN_H
23 #include <netinet/in.h>
24 #endif
25 #ifdef HAVE_ARPA_INET_H
26 #include <arpa/inet.h>
27 #endif
28 #ifdef HAVE_NETDB_H
29 #include <netdb.h>
30 #endif
32 #include <gcj/cni.h>
33 #include <jvm.h>
34 #include <java/net/InetAddress.h>
35 #include <java/net/UnknownHostException.h>
36 #include <java/lang/SecurityException.h>
38 #if defined(HAVE_UNAME) && ! defined(HAVE_GETHOSTNAME)
39 #include <sys/utsname.h>
40 #endif
42 #ifndef HAVE_GETHOSTNAME_DECL
43 extern "C" int gethostname (char *name, int namelen);
44 #endif
46 jbyteArray
47 java::net::InetAddress::aton (jstring host)
49 char *hostname;
50 char buf[100];
51 int len = JvGetStringUTFLength(host);
52 if (len < 100)
53 hostname = buf;
54 else
55 hostname = (char*) _Jv_AllocBytes (len+1);
56 JvGetStringUTFRegion (host, 0, host->length(), hostname);
57 buf[len] = '\0';
58 char* bytes = NULL;
59 int blen = 0;
60 #ifdef HAVE_INET_ATON
61 struct in_addr laddr;
62 if (inet_aton (hostname, &laddr))
64 bytes = (char*) &laddr;
65 blen = 4;
67 #elif defined(HAVE_INET_ADDR)
68 #if ! HAVE_IN_ADDR_T
69 typedef jint in_addr_t;
70 #endif
71 in_addr_t laddr = inet_addr (hostname);
72 if (laddr != (in_addr_t)(-1))
74 bytes = (char*) &laddr;
75 blen = 4;
77 #endif
78 #if defined (HAVE_INET_PTON) && defined (HAVE_INET6)
79 char inet6_addr[16];
80 if (len != 0 && inet_pton (AF_INET6, hostname, inet6_addr) > 0)
82 bytes = inet6_addr;
83 blen = 16;
85 #endif
86 if (blen == 0)
87 return NULL;
88 jbyteArray result = JvNewByteArray (blen);
89 memcpy (elements (result), bytes, blen);
90 return result;
93 jint
94 java::net::InetAddress::getFamily (jbyteArray bytes)
96 int len = bytes->length;
97 if (len == 4)
98 return AF_INET;
99 #ifdef HAVE_INET6
100 else if (len == 16)
101 return AF_INET6;
102 #endif /* HAVE_INET6 */
103 else
104 JvFail ("unrecognized size");
108 JArray<java::net::InetAddress*> *
109 java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr,
110 jboolean all)
112 struct hostent *hptr = NULL;
113 #if defined (HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR_R)
114 struct hostent hent_r;
115 #if HAVE_STRUCT_HOSTENT_DATA
116 struct hostent_data fixed_buffer, *buffer_r = &fixed_buffer;
117 #else
118 #if defined (__GLIBC__)
119 // FIXME: in glibc, gethostbyname_r returns NETDB_INTERNAL to herr and
120 // ERANGE to errno if the buffer size is too small, rather than what is
121 // expected here. We work around this by setting a bigger buffer size and
122 // hoping that it is big enough.
123 char fixed_buffer[1024];
124 #else
125 char fixed_buffer[200];
126 #endif
127 char *buffer_r = fixed_buffer;
128 int size_r = sizeof (fixed_buffer);
129 #endif
130 #endif
132 if (host != NULL)
134 char *hostname;
135 char buf[100];
136 int len = JvGetStringUTFLength(host);
137 if (len < 100)
138 hostname = buf;
139 else
140 hostname = (char*) _Jv_AllocBytes (len+1);
141 JvGetStringUTFRegion (host, 0, host->length(), hostname);
142 buf[len] = '\0';
143 #ifdef HAVE_GETHOSTBYNAME_R
144 while (true)
146 int ok;
147 #if HAVE_STRUCT_HOSTENT_DATA
148 ok = ! gethostbyname_r (hostname, &hent_r, buffer_r);
149 #else
150 int herr = 0;
151 #ifdef GETHOSTBYNAME_R_RETURNS_INT
152 ok = ! gethostbyname_r (hostname, &hent_r, buffer_r, size_r,
153 &hptr, &herr);
154 #else
155 hptr = gethostbyname_r (hostname, &hent_r, buffer_r, size_r, &herr);
156 ok = hptr != NULL;
157 #endif /* GETHOSTNAME_R_RETURNS_INT */
158 if (! ok && herr == ERANGE)
160 size_r *= 2;
161 buffer_r = (char *) _Jv_AllocBytes (size_r);
163 else
164 #endif /* HAVE_STRUCT_HOSTENT_DATA */
165 break;
167 #else
168 // FIXME: this is insufficient if some other piece of code calls
169 // this gethostbyname.
170 JvSynchronize sync (java::net::InetAddress::localhostAddress);
171 hptr = gethostbyname (hostname);
172 #endif /* HAVE_GETHOSTBYNAME_R */
174 else
176 jbyteArray bytes = iaddr->addr;
177 char *chars = (char*) elements (bytes);
178 int len = bytes->length;
179 int type;
180 char *val;
181 if (len == 4)
183 val = chars;
184 type = iaddr->family = AF_INET;
186 #ifdef HAVE_INET6
187 else if (len == 16)
189 val = (char *) &chars;
190 type = iaddr->family = AF_INET6;
192 #endif /* HAVE_INET6 */
193 else
194 JvFail ("unrecognized size");
196 #ifdef HAVE_GETHOSTBYADDR_R
197 while (true)
199 int ok;
200 #if HAVE_STRUCT_HOSTENT_DATA
201 ok = ! gethostbyaddr_r (val, len, type, &hent_r, buffer_r);
202 #else
203 int herr = 0;
204 #ifdef GETHOSTBYADDR_R_RETURNS_INT
205 ok = ! gethostbyaddr_r (val, len, type, &hent_r,
206 buffer_r, size_r, &hptr, &herr);
207 #else
208 hptr = gethostbyaddr_r (val, len, type, &hent_r,
209 buffer_r, size_r, &herr);
210 ok = hptr != NULL;
211 #endif /* GETHOSTBYADDR_R_RETURNS_INT */
212 if (! ok && herr == ERANGE)
214 size_r *= 2;
215 buffer_r = (char *) _Jv_AllocBytes (size_r);
217 else
218 #endif /* HAVE_STRUCT_HOSTENT_DATA */
219 break;
221 #else /* HAVE_GETHOSTBYADDR_R */
222 // FIXME: this is insufficient if some other piece of code calls
223 // this gethostbyaddr.
224 JvSynchronize sync (java::net::InetAddress::localhostAddress);
225 hptr = gethostbyaddr (val, len, type);
226 #endif /* HAVE_GETHOSTBYADDR_R */
228 if (hptr != NULL)
230 if (!all)
231 host = JvNewStringUTF (hptr->h_name);
232 java::lang::SecurityException *ex = checkConnect (host);
233 if (ex != NULL)
235 if (iaddr == NULL || iaddr->addr == NULL)
236 throw ex;
237 hptr = NULL;
240 if (hptr == NULL)
242 if (iaddr != NULL && iaddr->addr != NULL)
244 iaddr->hostName = iaddr->getHostAddress();
245 return NULL;
247 else
248 throw new java::net::UnknownHostException(host);
250 int count;
251 if (all)
253 char** ptr = hptr->h_addr_list;
254 count = 0;
255 while (*ptr++) count++;
257 else
258 count = 1;
259 JArray<java::net::InetAddress*> *result;
260 java::net::InetAddress** iaddrs;
261 if (all)
263 result = java::net::InetAddress::allocArray (count);
264 iaddrs = elements (result);
266 else
268 result = NULL;
269 iaddrs = &iaddr;
272 for (int i = 0; i < count; i++)
274 if (iaddrs[i] == NULL)
275 iaddrs[i] = new java::net::InetAddress (NULL, NULL);
276 if (iaddrs[i]->hostName == NULL)
277 iaddrs[i]->hostName = host;
278 if (iaddrs[i]->addr == NULL)
280 char *bytes = hptr->h_addr_list[i];
281 iaddrs[i]->addr = JvNewByteArray (hptr->h_length);
282 iaddrs[i]->family = getFamily (iaddrs[i]->addr);
283 memcpy (elements (iaddrs[i]->addr), bytes, hptr->h_length);
286 return result;
289 jstring
290 java::net::InetAddress::getLocalHostname ()
292 char *chars;
293 #ifdef HAVE_GETHOSTNAME
294 char buffer[MAXHOSTNAMELEN];
295 if (gethostname (buffer, MAXHOSTNAMELEN))
296 return NULL;
297 chars = buffer;
298 #elif HAVE_UNAME
299 struct utsname stuff;
300 if (uname (&stuff) != 0)
301 return NULL;
302 chars = stuff.nodename;
303 #else
304 return NULL;
305 #endif
306 // It is admittedly non-optimal to convert the hostname to Unicode
307 // only to convert it back in getByName, but simplicity wins. Note
308 // that unless there is a SecurityManager, we only get called once
309 // anyway, thanks to the InetAddress.localhost cache.
310 return JvNewStringUTF (chars);