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>
71 #include "gnu_java_net_VMPlainSocketImpl.h"
73 #define THROW_NO_NETWORK(env) JCL_ThrowException (env, "java/lang/InternalError", "this platform not configured for network support")
74 #define THROW_NO_IPV6(env) JCL_ThrowException (env, "java/lang/InternalError", "IPv6 support not available")
77 * Class: gnu_java_net_VMPlainSocketImpl
81 JNIEXPORT void JNICALL
82 Java_gnu_java_net_VMPlainSocketImpl_bind (JNIEnv *env,
83 jclass clazz __attribute__((unused)),
84 jint fd, jbyteArray addr, jint port)
86 struct sockaddr_in sockaddr;
91 elems = (*env)->GetByteArrayElements (env, addr, NULL);
93 memset(&sockaddr, 0, sizeof (struct sockaddr_in));
94 sockaddr.sin_family = AF_INET;
95 sockaddr.sin_port = htons (port);
96 /* addr is already in network byte order. */
98 sockaddr.sin_addr.s_addr = *((uint32_t *) elems);
100 sockaddr.sin_addr.s_addr = INADDR_ANY;
102 /* bind(2) from BSD says bind will never return EINTR */
103 /* bind is not a blocking system call */
104 ret = bind (fd, (struct sockaddr *) &sockaddr, sizeof (struct sockaddr_in));
107 (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT);
110 JCL_ThrowException (env, BIND_EXCEPTION, strerror (errno));
112 cpio_closeOnExec(ret);
117 * Class: gnu_java_net_VMPlainSocketImpl
121 JNIEXPORT void JNICALL
122 Java_gnu_java_net_VMPlainSocketImpl_bind6 (JNIEnv *env,
123 jclass c __attribute__((unused)),
124 jint fd, jbyteArray addr, jint port)
127 struct sockaddr_in6 sockaddr;
131 elems = (*env)->GetByteArrayElements (env, addr, NULL);
133 memset (&sockaddr, 0, sizeof (struct sockaddr_in6));
134 sockaddr.sin6_family = AF_INET6;
135 sockaddr.sin6_port = htons (port);
136 memcpy (&sockaddr.sin6_addr.s6_addr, elems, 16);
138 /* bind(2) from BSD says bind will never return EINTR */
139 /* bind is not a blocking system call */
140 ret = bind (fd, (struct sockaddr *) &sockaddr,
141 sizeof (struct sockaddr_in6));
143 (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT);
146 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
154 * Class: gnu_java_net_VMPlainSocketImpl
158 JNIEXPORT void JNICALL
159 Java_gnu_java_net_VMPlainSocketImpl_listen (JNIEnv *env,
160 jclass c __attribute__((unused)),
161 jint fd, jint backlog)
165 /* listen(2) says that this call will never return EINTR */
166 /* listen is not a blocking system call */
167 if ((ret = listen (fd, backlog)) == -1)
168 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
172 /* These constants are also defined in java/net/SocketOptions.java.
173 * Except for CPNET_IP_TTL which is defined in
174 * vm/reference/gnu/java/net/VMPlainSocketImpl.java .
177 CPNET_SO_KEEPALIVE = 0x8,
178 CPNET_SO_LINGER = 0x80,
179 CPNET_SO_TIMEOUT = 0x1006,
180 CPNET_SO_BINDADDR = 0x0F,
181 CPNET_SO_SNDBUF = 0x1001,
182 CPNET_SO_RCVBUF = 0x1002,
183 CPNET_SO_REUSEADDR = 0x04,
184 CPNET_SO_BROADCAST = 0x20,
185 CPNET_SO_OOBINLINE = 0x1003,
186 CPNET_TCP_NODELAY = 0x01,
187 CPNET_IP_MULTICAST_IF = 0x10,
188 CPNET_IP_MULTICAST_IF2 = 0x1F,
189 CPNET_IP_MULTICAST_LOOP = 0x12,
191 CPNET_IP_TTL = 0x1E61
196 * Class: gnu_java_net_VMPlainSocketImpl
200 JNIEXPORT void JNICALL
201 Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env,
202 jclass c __attribute__((unused)),
203 jint fd, jint option, jint value)
205 enum java_sockopt joption = (enum java_sockopt) option;
207 int level = SOL_SOCKET;
208 const int _value = value;
209 struct linger _linger;
210 struct timeval _timeo;
211 void *optval = (void *) &_value;
212 socklen_t optlen = sizeof (int);
216 case CPNET_IP_MULTICAST_LOOP:
218 optname = IP_MULTICAST_LOOP;
221 case CPNET_SO_KEEPALIVE:
222 optname = SO_KEEPALIVE;
225 case CPNET_SO_LINGER:
231 _linger.l_linger = _value;
233 optlen = sizeof (struct linger);
236 case CPNET_SO_TIMEOUT:
237 optname = SO_RCVTIMEO;
238 _timeo.tv_sec = value / 1000;
239 _timeo.tv_usec = (value % 1000) * 1000;
241 optlen = sizeof (struct timeval);
244 case CPNET_SO_SNDBUF:
248 case CPNET_SO_RCVBUF:
252 case CPNET_SO_REUSEADDR:
253 optname = SO_REUSEADDR;
256 case CPNET_SO_BROADCAST:
257 optname = SO_BROADCAST;
260 case CPNET_SO_OOBINLINE:
261 optname = SO_OOBINLINE;
264 case CPNET_TCP_NODELAY:
266 optname = TCP_NODELAY;
279 case CPNET_SO_BINDADDR:
280 case CPNET_IP_MULTICAST_IF:
281 case CPNET_IP_MULTICAST_IF2:
282 JCL_ThrowException (env, IO_EXCEPTION, "argument not a boolean or integer option");
286 if (setsockopt (fd, level, optname, (const void *) optval, optlen) == -1)
287 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
291 * Class: gnu_java_net_VMPlainSocketImpl
295 JNIEXPORT jint JNICALL
296 Java_gnu_java_net_VMPlainSocketImpl_getOption (JNIEnv *env,
297 jclass c __attribute__((unused)),
298 jint fd, jint option)
300 enum java_sockopt joption = (enum java_sockopt) option;
302 int level = SOL_SOCKET;
304 struct linger linger;
305 struct timeval timeo;
306 void *optval = &value;
307 socklen_t optlen = sizeof (int);
311 case CPNET_IP_MULTICAST_LOOP:
313 optname = IP_MULTICAST_LOOP;
316 case CPNET_SO_KEEPALIVE:
317 optname = SO_KEEPALIVE;
320 case CPNET_SO_LINGER:
323 optlen = sizeof (struct linger);
326 case CPNET_SO_TIMEOUT:
327 optname = SO_RCVTIMEO;
329 optlen = sizeof (struct timeval);
332 case CPNET_SO_SNDBUF:
336 case CPNET_SO_RCVBUF:
340 case CPNET_SO_REUSEADDR:
341 optname = SO_REUSEADDR;
344 case CPNET_SO_BROADCAST:
345 optname = SO_BROADCAST;
348 case CPNET_SO_OOBINLINE:
349 optname = SO_OOBINLINE;
352 case CPNET_TCP_NODELAY:
354 optname = TCP_NODELAY;
367 case CPNET_SO_BINDADDR:
368 case CPNET_IP_MULTICAST_IF:
369 case CPNET_IP_MULTICAST_IF2:
370 JCL_ThrowException (env, IO_EXCEPTION, "argument not a boolean or integer option");
374 if (getsockopt (fd, level, optname, optval, &optlen) == -1)
375 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
377 /* Returns the linger value if it is enabled or -1 in case
378 * it is disabled. This is how the Java API expects it.
380 if (joption == CPNET_SO_LINGER)
381 return (linger.l_onoff) ? linger.l_linger : -1;
382 if (joption == CPNET_SO_TIMEOUT)
383 return (timeo.tv_sec * 1000) + (timeo.tv_usec / 1000);
388 JNIEXPORT void JNICALL
389 Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface (JNIEnv *env,
390 jclass c __attribute__((unused)),
392 jint optionId __attribute__((unused)),
396 cpnet_address *cpaddr = _javanet_get_ip_netaddr (env, addr);
398 if ((*env)->ExceptionOccurred (env))
401 result = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
402 (struct sockaddr *) cpaddr->data, cpaddr->len);
404 cpnet_freeAddress (env, cpaddr);
407 JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno));
410 JNIEXPORT void JNICALL
411 Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface6 (JNIEnv *env,
412 jclass c __attribute__((unused)),
414 jint optionId __attribute__((unused)),
417 #ifdef HAVE_SETSOCKOPT
420 const char *str_ifname = JCL_jstring_to_cstring (env, ifname);
421 unsigned int if_index;
423 if ((*env)->ExceptionOccurred (env))
425 JCL_free_cstring(env, ifname, str_ifname);
429 if_index = if_nametoindex(str_ifname);
432 JCL_free_cstring(env, ifname, str_ifname);
433 JCL_ThrowException (env, SOCKET_EXCEPTION, "interface does not exist");
437 result = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
438 (unsigned int *) &if_index, sizeof(if_index));
440 JCL_free_cstring(env, ifname, str_ifname);
443 JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno));
446 JCL_ThrowException (env, "java/lang/InternalError",
447 "IPv6 support not available");
448 #endif /* HAVE_INET6 */
452 #endif /* HAVE_SETSOCKOPT */
455 JNIEXPORT jobject JNICALL
456 Java_gnu_java_net_VMPlainSocketImpl_getMulticastInterface (JNIEnv *env,
457 jclass c __attribute__((unused)),
459 jint optionId __attribute__((unused)))
462 cpnet_address *cpaddr;
463 int result = cpnet_getMulticastIF (env, fd, &cpaddr);
465 if (result != CPNATIVE_OK)
467 JCL_ThrowException (env, SOCKET_EXCEPTION,
468 cpnative_getErrorString (result));
472 obj = _javanet_create_inetaddress (env, cpaddr);
473 cpnet_freeAddress (env, cpaddr);
480 * Class: gnu_java_net_VMPlainSocketImpl
481 * Method: shutdownInput
484 JNIEXPORT void JNICALL
485 Java_gnu_java_net_VMPlainSocketImpl_shutdownInput (JNIEnv *env,
486 jclass c __attribute__((unused)),
489 if (shutdown (fd, SHUT_RD) == -1)
490 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
494 * Class: gnu_java_net_VMPlainSocketImpl
495 * Method: shutdownOutput
498 JNIEXPORT void JNICALL
499 Java_gnu_java_net_VMPlainSocketImpl_shutdownOutput (JNIEnv *env,
500 jclass c __attribute__((unused)),
503 if (shutdown (fd, SHUT_WR) == -1)
504 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
509 * Class: gnu_java_net_VMPlainSocketImpl
510 * Method: sendUrgentData
513 JNIEXPORT void JNICALL
514 Java_gnu_java_net_VMPlainSocketImpl_sendUrgentData (JNIEnv *env,
515 jclass c __attribute__((unused)),
518 const char x = (char) data;
520 if (send (fd, &x, 1, MSG_OOB) == -1)
521 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
526 * Class: gnu_java_net_VMPlainSocketImpl
530 JNIEXPORT void JNICALL
531 Java_gnu_java_net_VMPlainSocketImpl_join (JNIEnv *env,
532 jclass clazz __attribute__((unused)),
533 jint fd, jbyteArray addr)
535 #ifdef HAVE_SETSOCKOPT
536 struct ip_mreq maddr;
539 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
540 if (addr_elems == NULL)
543 maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
544 maddr.imr_interface.s_addr = INADDR_ANY;
546 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
548 if (-1 == setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
549 &maddr, sizeof (struct ip_mreq)))
550 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
554 JCL_ThrowException (env, "java/lang/InternalError",
555 "socket options not supported");
556 #endif /* HAVE_SETSOCKOPT */
561 * Class: gnu_java_net_VMPlainSocketImpl
565 JNIEXPORT void JNICALL
566 Java_gnu_java_net_VMPlainSocketImpl_join6 (JNIEnv *env,
567 jclass clazz __attribute__((unused)),
568 jint fd, jbyteArray addr)
570 #ifdef HAVE_SETSOCKOPT
572 struct ipv6_mreq maddr;
575 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
576 if (addr_elems == NULL)
579 memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
580 maddr.ipv6mr_interface = 0;
582 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
584 if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
585 &maddr, sizeof (struct ipv6_mreq)))
586 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
591 #endif /* HAVE_INET6 */
595 JCL_ThrowException (env, "java/lang/InternalError",
596 "socket options not supported");
597 #endif /* HAVE_SETSOCKOPT */
601 * Class: gnu_java_net_VMPlainSocketImpl
605 JNIEXPORT void JNICALL
606 Java_gnu_java_net_VMPlainSocketImpl_leave (JNIEnv *env,
607 jclass c __attribute__((unused)),
608 jint fd, jbyteArray addr)
610 #ifdef HAVE_SETSOCKOPT
611 struct ip_mreq maddr;
614 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
615 if (addr_elems == NULL)
618 maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
619 maddr.imr_interface.s_addr = INADDR_ANY;
621 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
623 if (-1 == setsockopt (fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
624 &maddr, sizeof (struct ip_mreq)))
625 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
629 JCL_ThrowException (env, "java/lang/InternalError",
630 "socket options not supported");
631 #endif /* HAVE_SETSOCKOPT */
635 * Class: gnu_java_net_VMPlainSocketImpl
639 JNIEXPORT void JNICALL
640 Java_gnu_java_net_VMPlainSocketImpl_leave6 (JNIEnv *env,
641 jclass c __attribute__((unused)),
642 jint fd, jbyteArray addr)
644 #ifdef HAVE_SETSOCKOPT
646 struct ipv6_mreq maddr;
649 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
650 if (addr_elems == NULL)
653 memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
654 maddr.ipv6mr_interface = 0;
656 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
658 if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
659 &maddr, sizeof (struct ipv6_mreq)))
660 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
665 #endif /* HAVE_INET6 */
669 JCL_ThrowException (env, "java/lang/InternalError",
670 "socket options not supported");
671 #endif /* HAVE_SETSOCKOPT */
674 static uint32_t getif_address (JNIEnv *env, const char *ifname);
675 static int getif_index (JNIEnv *env, const char *ifname);
678 * Class: gnu_java_net_VMPlainSocketImpl
680 * Signature: (I[BILjava/lang/String;)V
682 JNIEXPORT void JNICALL
683 Java_gnu_java_net_VMPlainSocketImpl_joinGroup (JNIEnv *env,
684 jclass c __attribute__((unused)),
685 jint fd, jbyteArray addr,
688 #ifdef HAVE_SETSOCKOPT
689 struct ip_mreq maddr;
691 const char *str_ifname;
695 str_ifname = JCL_jstring_to_cstring(env, ifname);
696 maddr.imr_interface.s_addr = getif_address (env, str_ifname);
697 JCL_free_cstring(env, ifname, str_ifname);
699 if ((*env)->ExceptionCheck (env))
703 maddr.imr_interface.s_addr = INADDR_ANY;
705 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
706 if (addr_elems == NULL)
709 maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
711 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
713 if (-1 == setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
714 &maddr, sizeof (struct ip_mreq)))
715 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
721 JCL_ThrowException (env, "java/lang/InternalError",
722 "socket options not supported");
723 #endif /* HAVE_SETSOCKOPT */
727 * Class: gnu_java_net_VMPlainSocketImpl
729 * Signature: (I[BILjava/lang/String;)V
731 JNIEXPORT void JNICALL
732 Java_gnu_java_net_VMPlainSocketImpl_joinGroup6 (JNIEnv *env,
733 jclass c __attribute__((unused)),
734 jint fd, jbyteArray addr,
737 #ifdef HAVE_SETSOCKOPT
739 struct ipv6_mreq maddr;
741 const char *str_ifname;
745 str_ifname = JCL_jstring_to_cstring(env, ifname);
746 maddr.ipv6mr_interface = getif_index (env, str_ifname);
747 JCL_free_cstring(env, ifname, str_ifname);
749 if ((*env)->ExceptionCheck (env))
753 maddr.ipv6mr_interface = 0;
755 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
756 if (addr_elems == NULL)
759 memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
761 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
763 if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
764 &maddr, sizeof (struct ipv6_mreq)))
765 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
770 #endif /* HAVE_INET6 */
774 JCL_ThrowException (env, "java/lang/InternalError",
775 "socket options not supported");
776 #endif /* HAVE_SETSOCKOPT */
780 * Class: gnu_java_net_VMPlainSocketImpl
782 * Signature: (I[BILjava/lang/String;)V
784 JNIEXPORT void JNICALL
785 Java_gnu_java_net_VMPlainSocketImpl_leaveGroup (JNIEnv *env,
786 jclass c __attribute__((unused)),
787 jint fd, jbyteArray addr,
790 #ifdef HAVE_SETSOCKOPT
791 struct ip_mreq maddr;
793 const char *str_ifname;
797 str_ifname = JCL_jstring_to_cstring(env, ifname);
798 maddr.imr_interface.s_addr = getif_address (env, str_ifname);
799 JCL_free_cstring(env, ifname, str_ifname);
801 if ((*env)->ExceptionCheck (env))
805 maddr.imr_interface.s_addr = INADDR_ANY;
807 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
808 if (addr_elems == NULL)
811 maddr.imr_multiaddr.s_addr = * ((uint32_t *) addr_elems);
813 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
815 if (-1 == setsockopt (fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
816 &maddr, sizeof (struct ip_mreq)))
817 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
822 JCL_ThrowException (env, "java/lang/InternalError",
823 "socket options not supported");
824 #endif /* HAVE_SETSOCKOPT */
828 * Class: gnu_java_net_VMPlainSocketImpl
829 * Method: leaveGroup6
830 * Signature: (I[BILjava/lang/String;)V
832 JNIEXPORT void JNICALL
833 Java_gnu_java_net_VMPlainSocketImpl_leaveGroup6 (JNIEnv *env,
834 jclass c __attribute__((unused)),
835 jint fd, jbyteArray addr,
838 #ifdef HAVE_SETSOCKOPT
840 struct ipv6_mreq maddr;
842 const char *str_ifname;
846 str_ifname = JCL_jstring_to_cstring(env, ifname);
847 maddr.ipv6mr_interface = getif_index (env, str_ifname);
848 JCL_free_cstring(env, ifname, str_ifname);
850 if ((*env)->ExceptionCheck (env))
854 maddr.ipv6mr_interface = 0;
856 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
857 if (addr_elems == NULL)
860 memcpy (&(maddr.ipv6mr_multiaddr.s6_addr), addr_elems, 16);
862 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
864 if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
865 &maddr, sizeof (struct ipv6_mreq)))
866 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
871 #endif /* HAVE_INET6 */
875 JCL_ThrowException (env, "java/lang/InternalError",
876 "socket options not supported");
877 #endif /* HAVE_SETSOCKOPT */
881 getif_address (JNIEnv *env, const char *ifname)
883 #if defined (HAVE_IFADDRS_H) && defined (HAVE_GETIFADDRS)
884 struct ifaddrs *ifaddrs, *i;
888 if (getifaddrs (&ifaddrs) == -1)
890 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
894 for (i = ifaddrs; i != NULL; i = i->ifa_next)
896 if (strcmp (ifname, i->ifa_name) == 0)
898 /* Matched the name; see if there is an IPv4 address. */
899 if (i->ifa_addr->sa_family == AF_INET)
902 addr = ((struct sockaddr_in *) i->ifa_addr)->sin_addr.s_addr;
909 JCL_ThrowException (env, SOCKET_EXCEPTION, "interface has no IPv4 address");
911 freeifaddrs (ifaddrs);
916 JCL_ThrowException (env, "java/lang/InternalError",
917 "getifaddrs not available");
919 #endif /* HAVE_IFADDRS_H && HAVE_GETIFADDRS */
923 getif_index (JNIEnv *env, const char *ifname)
925 #if defined (HAVE_IFADDRS_H) && defined (HAVE_GETIFADDRS)
926 struct ifaddrs *ifaddrs, *i;
927 char *lastname = NULL;
931 if (getifaddrs (&ifaddrs) == -1)
933 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
937 lastname = ifaddrs->ifa_name;
938 for (i = ifaddrs; i != NULL; i = i->ifa_next)
940 if (strcmp (lastname, ifaddrs->ifa_name) != 0)
942 lastname = ifaddrs->ifa_name;
945 if (strcmp (ifname, ifaddrs->ifa_name) == 0)
953 JCL_ThrowException (env, SOCKET_EXCEPTION,
954 "no interface with that name");
956 freeifaddrs (ifaddrs);
961 JCL_ThrowException (env, "java/lang/InternalError",
962 "getifaddrs not available");
964 #endif /* HAVE_GETIFADDRS */