/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#ifdef __solaris__
#include <fcntl.h>
#endif
#ifdef __linux__
#include <unistd.h>
#ifndef SO_BSDCOMPAT
#endif
#endif
#ifndef IPTOS_TOS_MASK
#endif
#ifndef IPTOS_PREC_MASK
#endif
#include "jvm.h"
#include "jni_util.h"
#include "net_util.h"
#include "java_net_SocketOptions.h"
#include "java_net_PlainDatagramSocketImpl.h"
#include "java_net_NetworkInterface.h"
/************************************************************************
* PlainDatagramSocketImpl
*/
#ifdef __linux__
#endif
#endif
/*
* Returns a java.lang.Integer based on 'i'
*/
CHECK_NULL_RETURN(c, NULL);
}
}
/*
* Returns a java.lang.Boolean based on 'b'
*/
CHECK_NULL_RETURN(c, NULL);
}
}
/*
* Returns the fd for a PlainDatagramSocketImpl or -1
* if closed.
*/
return -1;
}
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: init
* Signature: ()V
*/
#ifdef __linux__
#endif
"Ljava/io/FileDescriptor;");
"Ljava/net/InetAddress;");
#ifdef __linux__
/*
* We need to determine if this is a 2.2 kernel.
*/
} else {
/*
* If this fails assume that /proc has changed and that
* this must be new /proc format and hence new kernel.
*/
}
}
}
#ifdef AF_INET6
#endif
#endif
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: bind
* Signature: (ILjava/net/InetAddress;)V
*/
/* fdObj is the FileDescriptor field on this */
/* fd is an int field on fdObj */
int fd;
int len = 0;
"Socket closed");
return;
} else {
}
return;
}
/* bind */
if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) {
return;
}
"Bind failed");
} else {
"Bind failed");
}
return;
}
/* intialize the local port */
if (localport == 0) {
/* Now that we're a connected socket, let's extract the port number
* that the system chose for us and store it in the Socket object.
*/
"Error getting socket name");
return;
}
} else {
}
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: connect0
* Signature: (Ljava/net/InetAddress;I)V
*/
/* The object's field */
/* The fdObj'fd */
/* The packetAddress address, family and port */
int len = 0;
"Socket closed");
return;
}
return;
}
if (NET_InetAddressToSockaddr(env, address, port, (struct sockaddr *)&rmtaddr, &len, JNI_TRUE) != 0) {
return;
}
#ifdef __linux__
if (isOldKernel) {
int t = 0;
} else
#endif
{
"Connect failed");
return;
}
}
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: disconnect0
* Signature: ()V
*/
/* The object's field */
/* The fdObj'fd */
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
int len;
#endif
return;
}
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
#ifdef __linux__
if (isOldKernel) {
int t = 1;
} else {
#endif /* __linux__ */
#ifdef AF_INET6
if (ipv6_available()) {
len = sizeof(struct sockaddr_in6);
} else
#endif
{
len = sizeof(struct sockaddr_in);
}
#ifdef __linux__
// After disconnecting a UDP socket, Linux kernel will set
// local port to zero if the port number comes from implicit
// So bind again with former port number here.
int localPort = 0;
return;
}
if (localPort == 0) {
#ifdef AF_INET6
} else
#endif /* AF_INET6 */
{
}
}
}
#endif
#else
JVM_Connect(fd, 0, 0);
#endif
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: send
* Signature: (Ljava/net/DatagramPacket;)V
*/
/* The object's field */
/* The fdObj'fd */
int len;
"Socket closed");
return;
}
return;
}
return;
}
#ifdef __linux__
if (connected && !isOldKernel) {
#else
if (connected) {
#endif
/* arg to NET_Sendto () null in this case */
len = 0;
rmtaddrP = 0;
} else {
if (NET_InetAddressToSockaddr(env, packetAddress, packetPort, (struct sockaddr *)&rmtaddr, &len, JNI_TRUE) != 0) {
return;
}
}
if (packetBufferLen > MAX_BUFFER_LEN) {
/* When JNI-ifying the JDK's IO routines, we turned
* read's and write's of byte arrays of size greater
* than 2048 bytes into several operations of size 2048.
* This saves a malloc()/memcpy()/free() for big
* buffers. This is OK for file IO and TCP, but that
* strategy violates the semantics of a datagram protocol.
* (one big send) != (several smaller sends). So here
* we *must* alloc the buffer. Note it needn't be bigger
* than 65,536 (0xFFFF) the max size of an IP packet.
* Anything bigger should be truncated anyway.
*
* We may want to use a smarter allocation scheme at some
* point.
*/
if (packetBufferLen > MAX_PACKET_LEN) {
}
if (!fullPacket) {
return;
} else {
}
} else {
fullPacket = &(BUF[0]);
}
(jbyte *)fullPacket);
#ifdef AF_INET6
if (trafficClass != 0 && ipv6_available()) {
}
#endif /* AF_INET6 */
/*
* Send the datagram.
*
* If we are connected it's possible that sendto will return
* ECONNREFUSED indicating that an ICMP port unreachable has
* received.
*/
if (ret < 0) {
switch (ret) {
case JVM_IO_ERR :
if (errno == ECONNREFUSED) {
"ICMP Port Unreachable");
} else {
}
break;
case JVM_IO_INTR:
"operation interrupted");
break;
}
}
if (mallocedPacket) {
}
return;
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: peek
* Signature: (Ljava/net/InetAddress;)I
*/
ssize_t n;
int len;
int port;
return -1;
} else {
}
if (IS_NULL(addressObj)) {
}
if (timeout) {
if (ret == 0) {
"Peek timed out");
return ret;
} else if (ret == JVM_IO_ERR) {
} else {
}
return ret;
} else if (ret == JVM_IO_INTR) {
"operation interrupted");
return ret; /* WARNING: SHOULD WE REALLY RETURN -2??? */
}
}
len = SOCKADDR_LEN;
if (n == JVM_IO_ERR) {
#ifdef __solaris__
if (errno == ECONNREFUSED) {
errno = orig_errno;
}
#endif
if (errno == ECONNREFUSED) {
"ICMP Port Unreachable");
} else {
} else {
}
}
return 0;
} else if (n == JVM_IO_INTR) {
return 0;
}
#ifdef AF_INET6
#else
#endif
}
return port;
}
int fd;
int n;
int len;
int port;
"Socket closed");
return -1;
}
return -1;
}
if (IS_NULL(packetBuffer)) {
return -1;
}
if (timeout) {
if (ret == 0) {
"Receive timed out");
return -1;
} else if (ret == JVM_IO_ERR) {
#ifdef __linux__
} else {
}
#else
#endif
return -1;
} else if (ret == JVM_IO_INTR) {
"operation interrupted");
return -1;
}
}
if (packetBufferLen > MAX_BUFFER_LEN) {
/* When JNI-ifying the JDK's IO routines, we turned
* read's and write's of byte arrays of size greater
* than 2048 bytes into several operations of size 2048.
* This saves a malloc()/memcpy()/free() for big
* buffers. This is OK for file IO and TCP, but that
* strategy violates the semantics of a datagram protocol.
* (one big send) != (several smaller sends). So here
* we *must* alloc the buffer. Note it needn't be bigger
* than 65,536 (0xFFFF) the max size of an IP packet.
* anything bigger is truncated anyway.
*
* We may want to use a smarter allocation scheme at some
* point.
*/
if (packetBufferLen > MAX_PACKET_LEN) {
}
if (!fullPacket) {
return -1;
} else {
}
} else {
fullPacket = &(BUF[0]);
}
len = SOCKADDR_LEN;
/* truncate the data if the packet's length is too small */
if (n > packetBufferLen) {
n = packetBufferLen;
}
if (n == JVM_IO_ERR) {
#ifdef __solaris__
if (errno == ECONNREFUSED) {
errno = orig_errno;
}
#endif
if (errno == ECONNREFUSED) {
"ICMP Port Unreachable");
} else {
} else {
}
}
} else if (n == JVM_IO_INTR) {
"operation interrupted");
} else {
/*
* success - fill in received address...
*
* REMIND: Fill in an int on the packet, and create inetadd
* object in Java, as a performance improvement. Also
* construct the inetadd object lazily.
*/
/*
* Check if there is an InetAddress already associated with this
* packet. If so we check if it is the same source address. We
* can't update any existing InetAddress because it is immutable
*/
if (packetAddress != NULL) {
/* force a new InetAddress to be created */
}
}
if (packetAddress == NULL) {
/* stuff the new Inetaddress in the packet */
} else {
/* only get the new port number */
}
(jbyte *)fullPacket);
}
if (mallocedPacket) {
}
return port;
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: receive
* Signature: (Ljava/net/DatagramPacket;)V
*/
int fd;
int n;
int len;
#ifdef __linux__
#endif
"Socket closed");
return;
}
return;
}
if (IS_NULL(packetBuffer)) {
return;
}
if (packetBufferLen > MAX_BUFFER_LEN) {
/* When JNI-ifying the JDK's IO routines, we turned
* read's and write's of byte arrays of size greater
* than 2048 bytes into several operations of size 2048.
* This saves a malloc()/memcpy()/free() for big
* buffers. This is OK for file IO and TCP, but that
* strategy violates the semantics of a datagram protocol.
* (one big send) != (several smaller sends). So here
* we *must* alloc the buffer. Note it needn't be bigger
* than 65,536 (0xFFFF) the max size of an IP packet.
* anything bigger is truncated anyway.
*
* We may want to use a smarter allocation scheme at some
* point.
*/
if (packetBufferLen > MAX_PACKET_LEN) {
}
if (!fullPacket) {
return;
} else {
}
} else {
fullPacket = &(BUF[0]);
}
#ifdef __linux__
/*
* On Linux with the 2.2 kernel we simulate connected datagrams by
* discarding packets
*/
if (isOldKernel) {
if (connected) {
if (timeout) {
}
}
}
#endif
do {
if (timeout) {
if (ret <= 0) {
if (ret == 0) {
"Receive timed out");
} else if (ret == JVM_IO_ERR) {
#ifdef __linux__
} else {
}
#else
#endif
} else if (ret == JVM_IO_INTR) {
"operation interrupted");
}
if (mallocedPacket) {
}
return;
}
}
/*
* Security Note: For Linux 2.2 with connected datagrams ensure that
* to receive directly into DatagramPacket's byte array.
* (ie: if the virtual machine support pinning don't use
* GetByteArrayElements or a JNI critical section and receive
* directly into the byte array)
*/
len = SOCKADDR_LEN;
/* truncate the data if the packet's length is too small */
if (n > packetBufferLen) {
n = packetBufferLen;
}
if (n == JVM_IO_ERR) {
if (errno == ECONNREFUSED) {
"ICMP Port Unreachable");
} else {
} else {
}
}
} else if (n == JVM_IO_INTR) {
"operation interrupted");
} else {
int port;
/*
* If we are connected then we know that the datagram that we have
* received is from the address that we are connected too. However
* on Linux with 2.2 kernel we have to simulate this behaviour by
* discarding any datagrams that aren't from the connected address.
*/
#ifdef __linux__
if (isOldKernel && connected) {
/*
* Discard the datagram as it's not from the connected
* address
*/
/*
* Adjust timeout if necessary to ensure that we adhere to
* timeout semantics.
*/
if (timeout) {
if (timeout <= 0) {
"Receive timed out");
if (mallocedPacket) {
}
return;
}
}
continue;
}
}
#endif
/*
* success - fill in received address...
*
* REMIND: Fill in an int on the packet, and create inetadd
* object in Java, as a performance improvement. Also
* construct the inetadd object lazily.
*/
/*
* Check if there is an InetAddress already associated with this
* packet. If so we check if it is the same source address. We
* can't update any existing InetAddress because it is immutable
*/
if (packetAddress != NULL) {
/* force a new InetAddress to be created */
}
}
if (packetAddress == NULL) {
/* stuff the new Inetaddress in the packet */
} else {
/* only get the new port number */
}
(jbyte *)fullPacket);
}
} while (retry);
if (mallocedPacket) {
}
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: datagramSocketCreate
* Signature: ()V
*/
#ifdef AF_INET6
#else
#endif
"Socket closed");
return;
}
"Error creating socket");
return;
}
#ifdef AF_INET6
/* Disable IPV6_V6ONLY to ensure dual-socket support */
arg = 0;
sizeof(int)) < 0) {
return;
}
}
#endif /* AF_INET6 */
#ifdef __APPLE__
arg = 65507;
return;
}
return;
}
#endif /* __APPLE__ */
#ifdef __linux__
if (isOldKernel) {
}
#ifdef AF_INET6
/*
* On Linux for IPv6 sockets we must set the hop limit
* to 1 to be compatible with default ttl of 1 for IPv4 sockets.
*/
sizeof(ttl));
if (isOldKernel) {
}
}
#endif
#endif /* __linux__ */
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: datagramSocketClose
* Signature: ()V
*/
/*
* REMIND: PUT A LOCK AROUND THIS CODE
*/
int fd;
return;
}
if (fd == -1) {
return;
}
}
/*
* Set outgoing multicast interface designated by a NetworkInterface.
* Throw exception if failed.
*/
int i;
if (ni_addrsID == NULL ) {
CHECK_NULL(c);
"[Ljava/net/InetAddress;");
}
/*
* Check that there is at least one address bound to this
* interface.
*/
if (len < 1) {
"bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface");
return;
}
/*
* We need an ipv4 address here
*/
for (i = 0; i < len; i++) {
break;
}
}
"Error setting socket option");
}
}
/*
* Set outgoing multicast interface designated by a NetworkInterface.
* Throw exception if failed.
*/
#ifdef AF_INET6
int index;
if (ni_indexID == NULL) {
CHECK_NULL(c);
}
"IPV6_MULTICAST_IF failed (interface has IPv4 "
"address only?)");
} else {
"Error setting socket option");
}
return;
}
#ifdef __linux__
/*
* Linux 2.2 kernel doesn't support IPV6_MULTICAST_IF socket
* option so record index for later retrival.
*/
if (isOldKernel) {
}
#endif
}
#endif /* AF_INET6 */
/*
* Set outgoing multicast interface designated by an InetAddress.
* Throw exception if failed.
*/
"Error setting socket option");
}
}
/*
* Set outgoing multicast interface designated by an InetAddress.
* Throw exception if failed.
*/
#ifdef AF_INET6
CHECK_NULL(c);
}
"bad argument for IP_MULTICAST_IF"
": address not bound to any interface");
}
return;
}
}
#endif
/*
* Sets the multicast interface.
*
* SocketOptions.IP_MULTICAST_IF :-
* value is a InetAddress
* IPv4: set outgoing multicast interface using
* IPv6: Get the index of the interface to which the
* InetAddress is bound
* Set outgoing multicast interface using
* On Linux 2.2 record interface index as can't
* query the multicast interface.
*
* SockOptions.IF_MULTICAST_IF2 :-
* value is a NetworkInterface
* IPv4: Obtain IP address bound to network interface
* (NetworkInterface.addres[0])
* set outgoing multicast interface using
* IPv6: Obtain NetworkInterface.index
* Set outgoing multicast interface using
* On Linux 2.2 record interface index as can't
* query the multicast interface.
*
*/
{
if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
/*
* value is an InetAddress.
*/
#ifdef AF_INET6
#ifdef __linux__
if (ipv6_available()) {
}
#else /* __linux__ not defined */
if (ipv6_available()) {
} else {
}
#endif /* __linux__ */
#else
#endif /* AF_INET6 */
}
if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
/*
* value is a NetworkInterface.
*/
#ifdef AF_INET6
#ifdef __linux__
if (ipv6_available()) {
}
#else /* __linux__ not defined */
if (ipv6_available()) {
} else {
}
#endif /* __linux__ */
#else
#endif /* AF_INET6 */
}
}
/*
*/
char loopback;
return;
}
}
/*
*/
#ifdef AF_INET6
int loopback;
if (NET_SetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&loopback, sizeof(int)) < 0) {
return;
}
#ifdef __linux__
/*
* Can't query IPV6_MULTICAST_LOOP on Linux 2.2 kernel so
* store it in impl so that we can simulate getsockopt.
*/
if (isOldKernel) {
}
#endif
}
#endif /* AF_INET6 */
/*
* Sets the multicast loopback mode.
*/
#ifdef AF_INET6
#ifdef __linux__
if (ipv6_available()) {
}
#else /* __linux__ not defined */
if (ipv6_available()) {
} else {
}
#endif /* __linux__ */
#else
#endif /* AF_INET6 */
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: socketSetOption
*/
int fd;
union {
int i;
char c;
} optval;
/*
* Check that socket hasn't been closed
*/
if (fd < 0) {
"Socket closed");
return;
}
/*
* Check argument has been provided
*/
return;
}
/*
* Setting the multicast interface handled seperately
*/
if (opt == java_net_SocketOptions_IP_MULTICAST_IF ||
return;
}
/*
* Setting the multicast loopback mode handled separately
*/
if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP) {
return;
}
/*
* Map the Java level socket option to the platform specific
* level and option name.
*/
return;
}
switch (opt) {
{
break;
}
{
/* SO_REUSEADDR or SO_BROADCAST */
break;
}
default :
"Socket option not supported by PlainDatagramSocketImp");
break;
}
return;
}
}
/*
* Return the multicast interface:
*
* SocketOptions.IP_MULTICAST_IF
* IPv4: Query IPPROTO_IP/IP_MULTICAST_IF
* Create InetAddress
* IP_MULTICAST_IF returns struct ip_mreqn on 2.2
* kernel but struct in_addr on 2.4 kernel
* IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF or
* obtain from impl is Linux 2.2 kernel
* If index == 0 return InetAddress representing
* anyLocalAddress.
* If index > 0 query NetworkInterface by index
* and returns addrs[0]
*
* SocketOptions.IP_MULTICAST_IF2
* IPv4: Query IPPROTO_IP/IP_MULTICAST_IF
* Query NetworkInterface by IP address and
* return the NetworkInterface that the address
* is bound too.
* IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF
* (except Linux .2 kernel)
* Query NetworkInterface by index and
* return NetworkInterface.
*/
#ifdef AF_INET6
if (ipv6_available()) {
}
#endif
/*
* IPv4 implementation
*/
if (isIPV4) {
#ifdef __linux__
if (isOldKernel) {
}
#endif
"Error getting socket option");
return NULL;
}
/*
* Construct and populate an Inet4Address
*/
if (inet4_class == NULL) {
CHECK_NULL_RETURN(c, NULL);
}
#ifdef __linux__
#else
#endif
/*
* For IP_MULTICAST_IF return InetAddress
*/
if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
return addr;
}
/*
* For IP_MULTICAST_IF2 we get the NetworkInterface for
* this address and return it
*/
CHECK_NULL_RETURN(c, NULL);
"[Ljava/net/InetAddress;");
}
if (ni) {
return ni;
}
/*
* The address doesn't appear to be bound at any known
* NetworkInterface. Therefore we construct a NetworkInterface
* with this address.
*/
return ni;
}
#ifdef AF_INET6
/*
* IPv6 implementation
*/
if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) ||
int index;
#ifdef __linux__
/*
* Linux 2.2 kernel doesn't support IPV6_MULTICAST_IF socke option
* so use cached index.
*/
if (isOldKernel) {
} else
#endif
{
"Error getting socket option");
return NULL;
}
}
CHECK_NULL_RETURN(c, NULL);
"[Ljava/net/InetAddress;");
"anyLocalAddress",
"()Ljava/net/InetAddress;");
}
/*
* If multicast to a specific interface then return the
* interface (for IF2) or the any address on that interface
* (for IF).
*/
if (index > 0) {
index);
"IPV6_MULTICAST_IF returned index to unrecognized interface: %d",
index);
return NULL;
}
/*
* For IP_MULTICAST_IF2 return the NetworkInterface
*/
if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
return ni;
}
/*
* For IP_MULTICAST_IF return addrs[0]
*/
"IPV6_MULTICAST_IF returned interface without IP bindings");
return NULL;
}
return addr;
}
/*
* Multicast to any address - return anyLocalAddress
* or a NetworkInterface with addrs[0] set to anyLocalAddress
*/
NULL);
if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
return addr;
}
return ni;
}
#endif
return NULL;
}
/*
* Returns relevant info as a jint.
*
* Class: java_net_PlainDatagramSocketImpl
* Method: socketGetOption
*/
int fd;
union {
int i;
char c;
} optval;
if (fd < 0) {
"socket closed");
return NULL;
}
/*
* Handle IP_MULTICAST_IF seperately
*/
if (opt == java_net_SocketOptions_IP_MULTICAST_IF ||
}
/*
* SO_BINDADDR implemented using getsockname
*/
if (opt == java_net_SocketOptions_SO_BINDADDR) {
/* find out local IP address */
int port;
len = SOCKADDR_LEN;
"Error getting socket name");
return NULL;
}
return iaObj;
}
/*
* Map the Java level socket option to the platform specific
* level and option name.
*/
return NULL;
}
/*
* IP_MULTICAST_LOOP socket option isn't available on Linux 2.2
* kernel with IPv6 so return value stored in impl.
*/
level == IPPROTO_IPV6) {
}
#endif
if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP &&
level == IPPROTO_IP) {
} else {
}
"Error getting socket option");
return NULL;
}
switch (opt) {
/* getLoopbackMode() returns true if IP_MULTICAST_LOOP disabled */
if (level == IPPROTO_IP) {
} else {
}
}
/* should never rearch here */
return NULL;
}
/*
* Multicast-related calls
*/
if (ittl < 0) {
ittl += 0x100;
}
}
/*
* Set TTL for a socket. Throw exception if failed.
*/
sizeof(ittl)) < 0) {
"Error setting socket option");
}
}
/*
* Set hops limit for a socket. Throw exception if failed.
*/
#ifdef AF_INET6
"Error setting socket option");
}
}
#endif
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: setTTL
* Signature: (B)V
*/
int fd;
/* it is important to cast this to a char, otherwise setsockopt gets confused */
"Socket closed");
return;
} else {
}
/* setsockopt to be correct ttl */
#ifdef AF_INET6
#ifdef __linux__
if (ipv6_available()) {
if (isOldKernel) {
}
}
#else /* __linux__ not defined */
if (ipv6_available()) {
} else {
}
#endif /* __linux__ */
#else
#endif /* AF_INET6 */
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: getTTL
* Signature: ()B
*/
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: getTTL
* Signature: ()B
*/
"Socket closed");
return -1;
} else {
}
/* getsockopt of ttl */
#ifdef AF_INET6
if (ipv6_available()) {
int ttl = 0;
#ifdef __linux__
/*
* Linux 2.2 kernel doesn't support IPV6_MULTICAST_HOPS socket option
*/
if (isOldKernel) {
}
#endif
"Error getting socket option");
return -1;
}
} else
#endif /* AF_INET6 */
{
"Error getting socket option");
return -1;
}
}
}
/*
* mcast_join_leave: Join or leave a multicast group.
*
* For IPv4 sockets use IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP socket option
*
* For IPv6 sockets use IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP socket option
* an IPv4-mapped address is used.
*
* we must use the IPv4 socket options. This is because the IPv6 socket options
* don't support IPv4-mapped addresses. This is true as per 2.2.19 and 2.4.7
* kernel releases. In the future it's possible that IP_ADD_MEMBERSHIP
* will be updated to return ENOPROTOOPT if uses with an IPv6 socket (Solaris
* already does this). Thus to cater for this we first try with the IPv4
* socket options and if they fail we use the IPv6 socket options. This
* seems a reasonable failsafe solution.
*/
"Socket closed");
return;
} else {
}
return;
}
/*
*/
#ifdef AF_INET6
#ifdef __linux__
}
#endif
#else
/*
* IPv6 not compiled in
*/
#endif
/*
* For IPv4 join use IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP socket option
*
* On Linux if IPv4 or IPv6 use IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP
*/
if (!ipv6_join_leave) {
#ifdef __linux__
#else
#endif
int mname_len;
/*
* joinGroup(InetAddress, NetworkInterface) implementation :-
*
* address and interface index.
*
* IPv4: use ip_mreq structure populated with multicast
* address and first address obtained from
* NetworkInterface
*/
if (ipv6_available()) {
if (ni_indexID == NULL) {
CHECK_NULL(c);
}
} else
#endif
{
"bad argument for IP_ADD_MEMBERSHIP: "
"No IP addresses bound to interface");
return;
}
#ifdef __linux__
#else
#endif
}
}
/*
* joinGroup(InetAddress) implementation :-
*
* address and interface index. index obtained
* from cached value or IPV6_MULTICAST_IF.
*
* IPv4: use ip_mreq structure populated with multicast
* address and local address obtained from
* IP_MULTICAST_IF. On Linux IP_MULTICAST_IF
* returns different structure depending on
* kernel.
*/
if (ipv6_available()) {
int index;
if (isOldKernel) {
} else {
return;
}
}
} else
#endif
{
#ifdef __linux__
if (isOldKernel) {
}
#endif
return;
}
#ifdef __linux__
#else
#endif
}
}
/*
* Join the multicast group.
*/
/*
* If IP_ADD_MEMBERSHIP returns ENOPROTOOPT on Linux and we've got
* IPv6 enabled then it's possible that the kernel has been fixed
* so we switch to IPV6_ADD_MEMBERSHIP socket option.
* As of 2.4.7 kernel IPV6_ADD_MEMERSHIP can't handle IPv4-mapped
* addresses so we have to use IP_ADD_MEMERSHIP for IPv4 multicast
* groups. However if the socket is an IPv6 socket then then setsockopt
* should reurn ENOPROTOOPT. We assume this will be fixed in Linux
* at some stage.
*/
if (errno == ENOPROTOOPT) {
if (ipv6_available()) {
errno = 0;
} else {
}
}
#endif
if (errno) {
if (join) {
} else {
"Not a member of the multicast group");
else
}
}
}
/*
* If we haven't switched to IPv6 socket option then we're done.
*/
if (!ipv6_join_leave) {
return;
}
}
/*
* IPv6 join. If it's an IPv4 multicast group then we use an IPv4-mapped
* address.
*/
#ifdef AF_INET6
{
} else {
}
int index;
#ifdef __linux__
/*
* 2.2 kernel doens't support IPV6_MULTICAST_IF socket option
*/
if (isOldKernel) {
} else
#endif
{
return;
}
}
#ifdef __linux__
/*
* On 2.4.8+ if we join a group with the interface set to 0
* then the kernel records the interface it decides. This causes
* subsequent leave groups to fail as there is no match. Thus we
* pick the interface if there is a matching route.
*/
if (index == 0 && !isOldKernel) {
if (rt_index > 0) {
}
}
#endif
#ifdef MACOSX
}
#endif
} else {
}
#if defined(_ALLBSD_SOURCE)
#else
#endif
/* Join the multicast group */
if (join) {
} else {
"Not a member of the multicast group");
} else {
}
}
}
}
#endif
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: join
* Signature: (Ljava/net/InetAddress;)V
*/
{
}
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: leave
* Signature: (Ljava/net/InetAddress;)V
*/
{
}