1 /* VMPlainSocketImpl.c - Native methods for PlainSocketImpl class
2 Copyright (C) 2005, 2006 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)
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
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
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. */
41 #endif /* HAVE_CONFIG_H */
43 #include <config-int.h>
45 #include <sys/ioctl.h>
46 #include <sys/types.h>
47 #include <sys/socket.h>
52 #include <netinet/in.h>
53 #include <netinet/tcp.h>
69 #include "gnu_java_net_VMPlainSocketImpl.h"
71 #define THROW_NO_NETWORK(env) JCL_ThrowException (env, "java/lang/InternalError", "this platform not configured for network support")
74 * Class: gnu_java_net_VMPlainSocketImpl
78 JNIEXPORT void JNICALL
79 Java_gnu_java_net_VMPlainSocketImpl_bind (JNIEnv *env,
80 jclass clazz __attribute__((unused)),
81 jint fd, jbyteArray addr, jint port)
83 struct sockaddr_in sockaddr;
88 elems = (*env)->GetByteArrayElements (env, addr, NULL);
90 memset(&sockaddr, 0, sizeof (struct sockaddr_in));
91 sockaddr.sin_family = AF_INET;
92 sockaddr.sin_port = htons (port);
93 /* addr is already in network byte order. */
95 sockaddr.sin_addr.s_addr = *((uint32_t *) elems);
97 sockaddr.sin_addr.s_addr = INADDR_ANY;
99 /* bind(2) from BSD says bind will never return EINTR */
100 /* bind is not a blocking system call */
101 ret = bind (fd, (struct sockaddr *) &sockaddr, sizeof (struct sockaddr_in));
104 (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT);
107 JCL_ThrowException (env, BIND_EXCEPTION, strerror (errno));
109 cpio_closeOnExec(ret);
114 * Class: gnu_java_net_VMPlainSocketImpl
118 JNIEXPORT void JNICALL
119 Java_gnu_java_net_VMPlainSocketImpl_bind6 (JNIEnv *env,
120 jclass c __attribute__((unused)),
121 jint fd, jbyteArray addr, jint port)
123 /* FIXME! Add check if we have IPv6! */
124 struct sockaddr_in6 sockaddr;
128 elems = (*env)->GetByteArrayElements (env, addr, NULL);
130 memset (&sockaddr, 0, sizeof (struct sockaddr_in6));
131 sockaddr.sin6_family = AF_INET6;
132 sockaddr.sin6_port = htons (port);
133 memcpy (&sockaddr.sin6_addr.s6_addr, elems, 16);
135 /* bind(2) from BSD says bind will never return EINTR */
136 /* bind is not a blocking system call */
137 ret = bind (fd, (struct sockaddr *) &sockaddr,
138 sizeof (struct sockaddr_in6));
140 (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT);
143 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
148 * Class: gnu_java_net_VMPlainSocketImpl
152 JNIEXPORT void JNICALL
153 Java_gnu_java_net_VMPlainSocketImpl_listen (JNIEnv *env,
154 jclass c __attribute__((unused)),
155 jint fd, jint backlog)
159 /* listen(2) says that this call will never return EINTR */
160 /* listen is not a blocking system call */
161 if ((ret = listen (fd, backlog)) == -1)
162 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
166 /* These constants are also defined in java/net/SocketOptions.java.
167 * Except for CPNET_IP_TTL which is defined in
168 * vm/reference/gnu/java/net/VMPlainSocketImpl.java .
171 CPNET_SO_KEEPALIVE = 0x8,
172 CPNET_SO_LINGER = 0x80,
173 CPNET_SO_TIMEOUT = 0x1006,
174 CPNET_SO_BINDADDR = 0x0F,
175 CPNET_SO_SNDBUF = 0x1001,
176 CPNET_SO_RCVBUF = 0x1002,
177 CPNET_SO_REUSEADDR = 0x04,
178 CPNET_SO_BROADCAST = 0x20,
179 CPNET_SO_OOBINLINE = 0x1003,
180 CPNET_TCP_NODELAY = 0x01,
181 CPNET_IP_MULTICAST_IF = 0x10,
182 CPNET_IP_MULTICAST_IF2 = 0x1F,
183 CPNET_IP_MULTICAST_LOOP = 0x12,
185 CPNET_IP_TTL = 0x1E61
190 * Class: gnu_java_net_VMPlainSocketImpl
194 JNIEXPORT void JNICALL
195 Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env,
196 jclass c __attribute__((unused)),
197 jint fd, jint option, jint value)
199 enum java_sockopt joption = (enum java_sockopt) option;
201 int level = SOL_SOCKET;
202 const int _value = value;
203 struct linger _linger;
204 struct timeval _timeo;
205 void *optval = (void *) &_value;
206 socklen_t optlen = sizeof (int);
210 case CPNET_IP_MULTICAST_LOOP:
212 optname = IP_MULTICAST_LOOP;
215 case CPNET_SO_KEEPALIVE:
216 optname = SO_KEEPALIVE;
219 case CPNET_SO_LINGER:
225 _linger.l_linger = _value;
227 optlen = sizeof (struct linger);
230 case CPNET_SO_TIMEOUT:
231 optname = SO_RCVTIMEO;
232 _timeo.tv_sec = value / 1000;
233 _timeo.tv_usec = (value % 1000) * 1000;
235 optlen = sizeof (struct timeval);
238 case CPNET_SO_SNDBUF:
242 case CPNET_SO_RCVBUF:
246 case CPNET_SO_REUSEADDR:
247 optname = SO_REUSEADDR;
250 case CPNET_SO_BROADCAST:
251 optname = SO_BROADCAST;
254 case CPNET_SO_OOBINLINE:
255 optname = SO_OOBINLINE;
258 case CPNET_TCP_NODELAY:
260 optname = TCP_NODELAY;
273 case CPNET_SO_BINDADDR:
274 case CPNET_IP_MULTICAST_IF:
275 case CPNET_IP_MULTICAST_IF2:
276 JCL_ThrowException (env, IO_EXCEPTION, "argument not a boolean or integer option");
280 if (setsockopt (fd, level, optname, (const void *) optval, optlen) == -1)
281 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
285 * Class: gnu_java_net_VMPlainSocketImpl
289 JNIEXPORT jint JNICALL
290 Java_gnu_java_net_VMPlainSocketImpl_getOption (JNIEnv *env,
291 jclass c __attribute__((unused)),
292 jint fd, jint option)
294 enum java_sockopt joption = (enum java_sockopt) option;
296 int level = SOL_SOCKET;
298 struct linger linger;
299 struct timeval timeo;
300 void *optval = &value;
301 socklen_t optlen = sizeof (int);
305 case CPNET_IP_MULTICAST_LOOP:
307 optname = IP_MULTICAST_LOOP;
310 case CPNET_SO_KEEPALIVE:
311 optname = SO_KEEPALIVE;
314 case CPNET_SO_LINGER:
317 optlen = sizeof (struct linger);
320 case CPNET_SO_TIMEOUT:
321 optname = SO_RCVTIMEO;
323 optlen = sizeof (struct timeval);
326 case CPNET_SO_SNDBUF:
330 case CPNET_SO_RCVBUF:
334 case CPNET_SO_REUSEADDR:
335 optname = SO_REUSEADDR;
338 case CPNET_SO_BROADCAST:
339 optname = SO_BROADCAST;
342 case CPNET_SO_OOBINLINE:
343 optname = SO_OOBINLINE;
346 case CPNET_TCP_NODELAY:
348 optname = TCP_NODELAY;
361 case CPNET_SO_BINDADDR:
362 case CPNET_IP_MULTICAST_IF:
363 case CPNET_IP_MULTICAST_IF2:
364 JCL_ThrowException (env, IO_EXCEPTION, "argument not a boolean or integer option");
368 if (getsockopt (fd, level, optname, optval, &optlen) == -1)
369 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
371 /* Returns the linger value if it is enabled or -1 in case
372 * it is disabled. This is how the Java API expects it.
374 if (joption == CPNET_SO_LINGER)
375 return (linger.l_onoff) ? linger.l_linger : -1;
376 if (joption == CPNET_SO_TIMEOUT)
377 return (timeo.tv_sec * 1000) + (timeo.tv_usec / 1000);
382 JNIEXPORT void JNICALL
383 Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface (JNIEnv *env,
384 jclass c __attribute__((unused)),
386 jint optionId __attribute__((unused)),
390 cpnet_address *cpaddr = _javanet_get_ip_netaddr (env, addr);
392 if ((*env)->ExceptionOccurred (env))
395 result = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
396 (struct sockaddr *) cpaddr->data, cpaddr->len);
398 cpnet_freeAddress (env, cpaddr);
401 JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno));
404 JNIEXPORT void JNICALL
405 Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface6 (JNIEnv *env,
406 jclass c __attribute__((unused)),
408 jint optionId __attribute__((unused)),
411 #ifdef HAVE_SETSOCKOPT
414 const char *str_ifname = JCL_jstring_to_cstring (env, ifname);
417 if ((*env)->ExceptionOccurred (env))
419 JCL_free_cstring(env, ifname, str_ifname);
423 if_index = if_nametoindex(str_ifname);
426 JCL_free_cstring(env, ifname, str_ifname);
427 JCL_ThrowException (env, SOCKET_EXCEPTION, "interface does not exist");
431 result = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
432 (u_int *) &if_index, sizeof(if_index));
434 JCL_free_cstring(env, ifname, str_ifname);
437 JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno));
440 JCL_ThrowException (env, "java/lang/InternalError",
441 "IPv6 support not available");
442 #endif /* HAVE_INET6 */
445 JCL_ThrowException (env, "java/lang/InternalError",
446 "socket options not supported");
447 #endif /* HAVE_SETSOCKOPT */
450 JNIEXPORT jobject JNICALL
451 Java_gnu_java_net_VMPlainSocketImpl_getMulticastInterface (JNIEnv *env,
452 jclass c __attribute__((unused)),
454 jint optionId __attribute__((unused)))
457 cpnet_address *cpaddr;
458 int result = cpnet_getMulticastIF (env, fd, &cpaddr);
460 if (result != CPNATIVE_OK)
462 JCL_ThrowException (env, SOCKET_EXCEPTION,
463 cpnative_getErrorString (result));
467 obj = _javanet_create_inetaddress (env, cpaddr);
468 cpnet_freeAddress (env, cpaddr);
475 * Class: gnu_java_net_VMPlainSocketImpl
476 * Method: shutdownInput
479 JNIEXPORT void JNICALL
480 Java_gnu_java_net_VMPlainSocketImpl_shutdownInput (JNIEnv *env,
481 jclass c __attribute__((unused)),
484 if (shutdown (fd, SHUT_RD) == -1)
485 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
489 * Class: gnu_java_net_VMPlainSocketImpl
490 * Method: shutdownOutput
493 JNIEXPORT void JNICALL
494 Java_gnu_java_net_VMPlainSocketImpl_shutdownOutput (JNIEnv *env,
495 jclass c __attribute__((unused)),
498 if (shutdown (fd, SHUT_WR) == -1)
499 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
504 * Class: gnu_java_net_VMPlainSocketImpl
505 * Method: sendUrgentData
508 JNIEXPORT void JNICALL
509 Java_gnu_java_net_VMPlainSocketImpl_sendUrgentData (JNIEnv *env,
510 jclass c __attribute__((unused)),
513 const char x = (char) data;
515 if (send (fd, &x, 1, MSG_OOB) == -1)
516 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
521 * Class: gnu_java_net_VMPlainSocketImpl
525 JNIEXPORT void JNICALL
526 Java_gnu_java_net_VMPlainSocketImpl_join (JNIEnv *env,
527 jclass clazz __attribute__((unused)),
528 jint fd, jbyteArray addr)
530 #ifdef HAVE_SETSOCKOPT
531 struct ip_mreq maddr;
534 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
535 if (addr_elems == NULL)
538 maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
539 maddr.imr_interface.s_addr = INADDR_ANY;
541 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
543 if (-1 == setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
544 &maddr, sizeof (struct ip_mreq)))
545 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
549 JCL_ThrowException (env, "java/lang/InternalError",
550 "socket options not supported");
551 #endif /* HAVE_SETSOCKOPT */
556 * Class: gnu_java_net_VMPlainSocketImpl
560 JNIEXPORT void JNICALL
561 Java_gnu_java_net_VMPlainSocketImpl_join6 (JNIEnv *env,
562 jclass clazz __attribute__((unused)),
563 jint fd, jbyteArray addr)
565 #ifdef HAVE_SETSOCKOPT
567 struct ipv6_mreq maddr;
570 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
571 if (addr_elems == NULL)
574 memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
575 maddr.ipv6mr_interface = 0;
577 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
579 if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
580 &maddr, sizeof (struct ipv6_mreq)))
581 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
585 JCL_ThrowException (env, "java/lang/InternalError",
586 "IPv6 support not available");
587 #endif /* HAVE_INET6 */
591 JCL_ThrowException (env, "java/lang/InternalError",
592 "socket options not supported");
593 #endif /* HAVE_SETSOCKOPT */
597 * Class: gnu_java_net_VMPlainSocketImpl
601 JNIEXPORT void JNICALL
602 Java_gnu_java_net_VMPlainSocketImpl_leave (JNIEnv *env,
603 jclass c __attribute__((unused)),
604 jint fd, jbyteArray addr)
606 #ifdef HAVE_SETSOCKOPT
607 struct ip_mreq maddr;
610 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
611 if (addr_elems == NULL)
614 maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
615 maddr.imr_interface.s_addr = INADDR_ANY;
617 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
619 if (-1 == setsockopt (fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
620 &maddr, sizeof (struct ip_mreq)))
621 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
625 JCL_ThrowException (env, "java/lang/InternalError",
626 "socket options not supported");
627 #endif /* HAVE_SETSOCKOPT */
631 * Class: gnu_java_net_VMPlainSocketImpl
635 JNIEXPORT void JNICALL
636 Java_gnu_java_net_VMPlainSocketImpl_leave6 (JNIEnv *env,
637 jclass c __attribute__((unused)),
638 jint fd, jbyteArray addr)
640 #ifdef HAVE_SETSOCKOPT
642 struct ipv6_mreq maddr;
645 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
646 if (addr_elems == NULL)
649 memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
650 maddr.ipv6mr_interface = 0;
652 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
654 if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
655 &maddr, sizeof (struct ipv6_mreq)))
656 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
660 JCL_ThrowException (env, "java/lang/InternalError",
661 "IPv6 support not available");
662 #endif /* HAVE_INET6 */
666 JCL_ThrowException (env, "java/lang/InternalError",
667 "socket options not supported");
668 #endif /* HAVE_SETSOCKOPT */
671 static uint32_t getif_address (JNIEnv *env, const char *ifname);
672 static int getif_index (JNIEnv *env, const char *ifname);
675 * Class: gnu_java_net_VMPlainSocketImpl
677 * Signature: (I[BILjava/lang/String;)V
679 JNIEXPORT void JNICALL
680 Java_gnu_java_net_VMPlainSocketImpl_joinGroup (JNIEnv *env,
681 jclass c __attribute__((unused)),
682 jint fd, jbyteArray addr,
685 #ifdef HAVE_SETSOCKOPT
686 struct ip_mreq maddr;
688 const char *str_ifname;
692 str_ifname = JCL_jstring_to_cstring(env, ifname);
693 maddr.imr_interface.s_addr = getif_address (env, str_ifname);
694 JCL_free_cstring(env, ifname, str_ifname);
696 if ((*env)->ExceptionCheck (env))
700 maddr.imr_interface.s_addr = INADDR_ANY;
702 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
703 if (addr_elems == NULL)
706 maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
708 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
710 if (-1 == setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
711 &maddr, sizeof (struct ip_mreq)))
712 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
718 JCL_ThrowException (env, "java/lang/InternalError",
719 "socket options not supported");
720 #endif /* HAVE_SETSOCKOPT */
724 * Class: gnu_java_net_VMPlainSocketImpl
726 * Signature: (I[BILjava/lang/String;)V
728 JNIEXPORT void JNICALL
729 Java_gnu_java_net_VMPlainSocketImpl_joinGroup6 (JNIEnv *env,
730 jclass c __attribute__((unused)),
731 jint fd, jbyteArray addr,
734 #ifdef HAVE_SETSOCKOPT
736 struct ipv6_mreq maddr;
738 const char *str_ifname;
742 str_ifname = JCL_jstring_to_cstring(env, ifname);
743 maddr.ipv6mr_interface = getif_index (env, str_ifname);
744 JCL_free_cstring(env, ifname, str_ifname);
746 if ((*env)->ExceptionCheck (env))
750 maddr.ipv6mr_interface = 0;
752 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
753 if (addr_elems == NULL)
756 memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
758 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
760 if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
761 &maddr, sizeof (struct ipv6_mreq)))
762 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
766 JCL_ThrowException (env, "java/lang/InternalError",
767 "IPv6 support not available");
768 #endif /* HAVE_INET6 */
772 JCL_ThrowException (env, "java/lang/InternalError",
773 "socket options not supported");
774 #endif /* HAVE_SETSOCKOPT */
778 * Class: gnu_java_net_VMPlainSocketImpl
780 * Signature: (I[BILjava/lang/String;)V
782 JNIEXPORT void JNICALL
783 Java_gnu_java_net_VMPlainSocketImpl_leaveGroup (JNIEnv *env,
784 jclass c __attribute__((unused)),
785 jint fd, jbyteArray addr,
788 #ifdef HAVE_SETSOCKOPT
789 struct ip_mreq maddr;
791 const char *str_ifname;
795 str_ifname = JCL_jstring_to_cstring(env, ifname);
796 maddr.imr_interface.s_addr = getif_address (env, str_ifname);
797 JCL_free_cstring(env, ifname, str_ifname);
799 if ((*env)->ExceptionCheck (env))
803 maddr.imr_interface.s_addr = INADDR_ANY;
805 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
806 if (addr_elems == NULL)
809 maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
811 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
813 if (-1 == setsockopt (fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
814 &maddr, sizeof (struct ip_mreq)))
815 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
820 JCL_ThrowException (env, "java/lang/InternalError",
821 "socket options not supported");
822 #endif /* HAVE_SETSOCKOPT */
826 * Class: gnu_java_net_VMPlainSocketImpl
827 * Method: leaveGroup6
828 * Signature: (I[BILjava/lang/String;)V
830 JNIEXPORT void JNICALL
831 Java_gnu_java_net_VMPlainSocketImpl_leaveGroup6 (JNIEnv *env,
832 jclass c __attribute__((unused)),
833 jint fd, jbyteArray addr,
836 #ifdef HAVE_SETSOCKOPT
838 struct ipv6_mreq maddr;
840 const char *str_ifname;
844 str_ifname = JCL_jstring_to_cstring(env, ifname);
845 maddr.ipv6mr_interface = getif_index (env, str_ifname);
846 JCL_free_cstring(env, ifname, str_ifname);
848 if ((*env)->ExceptionCheck (env))
852 maddr.ipv6mr_interface = 0;
854 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
855 if (addr_elems == NULL)
858 memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
860 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
862 if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
863 &maddr, sizeof (struct ipv6_mreq)))
864 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
868 JCL_ThrowException (env, "java/lang/InternalError",
869 "IPv6 support not available");
870 #endif /* HAVE_INET6 */
874 JCL_ThrowException (env, "java/lang/InternalError",
875 "socket options not supported");
876 #endif /* HAVE_SETSOCKOPT */
880 getif_address (JNIEnv *env, const char *ifname)
882 #if defined (HAVE_IFADDRS_H) && defined (HAVE_GETIFADDRS)
883 struct ifaddrs *ifaddrs, *i;
887 if (getifaddrs (&ifaddrs) == -1)
889 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
893 for (i = ifaddrs; i != NULL; i = i->ifa_next)
895 if (strcmp (ifname, i->ifa_name) == 0)
897 /* Matched the name; see if there is an IPv4 address. */
898 if (i->ifa_addr->sa_family == AF_INET)
901 addr = ((struct sockaddr_in *) i->ifa_addr)->sin_addr.s_addr;
908 JCL_ThrowException (env, SOCKET_EXCEPTION, "interface has no IPv4 address");
910 freeifaddrs (ifaddrs);
915 JCL_ThrowException (env, "java/lang/InternalError",
916 "getifaddrs not available");
918 #endif /* HAVE_IFADDRS_H && HAVE_GETIFADDRS */
922 getif_index (JNIEnv *env, const char *ifname)
924 #if defined (HAVE_IFADDRS_H) && defined (HAVE_GETIFADDRS)
925 struct ifaddrs *ifaddrs, *i;
926 char *lastname = NULL;
930 if (getifaddrs (&ifaddrs) == -1)
932 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
936 lastname = ifaddrs->ifa_name;
937 for (i = ifaddrs; i != NULL; i = i->ifa_next)
939 if (strcmp (lastname, ifaddrs->ifa_name) != 0)
941 lastname = ifaddrs->ifa_name;
944 if (strcmp (ifname, ifaddrs->ifa_name) == 0)
952 JCL_ThrowException (env, SOCKET_EXCEPTION,
953 "no interface with that name");
955 freeifaddrs (ifaddrs);
960 JCL_ThrowException (env, "java/lang/InternalError",
961 "getifaddrs not available");
963 #endif /* HAVE_GETIFADDRS */