summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid (Google) Code Review <android-gerrit@google.com>2009-09-30 19:37:27 -0400
committerAndroid (Google) Code Review <android-gerrit@google.com>2009-09-30 19:37:27 -0400
commite851c562ee5eb514135b5066553fcef6b0e5c333 (patch)
tree3a991781548f4f15964fbba56a07d0fb9373117e
parent1131d3da4e3d3df7f608fb0078ec67d14035ff25 (diff)
parentd6a4cc340b98980f292168a34458015344ee6646 (diff)
downloaddalvik-e851c562ee5eb514135b5066553fcef6b0e5c333.tar.gz
Merge change Iea75a523 into eclair
* changes: Fixes for socket options on multicast sockets.
-rw-r--r--libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp93
1 files changed, 72 insertions, 21 deletions
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index ac2b4e23f..339c62cc6 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -1320,6 +1320,24 @@ static int sockConnectWithTimeout(int handle, struct sockaddr_storage addr,
}
+#if LOG_SOCKOPT
+/**
+ * Helper method to log getsockopt/getsockopt calls.
+ */
+static const char *sockoptLevelToString(int level) {
+ switch(level) {
+ case SOL_SOCKET:
+ return "SOL_SOCKET";
+ case SOL_IP:
+ return "SOL_IP";
+ case SOL_IPV6:
+ return "SOL_IPV6";
+ default:
+ return "SOL_???";
+ }
+}
+#endif
+
/**
* Helper method to get or set socket options
*
@@ -1342,25 +1360,42 @@ static int getOrSetSocketOption(int action, int socket, int ipv4Option,
switch (family) {
case AF_INET:
option = ipv4Option;
- protocol = IPPROTO_IP;
+ protocol = SOL_IP;
break;
case AF_INET6:
option = ipv6Option;
- protocol = IPPROTO_IPV6;
+ protocol = SOL_IPV6;
break;
default:
+ // TODO: throw Java exceptions from this method instead of just
+ // returning error codes.
errno = EAFNOSUPPORT;
return -1;
}
+
+ int ret;
if (action == SOCKOPT_GET) {
- return getsockopt(socket, protocol, option, &optionValue, optionLength);
+ ret = getsockopt(socket, protocol, option, optionValue, optionLength);
+#if LOG_SOCKOPT
+ LOGI("getsockopt(%d, %s, %d, %p, [%d]) = %d %s",
+ socket, sockoptLevelToString(protocol), option, optionValue,
+ *optionLength, ret, (ret == -1) ? strerror(errno) : "");
+#endif
} else if (action == SOCKOPT_SET) {
- return setsockopt(socket, protocol, option, &optionValue,
- *optionLength);
+ ret = setsockopt(socket, protocol, option, optionValue, *optionLength);
+#if LOG_SOCKOPT
+ LOGI("setsockopt(%d, %s, %d, [%d], %d) = %d %s",
+ socket, sockoptLevelToString(protocol), option,
+ // Note: this only works for integer options.
+ // TODO: Use dvmPrintHexDump() to log non-integer options.
+ *(int *)optionValue, *optionLength, ret,
+ (ret == -1) ? strerror(errno) : "");
+#endif
} else {
errno = EINVAL;
- return -1;
+ ret = -1;
}
+ return ret;
}
/*
@@ -1382,13 +1417,13 @@ static int interfaceIndexFromMulticastSocket(int socket) {
// IP_MULTICAST_IF returns a pointer to a struct ip_mreqn.
struct ip_mreqn tempRequest;
requestLength = sizeof(tempRequest);
- result = getsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &tempRequest,
+ result = getsockopt(socket, SOL_IP, IP_MULTICAST_IF, &tempRequest,
&requestLength);
interfaceIndex = tempRequest.imr_ifindex;
} else if (family == AF_INET6) {
// IPV6_MULTICAST_IF returns a pointer to an integer.
requestLength = sizeof(interfaceIndex);
- result = getsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ result = getsockopt(socket, SOL_IPV6, IPV6_MULTICAST_IF,
&interfaceIndex, &requestLength);
} else {
errno = EAFNOSUPPORT;
@@ -1465,7 +1500,7 @@ static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
struct sockaddr_in *sin = (struct sockaddr_in *) &sockaddrP;
multicastRequest.imr_multiaddr = sin->sin_addr;
- result = setsockopt(handle, IPPROTO_IP, setSockOptVal,
+ result = setsockopt(handle, SOL_IP, setSockOptVal,
&multicastRequest, length);
if (0 != result) {
throwSocketException (env, convertError(errno));
@@ -1497,12 +1532,18 @@ static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
if (result < 0) // Exception has already been thrown.
return;
+ int family = getSocketAddressFamily(handle);
+
+ // Handle IPv4 multicast on an IPv6 socket.
+ if (family == AF_INET6 && sockaddrP.ss_family == AF_INET) {
+ family = AF_INET;
+ }
+
struct ip_mreqn ipv4Request;
struct ipv6_mreq ipv6Request;
void *multicastRequest;
socklen_t requestLength;
int level;
- int family = getSocketAddressFamily(handle);
switch (family) {
case AF_INET:
requestLength = sizeof(ipv4Request);
@@ -1511,16 +1552,23 @@ static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
((struct sockaddr_in *) &sockaddrP)->sin_addr;
ipv4Request.imr_ifindex = interfaceIndex;
multicastRequest = &ipv4Request;
- level = IPPROTO_IP;
+ level = SOL_IP;
break;
case AF_INET6:
+ // setSockOptVal is passed in by the caller and may be IPv4-only
+ if (setSockOptVal == IP_ADD_MEMBERSHIP) {
+ setSockOptVal = IPV6_ADD_MEMBERSHIP;
+ }
+ if (setSockOptVal == IP_DROP_MEMBERSHIP) {
+ setSockOptVal == IPV6_DROP_MEMBERSHIP;
+ }
requestLength = sizeof(ipv6Request);
memset(&ipv6Request, 0, requestLength);
ipv6Request.ipv6mr_multiaddr =
((struct sockaddr_in6 *) &sockaddrP)->sin6_addr;
ipv6Request.ipv6mr_interface = interfaceIndex;
multicastRequest = &ipv6Request;
- level = IPPROTO_IPV6;
+ level = SOL_IPV6;
break;
default:
throwSocketException (env, SOCKERR_BADAF);
@@ -3032,20 +3080,21 @@ static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
return newJavaLangByte(env, 0);
}
+ // Java uses a byte to store the TTL, but the kernel uses an int.
result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_MULTICAST_TTL,
- IPV6_MULTICAST_HOPS, &byteValue,
- &byteSize);
+ IPV6_MULTICAST_HOPS, &intValue,
+ &intSize);
if (0 != result) {
throwSocketException(env, convertError(errno));
return NULL;
}
- return newJavaLangByte(env, (jbyte)(byteValue & 0xFF));
+ return newJavaLangByte(env, (jbyte)(intValue & 0xFF));
}
case JAVASOCKOPT_MCAST_INTERFACE: {
if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
return NULL;
}
- result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
+ result = getsockopt(handle, SOL_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
if (0 != result) {
throwSocketException(env, convertError(errno));
return NULL;
@@ -3065,14 +3114,14 @@ static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
switch (addressFamily) {
case AF_INET:
optionLength = sizeof(multicastRequest);
- result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
+ result = getsockopt(handle, SOL_IP, IP_MULTICAST_IF,
&multicastRequest, &optionLength);
if (result == 0)
interfaceIndex = multicastRequest.imr_ifindex;
break;
case AF_INET6:
optionLength = sizeof(interfaceIndex);
- result = getsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ result = getsockopt(handle, SOL_IPV6, IPV6_MULTICAST_IF,
&interfaceIndex, &optionLength);
break;
default:
@@ -3239,9 +3288,11 @@ static void osNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz,
if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
return;
}
+ // Java uses a byte to store the TTL, but the kernel uses an int.
+ intVal = byteVal;
result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL,
- IPV6_MULTICAST_HOPS, &byteVal,
- &byteSize);
+ IPV6_MULTICAST_HOPS, &intVal,
+ &intSize);
if (0 != result) {
throwSocketException(env, convertError(errno));
return;
@@ -3274,7 +3325,7 @@ static void osNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz,
memset(&mcast_req, 0, sizeof(mcast_req));
struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal;
mcast_req.imr_address = sin->sin_addr;
- result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
+ result = setsockopt(handle, SOL_IP, IP_MULTICAST_IF,
&mcast_req, sizeof(mcast_req));
if (0 != result) {
throwSocketException(env, convertError(errno));