libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / native / jni / java-net / java_net_VMNetworkInterface.c
blob658299733e54e523140cd5095a7555df6dbfe577
1 /* VMNetworkInterface.c - Native methods for NetworkInterface class
2 Copyright (C) 2003, 2005, 2006, 2008 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif /* HAVE_CONFIG_H */
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #ifdef HAVE_IFADDRS_H
45 #include <ifaddrs.h>
46 #endif
47 #include <netinet/in.h>
48 #include <errno.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
53 #include <net/if.h>
54 #include <sys/ioctl.h>
55 /* Required on Solaris. */
56 #include <unistd.h>
58 #ifdef HAVE_SYS_SOCKIO_H
59 # include <sys/sockio.h>
60 #endif
62 #include <jni.h>
63 #include <jcl.h>
65 #include <cpnative.h>
66 #include <cpnet.h>
68 #include "java_net_VMNetworkInterface.h"
70 int iff_flags(JNIEnv *, jstring, jint *);
72 static jmethodID java_net_VMNetworkInterface_init;
73 static jmethodID java_net_VMNetworkInterface_addAddress;
76 * Initialize our static method ID's.
78 * Class: java_net_VMNetworkInterface
79 * Method: initIds
80 * Signature: ()V
82 JNIEXPORT void JNICALL
83 Java_java_net_VMNetworkInterface_initIds (JNIEnv *env, jclass clazz)
85 java_net_VMNetworkInterface_init =
86 (*env)->GetMethodID (env, clazz, "<init>", "(Ljava/lang/String;)V");
87 if (java_net_VMNetworkInterface_init == NULL)
89 if (!(*env)->ExceptionCheck (env))
90 JCL_ThrowException (env, "java/lang/NoSuchMethodError",
91 "VMNetworkinterface.addAddress");
92 return;
94 java_net_VMNetworkInterface_addAddress =
95 (*env)->GetMethodID (env, clazz, "addAddress", "(Ljava/nio/ByteBuffer;)V");
96 if (java_net_VMNetworkInterface_addAddress == NULL)
98 if (!(*env)->ExceptionCheck (env))
99 JCL_ThrowException (env, "java/lang/NoSuchMethodError",
100 "VMNetworkinterface.addAddress");
104 struct netif_entry
106 char *name;
107 jobject netif;
108 int numaddrs;
109 struct netif_entry *next;
112 #if defined (HAVE_IFADDRS_H) && defined (HAVE_GETIFADDRS)
113 static void
114 free_netif_list (JNIEnv *env, struct netif_entry *list)
116 while (list != NULL)
118 struct netif_entry *e = list->next;
119 JCL_free (env, list);
120 list = e;
123 #endif
126 * Returns all local network interfaces as an array.
128 JNIEXPORT jobjectArray JNICALL
129 Java_java_net_VMNetworkInterface_getVMInterfaces (JNIEnv * env,
130 jclass clazz UNUSED)
132 #if defined (HAVE_IFADDRS_H) && defined (HAVE_GETIFADDRS)
133 struct ifaddrs *ifaddrs, *i;
134 struct netif_entry *iflist = NULL, *e;
135 jobjectArray netifs;
136 int numifs = 0;
137 int k;
139 if (getifaddrs (&ifaddrs) == -1)
141 JCL_ThrowException (env, "java/net/SocketException", strerror (errno));
142 return NULL;
145 for (i = ifaddrs; i != NULL; i = i->ifa_next)
147 if (iflist == NULL)
149 iflist = JCL_malloc (env, sizeof (struct netif_entry));
150 if (iflist == NULL)
152 freeifaddrs (ifaddrs);
153 return NULL;
155 iflist->name = i->ifa_name;
156 iflist->numaddrs = 0;
157 iflist->next = NULL;
158 iflist->netif = (*env)->NewObject (env, clazz, java_net_VMNetworkInterface_init,
159 (*env)->NewStringUTF (env, i->ifa_name));
160 if (iflist->netif == NULL)
162 freeifaddrs (ifaddrs);
163 JCL_free (env, iflist);
164 return NULL;
166 e = iflist;
168 else
170 struct netif_entry *p = NULL;
171 for (e = iflist; e != NULL; e = e->next)
173 if (strcmp (e->name, i->ifa_name) == 0)
174 break;
175 p = e;
178 if (e == NULL)
180 p->next = (struct netif_entry *) JCL_malloc (env, sizeof (struct netif_entry));
181 if (p->next == NULL)
183 free_netif_list (env, iflist);
184 freeifaddrs (ifaddrs);
185 return NULL;
187 e = p->next;
188 e->name = i->ifa_name;
189 e->numaddrs = 0;
190 e->next = NULL;
191 e->netif = (*env)->NewObject (env, clazz, java_net_VMNetworkInterface_init,
192 (*env)->NewStringUTF (env, i->ifa_name));
193 if (e->netif == NULL)
195 free_netif_list (env, iflist);
196 freeifaddrs (ifaddrs);
197 return NULL;
202 if (i->ifa_addr == NULL)
203 continue;
205 if (i->ifa_addr->sa_family == AF_INET)
207 struct sockaddr_in *sin = (struct sockaddr_in *) i->ifa_addr;
208 jobject buffer = (*env)->NewDirectByteBuffer (env, &(sin->sin_addr.s_addr), 4);
209 (*env)->CallVoidMethod (env, e->netif, java_net_VMNetworkInterface_addAddress,
210 buffer);
211 if ((*env)->ExceptionCheck (env))
213 free_netif_list (env, iflist);
214 freeifaddrs (ifaddrs);
215 return NULL;
217 (*env)->DeleteLocalRef (env, buffer);
218 e->numaddrs++;
220 #ifdef HAVE_INET6
221 else if (i->ifa_addr->sa_family == AF_INET6)
223 struct sockaddr_in6 *sin = (struct sockaddr_in6 *) i->ifa_addr;
224 jobject buffer = (*env)->NewDirectByteBuffer (env, &(sin->sin6_addr.s6_addr), 16);
225 (*env)->CallVoidMethod (env, e->netif, java_net_VMNetworkInterface_addAddress,
226 buffer);
227 if ((*env)->ExceptionCheck (env))
229 free_netif_list (env, iflist);
230 freeifaddrs (ifaddrs);
231 return NULL;
233 (*env)->DeleteLocalRef (env, buffer);
234 e->numaddrs++;
236 #endif /* HAVE_INET6 */
239 /* Count how many interfaces we have that have addresses. */
240 for (e = iflist; e != NULL; e = e->next)
242 if (e->numaddrs != 0)
243 numifs++;
246 netifs = (*env)->NewObjectArray (env, numifs, clazz, NULL);
247 k = 0;
248 for (e = iflist; e != NULL && k < numifs; e = e->next)
250 if (e->numaddrs != 0)
252 (*env)->SetObjectArrayElement (env, netifs, k, e->netif);
253 (*env)->DeleteLocalRef (env, e->netif);
254 k++;
258 free_netif_list (env, iflist);
259 freeifaddrs (ifaddrs);
260 return netifs;
261 #else
262 JCL_ThrowException (env, "java/net/SocketException", "getifaddrs not supported");
263 return NULL;
264 #endif /* HAVE_IFADDRS_H && HAVE_GETIFADDRS */
267 int iff_flags(JNIEnv *env, jstring name, jint *flags)
269 struct ifreq iff;
270 const char *iff_name;
271 jint socket;
272 int error, retval;
274 if ((error = cpnet_openSocketDatagram(env, &socket, AF_INET)))
276 return error;
279 iff_name = JCL_jstring_to_cstring(env, name);
280 memset(&iff, 0, sizeof(iff));
281 strcpy(iff.ifr_name, iff_name);
283 if (ioctl(socket, SIOCGIFFLAGS, &iff) >= 0)
285 *flags = (jint) iff.ifr_flags;
287 retval = 0;
289 else
291 retval = errno;
294 cpnet_close(env, socket);
296 JCL_free_cstring(env, name, iff_name);
298 return retval;
301 JNIEXPORT jboolean JNICALL
302 Java_java_net_VMNetworkInterface_isUp (JNIEnv *env, jclass class UNUSED,
303 jstring name)
305 jint flags;
306 int error;
307 jboolean retval;
309 if ((error = iff_flags(env, name, &flags)))
311 JCL_ThrowException(env, "java/net/SocketException",
312 cpnative_getErrorString(error));
314 retval = JNI_FALSE;
316 else
318 retval = (flags & (IFF_UP | IFF_RUNNING))
319 ? JNI_TRUE
320 : JNI_FALSE;
323 return retval;
326 JNIEXPORT jboolean JNICALL
327 Java_java_net_VMNetworkInterface_isPointToPoint (JNIEnv *env,
328 jclass class UNUSED,
329 jstring name)
331 jint flags;
332 int error;
333 jboolean retval;
335 if ((error = iff_flags(env, name, &flags)))
337 JCL_ThrowException(env, "java/net/SocketException",
338 cpnative_getErrorString(error));
340 retval = JNI_FALSE;
342 else
344 retval = (flags & IFF_POINTOPOINT) ? JNI_TRUE
345 : JNI_FALSE;
348 return retval;
351 JNIEXPORT jboolean JNICALL
352 Java_java_net_VMNetworkInterface_isLoopback (JNIEnv *env,
353 jclass class UNUSED,
354 jstring name)
356 jint flags;
357 int error;
358 jboolean retval;
360 if ((error = iff_flags(env, name, &flags)))
362 JCL_ThrowException(env, "java/net/SocketException",
363 cpnative_getErrorString(error));
365 retval = JNI_FALSE;
367 else
369 retval = (flags & IFF_LOOPBACK) ? JNI_TRUE : JNI_FALSE;
372 return retval;
375 JNIEXPORT jboolean JNICALL
376 Java_java_net_VMNetworkInterface_supportsMulticast (JNIEnv *env,
377 jclass class UNUSED,
378 jstring name)
380 jint flags;
381 int error;
382 jboolean retval;
384 if ((error = iff_flags(env, name, &flags)))
386 JCL_ThrowException(env, "java/net/SocketException",
387 cpnative_getErrorString(error));
389 retval = JNI_FALSE;
391 else
393 retval = (flags & IFF_MULTICAST) ? JNI_TRUE : JNI_FALSE;
396 return retval;
399 /* end of file */