OSDN Git Service

* config/rs6000/x-rs6000: New file.
[pf3gnuchains/gcc-fork.git] / libjava / java / net / natVMInetAddressPosix.cc
1 /* Copyright (C) 2003, 2006  Free Software Foundation
2
3    This file is part of libgcj.
4
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
7 details.  */
8
9 #include <config.h>
10
11 #ifdef HAVE_UNISTD_H
12 #include <unistd.h>
13 #endif
14 #include <string.h>
15 #include <errno.h>
16
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
31
32 #include <gcj/cni.h>
33 #include <jvm.h>
34 #include <java/net/VMInetAddress.h>
35 #include <java/net/UnknownHostException.h>
36
37 #if defined(HAVE_UNAME) && ! defined(HAVE_GETHOSTNAME)
38 #include <sys/utsname.h>
39 #endif
40
41 #ifndef HAVE_GETHOSTNAME_DECL
42 extern "C" int gethostname (char *name, int namelen);
43 #endif
44
45 jstring
46 java::net::VMInetAddress::getLocalHostname ()
47 {
48   char *chars;
49 #ifdef HAVE_GETHOSTNAME
50   char buffer[MAXHOSTNAMELEN];
51   if (gethostname (buffer, MAXHOSTNAMELEN))
52     return NULL;
53   chars = buffer;
54 #elif HAVE_UNAME
55   struct utsname stuff;
56   if (uname (&stuff) != 0)
57     return NULL;
58   chars = stuff.nodename;
59 #else
60   return NULL;
61 #endif
62   // It is admittedly non-optimal to convert the hostname to Unicode
63   // only to convert it back in getByName, but simplicity wins.
64   return JvNewStringUTF (chars);
65 }
66
67 jbyteArray
68 java::net::VMInetAddress::lookupInaddrAny ()
69 {
70 #if ! HAVE_IN_ADDR_T
71   typedef jint in_addr_t;
72 #endif
73   in_addr_t laddr = INADDR_ANY;
74   char *bytes = (char *) &laddr;
75   int blen = sizeof (laddr);
76   jbyteArray result = JvNewByteArray (blen);
77   memcpy (elements (result), bytes, blen);
78   return result;
79 }
80
81 jstring
82 java::net::VMInetAddress::getHostByAddr (jbyteArray addr)
83 {
84   struct hostent *hptr = NULL;
85 #ifdef HAVE_GETHOSTBYADDR_R
86   struct hostent hent_r;
87 #if HAVE_STRUCT_HOSTENT_DATA
88   struct hostent_data fixed_buffer, *buffer_r = &fixed_buffer;
89 #else
90 #ifdef __GLIBC__
91   // FIXME: in glibc, gethostbyname_r returns NETDB_INTERNAL to herr and
92   // ERANGE to errno if the buffer size is too small, rather than what is 
93   // expected here. We work around this by setting a bigger buffer size and 
94   // hoping that it is big enough.
95   char fixed_buffer[1024];
96 #else
97   char fixed_buffer[200];
98 #endif /* __GLIBC__ */
99   char *buffer_r = fixed_buffer;
100   int size_r = sizeof (fixed_buffer);
101 #endif /* HAVE_STRUCT_HOSTENT_DATA */
102 #endif /* HAVE_GETHOSTBYADDR_R */
103
104   char *bytes = (char*) elements (addr);
105   int len = addr->length;
106   int type;
107   char *val;
108   if (len == 4)
109     {
110       val = bytes;
111       type = AF_INET;
112     }
113 #ifdef HAVE_INET6
114   else if (len == 16)
115     {
116       val = (char *) &bytes;
117       type = AF_INET6;
118     }
119 #endif /* HAVE_INET6 */
120   else
121     JvFail ("unrecognized size");
122
123 #ifdef HAVE_GETHOSTBYADDR_R
124   while (true)
125     {
126       int ok;
127 #if HAVE_STRUCT_HOSTENT_DATA
128       ok = ! gethostbyaddr_r (val, len, type, &hent_r, buffer_r);
129 #else
130       int herr = 0;
131 #ifdef GETHOSTBYADDR_R_RETURNS_INT
132       ok = ! gethostbyaddr_r (val, len, type, &hent_r,
133                               buffer_r, size_r, &hptr, &herr);
134 #else
135       hptr = gethostbyaddr_r (val, len, type, &hent_r,
136                               buffer_r, size_r, &herr);
137       ok = hptr != NULL;
138 #endif /* GETHOSTBYADDR_R_RETURNS_INT */
139       if (! ok && herr == ERANGE)
140         {
141           size_r *= 2;
142           buffer_r = (char *) _Jv_AllocBytes (size_r);
143         }
144       else 
145 #endif /* HAVE_STRUCT_HOSTENT_DATA */
146         break;
147     }
148 #else /* HAVE_GETHOSTBYADDR_R */
149   // FIXME: this is insufficient if some other piece of code calls
150   // this gethostbyaddr.
151   JvSynchronize sync (&java::net::VMInetAddress::class$);
152   hptr = gethostbyaddr (val, len, type);
153 #endif /* HAVE_GETHOSTBYADDR_R */
154
155   if (hptr == NULL)
156     throw new java::net::UnknownHostException ();
157
158   return JvNewStringUTF (hptr->h_name);
159 }
160
161 JArray<jbyteArray> *
162 java::net::VMInetAddress::getHostByName (jstring host)
163 {
164   struct hostent *hptr = NULL;
165 #ifdef HAVE_GETHOSTBYNAME_R
166   struct hostent hent_r;
167 #if HAVE_STRUCT_HOSTENT_DATA
168   struct hostent_data fixed_buffer, *buffer_r = &fixed_buffer;
169 #else
170 #ifdef __GLIBC__
171   // FIXME: in glibc, gethostbyname_r returns NETDB_INTERNAL to herr and
172   // ERANGE to errno if the buffer size is too small, rather than what is 
173   // expected here. We work around this by setting a bigger buffer size and 
174   // hoping that it is big enough.
175   char fixed_buffer[1024];
176 #else
177   char fixed_buffer[200];
178 #endif /* __GLIBC__ */
179   char *buffer_r = fixed_buffer;
180   int size_r = sizeof (fixed_buffer);
181 #endif /* HAVE_STRUCT_HOSTENT_DATA */
182 #endif /* HAVE_GETHOSTBYNAME_R */
183
184   char *hostname;
185   char buf[100];
186   int len = JvGetStringUTFLength(host);
187   if (len < 100)
188     hostname = buf;
189   else
190     hostname = (char *) _Jv_AllocBytes (len + 1);
191   JvGetStringUTFRegion (host, 0, host->length(), hostname);
192   buf[len] = '\0';
193 #ifdef HAVE_GETHOSTBYNAME_R
194   while (true)
195     {
196       int ok;
197 #if HAVE_STRUCT_HOSTENT_DATA
198       ok = ! gethostbyname_r (hostname, &hent_r, buffer_r);
199 #else
200       int herr = 0;
201 #ifdef GETHOSTBYNAME_R_RETURNS_INT
202       ok = ! gethostbyname_r (hostname, &hent_r, buffer_r, size_r,
203                               &hptr, &herr);
204 #else
205       hptr = gethostbyname_r (hostname, &hent_r, buffer_r, size_r, &herr);
206       ok = hptr != NULL;
207 #endif /* GETHOSTNAME_R_RETURNS_INT */
208       if (! ok && herr == ERANGE)
209         {
210           size_r *= 2;
211           buffer_r = (char *) _Jv_AllocBytes (size_r);
212         }
213       else
214 #endif /* HAVE_STRUCT_HOSTENT_DATA */
215         break;
216     }
217 #else /* HAVE_GETHOSTBYNAME_R */
218   // FIXME: this is insufficient if some other piece of code calls
219   // this gethostbyname.
220   JvSynchronize sync (&java::net::VMInetAddress::class$);
221   hptr = gethostbyname (hostname);
222 #endif /* HAVE_GETHOSTBYNAME_R */
223
224   if (hptr == NULL)
225     throw new java::net::UnknownHostException (host);
226
227   int count = 0;
228   char ** ptr = hptr->h_addr_list;
229   while (*ptr++)  count++;
230
231   JArray<jbyteArray> *result =
232     (JArray<jbyteArray> *) _Jv_NewObjectArray (
233       count, _Jv_GetArrayClass(JvPrimClass(byte), NULL), NULL);
234   jbyteArray* addrs = elements (result);
235
236   for (int i = 0; i < count; i++)
237     {
238       addrs[i] = JvNewByteArray (hptr->h_length);
239       memcpy (elements (addrs[i]), hptr->h_addr_list[i], hptr->h_length);
240     }
241   return result;
242 }
243
244 jbyteArray
245 java::net::VMInetAddress::aton (jstring host)
246 {
247   char *hostname;
248   char buf[100];
249   int len = JvGetStringUTFLength(host);
250   if (len < 100)
251     hostname = buf;
252   else
253     hostname = (char *) _Jv_AllocBytes (len+1);
254   JvGetStringUTFRegion (host, 0, host->length(), hostname);
255   buf[len] = '\0';
256   char *bytes = NULL;
257   int blen = 0;
258 #ifdef HAVE_INET_ATON
259   struct in_addr laddr;
260   if (inet_aton (hostname, &laddr))
261     {
262       bytes = (char *) &laddr;
263       blen = 4;
264     }
265 #elif defined(HAVE_INET_ADDR)
266 #if ! HAVE_IN_ADDR_T
267   typedef jint in_addr_t;
268 #endif
269   in_addr_t laddr = inet_addr (hostname);
270   if (laddr != (in_addr_t)(-1))
271     {
272       bytes = (char *) &laddr;
273       blen = 4;
274     }
275 #endif
276 #if defined (HAVE_INET_PTON) && defined (HAVE_INET6)
277   char inet6_addr[16];
278   if (len != 0 && inet_pton (AF_INET6, hostname, inet6_addr) > 0)
279     {
280       bytes = inet6_addr;
281       blen = 16;
282     }
283 #endif
284   if (blen == 0)
285     return NULL;
286   jbyteArray result = JvNewByteArray (blen);
287   memcpy (elements (result), bytes, blen);
288   return result;
289 }