OSDN Git Service

9d5f93e857fc25d9186455bee9d58f6a4e7409c2
[pf3gnuchains/gcc-fork.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_INET6;
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 }