Initial revision
[gcc.git] / libjava / java / net / natInetAddress.cc
1 // natClass.cc - Implementation of java.lang.Class native methods.
2
3 /* Copyright (C) 1998, 1999 Cygnus Solutions
4
5 This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
10
11 #include <config.h>
12
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16 #include <string.h>
17 #include <errno.h>
18
19 #include <sys/param.h>
20 #include <sys/types.h>
21 #ifdef HAVE_SYS_SOCKET_H
22 #include <sys/socket.h>
23 #endif
24 #ifdef HAVE_NETINET_IN_H
25 #include <netinet/in.h>
26 #endif
27 #ifdef HAVE_ARPA_INET_H
28 #include <arpa/inet.h>
29 #endif
30 #ifdef HAVE_NETDB_H
31 #include <netdb.h>
32 #endif
33
34 #include <cni.h>
35 #include <jvm.h>
36 #include <java/net/InetAddress.h>
37 #include <java/net/UnknownHostException.h>
38 #include <java/lang/SecurityException.h>
39
40 #if defined(HAVE_UNAME) && ! defined(HAVE_GETHOSTNAME)
41 #include <sys/utsname.h>
42 #endif
43
44 #ifndef HAVE_GETHOSTNAME_DECL
45 extern "C" int gethostname (char *name, int namelen);
46 #endif
47
48 jbyteArray
49 java::net::InetAddress::aton (jstring host)
50 {
51 char *hostname;
52 char buf[100];
53 int len = JvGetStringUTFLength(host);
54 if (len < 100)
55 hostname = buf;
56 else
57 hostname = (char*) _Jv_AllocBytesChecked (len+1);
58 JvGetStringUTFRegion (host, 0, host->length(), hostname);
59 buf[len] = '\0';
60 char* bytes = NULL;
61 int blen = 0;
62 #ifdef HAVE_INET_ATON
63 struct in_addr laddr;
64 if (inet_aton (hostname, &laddr))
65 {
66 bytes = (char*) &laddr;
67 len = 4;
68 }
69 #elif defined(HAVE_INET_ADDR)
70 in_addr_t laddr = inet_addr (hostname);
71 if (laddr != (in_addr_t)(-1))
72 {
73 bytes = (char*) &laddr;
74 len = 4;
75 }
76 #endif
77 #ifdef HAVE_INET_PTON
78 char inet6_addr[16];
79 if (len == 0 && inet_pton (AF_INET6, hostname, inet6_addr) > 0)
80 {
81 bytes = inet6_addr;
82 len = 16;
83 }
84 #endif
85 if (blen == 0)
86 return NULL;
87 jbyteArray result = JvNewByteArray (len);
88 memcpy (elements (result), bytes, blen);
89 return result;
90 }
91
92
93 JArray<java::net::InetAddress*> *
94 java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr,
95 jboolean all)
96 {
97 struct hostent *hptr = NULL;
98 #if defined (HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR_R)
99 struct hostent hent_r;
100 char fixed_buffer[200];
101 char *buffer_r = fixed_buffer;
102 int size_r = sizeof (fixed_buffer);
103 #endif
104
105 if (host != NULL)
106 {
107 char *hostname;
108 char buf[100];
109 int len = JvGetStringUTFLength(host);
110 if (len < 100)
111 hostname = buf;
112 else
113 hostname = (char*) _Jv_AllocBytesChecked (len+1);
114 JvGetStringUTFRegion (host, 0, host->length(), hostname);
115 buf[len] = '\0';
116 #ifdef HAVE_GETHOSTBYNAME_R
117 int herr = ERANGE;
118 while (hptr == NULL && herr == ERANGE)
119 {
120 int ok;
121 #ifdef GETHOSTBYNAME_R_RETURNS_INT
122 ok = ! gethostbyname_r (hostname, &hent_r, buffer_r, size_r,
123 &hptr, &herr);
124 #else
125 hptr = gethostbyname_r (hostname, &hent_r, buffer_r, size_r, &herr);
126 ok = hptr != NULL;
127 #endif /* GETHOSTNAME_R_RETURNS_INT */
128 if (! ok && herr == ERANGE)
129 {
130 size_r *= 2;
131 buffer_r = (char *) _Jv_AllocBytesChecked (size_r);
132 }
133 }
134 #else
135 // FIXME: this is insufficient if some other piece of code calls
136 // this gethostbyname.
137 JvSynchronize sync (java::net::InetAddress::localhostAddress);
138 hptr = gethostbyname (hostname);
139 #endif /* HAVE_GETHOSTBYNAME_R */
140 }
141 else
142 {
143 jbyteArray bytes = iaddr->address;
144 char *chars = (char*) elements (bytes);
145 int len = bytes->length;
146 int type;
147 char *val;
148 if (len == 4)
149 {
150 val = chars;
151 type = AF_INET;
152 }
153 #ifdef HAVE_INET6
154 else if (len == 16)
155 {
156 val = (char *) &chars;
157 type = AF_INET16;
158 }
159 #endif /* HAVE_INET6 */
160 else
161 JvFail ("unrecognized size");
162
163 #ifdef HAVE_GETHOSTBYADDR_R
164 int herr = ERANGE;
165 while (hptr == NULL && herr == ERANGE)
166 {
167 int ok;
168 #ifdef GETHOSTBYADDR_R_RETURNS_INT
169 ok = ! gethostbyaddr_r (val, len, type, &hent_r,
170 buffer_r, size_r, &hptr, &herr);
171 #else
172 hptr = gethostbyaddr_r (val, len, type, &hent_r,
173 buffer_r, size_r, &herr);
174 ok = hptr != NULL;
175 #endif /* GETHOSTBYADDR_R_RETURNS_INT */
176 if (! ok && herr == ERANGE)
177 {
178 size_r *= 2;
179 buffer_r = (char *) _Jv_AllocBytesChecked (size_r);
180 }
181 }
182 #else /* HAVE_GETHOSTBYADDR_R */
183 // FIXME: this is insufficient if some other piece of code calls
184 // this gethostbyaddr.
185 JvSynchronize sync (java::net::InetAddress::localhostAddress);
186 hptr = gethostbyaddr (val, len, type);
187 #endif /* HAVE_GETHOSTBYADDR_R */
188 }
189 if (hptr != NULL)
190 {
191 host = JvNewStringUTF (hptr->h_name);
192 java::lang::SecurityException *ex = checkConnect (host);
193 if (ex != NULL)
194 {
195 if (iaddr == NULL || iaddr->address == NULL)
196 JvThrow (ex);
197 hptr = NULL;
198 }
199 }
200 if (hptr == NULL)
201 {
202 if (iaddr != NULL && iaddr->address != NULL)
203 {
204 iaddr->hostname = iaddr->getHostAddress();
205 return NULL;
206 }
207 else
208 JvThrow (new java::net::UnknownHostException(host));
209 }
210 int count;
211 if (all)
212 {
213 char** ptr = hptr->h_addr_list;
214 count = 0;
215 while (*ptr++) count++;
216 }
217 else
218 count = 1;
219 JArray<java::net::InetAddress*> *result;
220 java::net::InetAddress** iaddrs;
221 if (all)
222 {
223 result = java::net::InetAddress::allocArray (count);
224 iaddrs = elements (result);
225 }
226 else
227 {
228 result = NULL;
229 iaddrs = &iaddr;
230 }
231
232 for (int i = 0; i < count; i++)
233 {
234 if (iaddrs[i] == NULL)
235 iaddrs[i] = new java::net::InetAddress (NULL, NULL);
236 if (i == 0)
237 iaddrs[0]->hostname = host;
238 if (iaddrs[i]->address == NULL)
239 {
240 char *bytes = hptr->h_addr_list[i];
241 iaddr->address = JvNewByteArray (hptr->h_length);
242 memcpy (elements (iaddr->address), bytes, hptr->h_length);
243 }
244 }
245 return result;
246 }
247
248 jstring
249 java::net::InetAddress::getLocalHostname ()
250 {
251 char *chars;
252 #ifdef HAVE_GETHOSTNAME
253 char buffer[MAXHOSTNAMELEN];
254 if (gethostname (buffer, MAXHOSTNAMELEN))
255 return NULL;
256 chars = buffer;
257 #elif HAVE_UNAME
258 struct utsname stuff;
259 if (uname (&stuff) != 0)
260 return NULL:
261 chars = stuff.nodename;
262 #else
263 return NULL;
264 #endif
265 // It is admittedly non-optimal to convert the hostname to Unicode
266 // only to convert it back in getByName, but simplicity wins. Note
267 // that unless there is a SecurityManager, we only get called once
268 // anyway, thanks to the InetAddress.localhost cache.
269 return JvNewStringUTF (chars);
270 }