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
17 #include <sys/param.h>
18 #include <sys/types.h>
19 #ifdef HAVE_SYS_SOCKET_H
20 #include <sys/socket.h>
22 #ifdef HAVE_NETINET_IN_H
23 #include <netinet/in.h>
25 #ifdef HAVE_ARPA_INET_H
26 #include <arpa/inet.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>
42 #ifndef HAVE_GETHOSTNAME_DECL
43 extern "C" int gethostname (char *name
, int namelen
);
47 java::net::InetAddress::aton (jstring host
)
51 int len
= JvGetStringUTFLength(host
);
55 hostname
= (char*) _Jv_AllocBytes (len
+1);
56 JvGetStringUTFRegion (host
, 0, host
->length(), hostname
);
62 if (inet_aton (hostname
, &laddr
))
64 bytes
= (char*) &laddr
;
67 #elif defined(HAVE_INET_ADDR)
69 typedef jint in_addr_t
;
71 in_addr_t laddr
= inet_addr (hostname
);
72 if (laddr
!= (in_addr_t
)(-1))
74 bytes
= (char*) &laddr
;
78 #if defined (HAVE_INET_PTON) && defined (HAVE_INET6)
80 if (len
!= 0 && inet_pton (AF_INET6
, hostname
, inet6_addr
) > 0)
88 jbyteArray result
= JvNewByteArray (blen
);
89 memcpy (elements (result
), bytes
, blen
);
94 java::net::InetAddress::getFamily (jbyteArray bytes
)
96 int len
= bytes
->length
;
102 #endif /* HAVE_INET6 */
104 JvFail ("unrecognized size");
108 JArray
<java::net::InetAddress
*> *
109 java::net::InetAddress::lookup (jstring host
, java::net::InetAddress
* iaddr
,
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
;
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];
125 char fixed_buffer
[200];
127 char *buffer_r
= fixed_buffer
;
128 int size_r
= sizeof (fixed_buffer
);
136 int len
= JvGetStringUTFLength(host
);
140 hostname
= (char*) _Jv_AllocBytes (len
+1);
141 JvGetStringUTFRegion (host
, 0, host
->length(), hostname
);
143 #ifdef HAVE_GETHOSTBYNAME_R
147 #if HAVE_STRUCT_HOSTENT_DATA
148 ok
= ! gethostbyname_r (hostname
, &hent_r
, buffer_r
);
151 #ifdef GETHOSTBYNAME_R_RETURNS_INT
152 ok
= ! gethostbyname_r (hostname
, &hent_r
, buffer_r
, size_r
,
155 hptr
= gethostbyname_r (hostname
, &hent_r
, buffer_r
, size_r
, &herr
);
157 #endif /* GETHOSTNAME_R_RETURNS_INT */
158 if (! ok
&& herr
== ERANGE
)
161 buffer_r
= (char *) _Jv_AllocBytes (size_r
);
164 #endif /* HAVE_STRUCT_HOSTENT_DATA */
168 // FIXME: this is insufficient if some other piece of code calls
169 // this gethostbyname.
170 JvSynchronize
sync (java::net::InetAddress::loopbackAddress
);
171 hptr
= gethostbyname (hostname
);
172 #endif /* HAVE_GETHOSTBYNAME_R */
176 jbyteArray bytes
= iaddr
->addr
;
177 char *chars
= (char*) elements (bytes
);
178 int len
= bytes
->length
;
184 type
= iaddr
->family
= AF_INET
;
189 val
= (char *) &chars
;
190 type
= iaddr
->family
= AF_INET6
;
192 #endif /* HAVE_INET6 */
194 JvFail ("unrecognized size");
196 #ifdef HAVE_GETHOSTBYADDR_R
200 #if HAVE_STRUCT_HOSTENT_DATA
201 ok
= ! gethostbyaddr_r (val
, len
, type
, &hent_r
, buffer_r
);
204 #ifdef GETHOSTBYADDR_R_RETURNS_INT
205 ok
= ! gethostbyaddr_r (val
, len
, type
, &hent_r
,
206 buffer_r
, size_r
, &hptr
, &herr
);
208 hptr
= gethostbyaddr_r (val
, len
, type
, &hent_r
,
209 buffer_r
, size_r
, &herr
);
211 #endif /* GETHOSTBYADDR_R_RETURNS_INT */
212 if (! ok
&& herr
== ERANGE
)
215 buffer_r
= (char *) _Jv_AllocBytes (size_r
);
218 #endif /* HAVE_STRUCT_HOSTENT_DATA */
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::loopbackAddress
);
225 hptr
= gethostbyaddr (val
, len
, type
);
226 #endif /* HAVE_GETHOSTBYADDR_R */
231 host
= JvNewStringUTF (hptr
->h_name
);
235 if (iaddr
!= NULL
&& iaddr
->addr
!= NULL
)
237 iaddr
->hostName
= iaddr
->getHostAddress();
241 throw new java::net::UnknownHostException(host
);
246 char** ptr
= hptr
->h_addr_list
;
248 while (*ptr
++) count
++;
252 JArray
<java::net::InetAddress
*> *result
;
253 java::net::InetAddress
** iaddrs
;
256 result
= java::net::InetAddress::allocArray (count
);
257 iaddrs
= elements (result
);
265 for (int i
= 0; i
< count
; i
++)
267 if (iaddrs
[i
] == NULL
)
268 iaddrs
[i
] = new java::net::InetAddress (NULL
, NULL
);
269 if (iaddrs
[i
]->hostName
== NULL
)
270 iaddrs
[i
]->hostName
= host
;
271 if (iaddrs
[i
]->addr
== NULL
)
273 char *bytes
= hptr
->h_addr_list
[i
];
274 iaddrs
[i
]->addr
= JvNewByteArray (hptr
->h_length
);
275 iaddrs
[i
]->family
= getFamily (iaddrs
[i
]->addr
);
276 memcpy (elements (iaddrs
[i
]->addr
), bytes
, hptr
->h_length
);
283 java::net::InetAddress::getLocalHostname ()
286 #ifdef HAVE_GETHOSTNAME
287 char buffer
[MAXHOSTNAMELEN
];
288 if (gethostname (buffer
, MAXHOSTNAMELEN
))
292 struct utsname stuff
;
293 if (uname (&stuff
) != 0)
295 chars
= stuff
.nodename
;
299 // It is admittedly non-optimal to convert the hostname to Unicode
300 // only to convert it back in getByName, but simplicity wins. Note
301 // that unless there is a SecurityManager, we only get called once
302 // anyway, thanks to the InetAddress.localhost cache.
303 return JvNewStringUTF (chars
);