summaryrefslogtreecommitdiff
path: root/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c
diff options
context:
space:
mode:
Diffstat (limited to 'native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c')
-rw-r--r--native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c170
1 files changed, 149 insertions, 21 deletions
diff --git a/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c b/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c
index 6ebb64fa5..53ef04d47 100644
--- a/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c
+++ b/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c
@@ -40,6 +40,8 @@ exception statement from your version. */
#include <config.h>
#endif /* HAVE_CONFIG_H */
+#include <config-int.h>
+
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -47,6 +49,7 @@ exception statement from your version. */
#include <ifaddrs.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
+#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
@@ -56,16 +59,14 @@ exception statement from your version. */
#include <jni.h>
#include <jcl.h>
-/* #include "javanet.h" */
+#include "cpnative.h"
+#include "cpnet.h"
+#include "cpio.h"
+#include "javanet.h"
#include "gnu_java_net_VMPlainSocketImpl.h"
-#define IO_EXCEPTION "java/io/IOException"
-#define SOCKET_EXCEPTION "java/net/SocketException"
-#define BIND_EXCEPTION "java/net/BindException"
-
-#define THROW_NO_NETWORK(env) JCL_ThrowException (env, "java/lang/InternalError", "this platform not configured for network support")
-
+#define THROW_NO_NETWORK(env) JCL_ThrowException (env, "java/lang/InternalError", "this platform not configured for network support")
/*
* Class: gnu_java_net_VMPlainSocketImpl
@@ -102,6 +103,8 @@ Java_gnu_java_net_VMPlainSocketImpl_bind (JNIEnv *env,
if (-1 == ret)
JCL_ThrowException (env, BIND_EXCEPTION, strerror (errno));
+
+ cpio_closeOnExec(ret);
}
@@ -158,7 +161,10 @@ Java_gnu_java_net_VMPlainSocketImpl_listen (JNIEnv *env,
}
-/* These constants are also defined in java/net/SocketOptions.java */
+/* These constants are also defined in java/net/SocketOptions.java.
+ * Except for CPNET_IP_TTL which is defined in
+ * vm/reference/gnu/java/net/VMPlainSocketImpl.java .
+ */
enum java_sockopt {
CPNET_SO_KEEPALIVE = 0x8,
CPNET_SO_LINGER = 0x80,
@@ -173,7 +179,8 @@ enum java_sockopt {
CPNET_IP_MULTICAST_IF = 0x10,
CPNET_IP_MULTICAST_IF2 = 0x1F,
CPNET_IP_MULTICAST_LOOP = 0x12,
- CPNET_IP_TOS = 0x03
+ CPNET_IP_TOS = 0x03,
+ CPNET_IP_TTL = 0x1E61
};
@@ -195,7 +202,7 @@ Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env,
struct timeval _timeo;
void *optval = (void *) &_value;
socklen_t optlen = sizeof (int);
-
+
switch (joption)
{
case CPNET_IP_MULTICAST_LOOP:
@@ -209,7 +216,7 @@ Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env,
case CPNET_SO_LINGER:
optname = SO_LINGER;
- if (_value == 0)
+ if (_value == -1)
_linger.l_onoff = 0;
else
_linger.l_onoff = 1;
@@ -256,6 +263,11 @@ Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env,
optname = IP_TOS;
break;
+ case CPNET_IP_TTL:
+ level = IPPROTO_IP;
+ optname = IP_TTL;
+ break;
+
case CPNET_SO_BINDADDR:
case CPNET_IP_MULTICAST_IF:
case CPNET_IP_MULTICAST_IF2:
@@ -339,6 +351,11 @@ Java_gnu_java_net_VMPlainSocketImpl_getOption (JNIEnv *env,
optname = IP_TOS;
break;
+ case CPNET_IP_TTL:
+ level = IPPROTO_IP;
+ optname = IP_TTL;
+ break;
+
case CPNET_SO_BINDADDR:
case CPNET_IP_MULTICAST_IF:
case CPNET_IP_MULTICAST_IF2:
@@ -349,14 +366,108 @@ Java_gnu_java_net_VMPlainSocketImpl_getOption (JNIEnv *env,
if (getsockopt (fd, level, optname, optval, &optlen) == -1)
JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ /* Returns the linger value if it is enabled or -1 in case
+ * it is disabled. This is how the Java API expects it.
+ */
if (joption == CPNET_SO_LINGER)
- return linger.l_linger;
+ return (linger.l_onoff) ? linger.l_linger : -1;
if (joption == CPNET_SO_TIMEOUT)
return (timeo.tv_sec * 1000) + (timeo.tv_usec / 1000);
return value;
}
+JNIEXPORT void JNICALL
+Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface (JNIEnv *env,
+ jclass c __attribute__((unused)),
+ jint fd,
+ jint optionId __attribute__((unused)),
+ jobject addr)
+{
+ int result;
+ cpnet_address *cpaddr = _javanet_get_ip_netaddr (env, addr);
+
+ if ((*env)->ExceptionOccurred (env))
+ return;
+
+ result = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
+ (struct sockaddr *) cpaddr->data, cpaddr->len);
+
+ cpnet_freeAddress (env, cpaddr);
+
+ if (result == -1)
+ JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno));
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface6 (JNIEnv *env,
+ jclass c __attribute__((unused)),
+ jint fd,
+ jint optionId __attribute__((unused)),
+ jstring ifname)
+{
+#ifdef HAVE_SETSOCKOPT
+#ifdef HAVE_INET6
+ int result;
+ const char *str_ifname = JCL_jstring_to_cstring (env, ifname);
+ u_int if_index;
+
+ if ((*env)->ExceptionOccurred (env))
+ {
+ JCL_free_cstring(env, ifname, str_ifname);
+ return;
+ }
+
+ if_index = if_nametoindex(str_ifname);
+ if (!if_index)
+ {
+ JCL_free_cstring(env, ifname, str_ifname);
+ JCL_ThrowException (env, SOCKET_EXCEPTION, "interface does not exist");
+ return;
+ }
+
+ result = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ (u_int *) &if_index, sizeof(if_index));
+
+ JCL_free_cstring(env, ifname, str_ifname);
+
+ if (result == -1)
+ JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno));
+#else
+ (void) fd;
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "IPv6 support not available");
+#endif /* HAVE_INET6 */
+#else
+ (void) fd;
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "socket options not supported");
+#endif /* HAVE_SETSOCKOPT */
+}
+
+JNIEXPORT jobject JNICALL
+Java_gnu_java_net_VMPlainSocketImpl_getMulticastInterface (JNIEnv *env,
+ jclass c __attribute__((unused)),
+ jint fd,
+ jint optionId __attribute__((unused)))
+{
+ jobject obj;
+ cpnet_address *cpaddr;
+ int result = cpnet_getMulticastIF (env, fd, &cpaddr);
+
+ if (result != CPNATIVE_OK)
+ {
+ JCL_ThrowException (env, SOCKET_EXCEPTION,
+ cpnative_getErrorString (result));
+ return (0);
+ }
+
+ obj = _javanet_create_inetaddress (env, cpaddr);
+ cpnet_freeAddress (env, cpaddr);
+
+ return obj;
+}
+
/*
* Class: gnu_java_net_VMPlainSocketImpl
@@ -538,7 +649,7 @@ Java_gnu_java_net_VMPlainSocketImpl_leave6 (JNIEnv *env,
(*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
- if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
&maddr, sizeof (struct ipv6_mreq)))
JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
#else
@@ -555,8 +666,8 @@ Java_gnu_java_net_VMPlainSocketImpl_leave6 (JNIEnv *env,
#endif /* HAVE_SETSOCKOPT */
}
-static uint32_t getif_address (JNIEnv *env, char *ifname);
-static int getif_index (JNIEnv *env, char *ifname);
+static uint32_t getif_address (JNIEnv *env, const char *ifname);
+static int getif_index (JNIEnv *env, const char *ifname);
/*
* Class: gnu_java_net_VMPlainSocketImpl
@@ -572,10 +683,14 @@ Java_gnu_java_net_VMPlainSocketImpl_joinGroup (JNIEnv *env,
#ifdef HAVE_SETSOCKOPT
struct ip_mreq maddr;
jbyte *addr_elems;
+ const char *str_ifname;
if (ifname != NULL)
{
- maddr.imr_interface.s_addr = getif_address (env, ifname);
+ str_ifname = JCL_jstring_to_cstring(env, ifname);
+ maddr.imr_interface.s_addr = getif_address (env, str_ifname);
+ JCL_free_cstring(env, ifname, str_ifname);
+
if ((*env)->ExceptionCheck (env))
return;
}
@@ -593,6 +708,7 @@ Java_gnu_java_net_VMPlainSocketImpl_joinGroup (JNIEnv *env,
if (-1 == setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&maddr, sizeof (struct ip_mreq)))
JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
+
#else
(void) fd;
(void) addr;
@@ -617,10 +733,14 @@ Java_gnu_java_net_VMPlainSocketImpl_joinGroup6 (JNIEnv *env,
#ifdef HAVE_INET6
struct ipv6_mreq maddr;
jbyte *addr_elems;
+ const char *str_ifname;
if (ifname == NULL)
{
- maddr.ipv6mr_interface = getif_index (env, ifname);
+ str_ifname = JCL_jstring_to_cstring(env, ifname);
+ maddr.ipv6mr_interface = getif_index (env, str_ifname);
+ JCL_free_cstring(env, ifname, str_ifname);
+
if ((*env)->ExceptionCheck (env))
return;
}
@@ -666,10 +786,14 @@ Java_gnu_java_net_VMPlainSocketImpl_leaveGroup (JNIEnv *env,
#ifdef HAVE_SETSOCKOPT
struct ip_mreq maddr;
jbyte *addr_elems;
+ const char *str_ifname;
if (ifname != NULL)
{
- maddr.imr_interface.s_addr = getif_address (env, ifname);
+ str_ifname = JCL_jstring_to_cstring(env, ifname);
+ maddr.imr_interface.s_addr = getif_address (env, str_ifname);
+ JCL_free_cstring(env, ifname, str_ifname);
+
if ((*env)->ExceptionCheck (env))
return;
}
@@ -711,10 +835,14 @@ Java_gnu_java_net_VMPlainSocketImpl_leaveGroup6 (JNIEnv *env,
#ifdef HAVE_INET6
struct ipv6_mreq maddr;
jbyte *addr_elems;
+ const char *str_ifname;
if (ifname == NULL)
{
- maddr.ipv6mr_interface = getif_index (env, ifname);
+ str_ifname = JCL_jstring_to_cstring(env, ifname);
+ maddr.ipv6mr_interface = getif_index (env, str_ifname);
+ JCL_free_cstring(env, ifname, str_ifname);
+
if ((*env)->ExceptionCheck (env))
return;
}
@@ -747,7 +875,7 @@ Java_gnu_java_net_VMPlainSocketImpl_leaveGroup6 (JNIEnv *env,
}
static uint32_t
-getif_address (JNIEnv *env, char *ifname)
+getif_address (JNIEnv *env, const char *ifname)
{
#ifdef HAVE_GETIFADDRS
struct ifaddrs *ifaddrs, *i;
@@ -789,7 +917,7 @@ getif_address (JNIEnv *env, char *ifname)
}
static int
-getif_index (JNIEnv *env, char *ifname)
+getif_index (JNIEnv *env, const char *ifname)
{
#ifdef HAVE_GETIFADDRS
struct ifaddrs *ifaddrs, *i;