gcc/libjava/java/net/natVMNetworkInterfacePosix.cc
Gary Benson aac8697859 InetAddress.java: Mostly merged with Classpath.
2006-09-20  Gary Benson  <gbenson@redhat.com>

	* java/net/InetAddress.java: Mostly merged with Classpath.
	* java/net/VMInetAddress.java: New file.
	* sources.am, Makefile.in: Rebuilt.

	* java/net/natVMNetworkInterfacePosix.cc
	(getInterfaces): Create InetAddress objects using
	InetAddress.getByAddress.
	* gnu/java/net/natPlainSocketImplPosix.cc
	(accept, getOption): Likewise.
	* gnu/java/net/natPlainDatagramSocketImplPosix.cc
	(peekData, receive, getLocalAddress): Likewise.

From-SVN: r117075
2006-09-20 07:55:26 +00:00

164 lines
4.2 KiB
C++

/* Copyright (C) 2003, 2005, 2006 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#include <platform.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#define BSD_COMP /* Get FIONREAD on Solaris2. */
#include <sys/ioctl.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#ifdef HAVE_IFADDRS_H
#include <ifaddrs.h>
#endif
#include <gcj/cni.h>
#include <jvm.h>
#include <java/net/InetAddress.h>
#include <java/net/NetworkInterface.h>
#include <java/net/SocketException.h>
#include <java/net/VMNetworkInterface.h>
#include <java/util/Vector.h>
::java::util::Vector*
java::net::VMNetworkInterface::getInterfaces ()
{
::java::util::Vector* ht = new ::java::util::Vector ();
#ifdef HAVE_GETIFADDRS
struct ifaddrs *addrs;
if (::getifaddrs (&addrs) == -1)
throw new ::java::net::SocketException(JvNewStringUTF (strerror (errno)));
for (struct ifaddrs *work = addrs; work != NULL; work = work->ifa_next)
{
// Sometimes the address can be NULL; I don't know why but
// there's nothing we can do with this.
if (! work->ifa_addr)
continue;
// We only return Inet4 or Inet6 addresses.
jbyteArray laddr;
if (work->ifa_addr->sa_family == AF_INET)
{
sockaddr_in *real = reinterpret_cast<sockaddr_in *> (work->ifa_addr);
laddr = JvNewByteArray(4);
memcpy (elements (laddr), &real->sin_addr, 4);
}
#ifdef HAVE_INET6
else if (work->ifa_addr->sa_family == AF_INET6)
{
sockaddr_in6 *real
= reinterpret_cast<sockaddr_in6 *> (work->ifa_addr);
laddr = JvNewByteArray(16);
memcpy (elements (laddr), &real->sin6_addr, 16);
}
#endif
else
continue;
::java::net::InetAddress *inaddr
= ::java::net::InetAddress::getByAddress(laddr);
// It is ok to make a new NetworkInterface for each struct; the
// java code will unify these as necessary; see
// NetworkInterface.condense().
jstring name = JvNewStringUTF (work->ifa_name);
ht->add (new NetworkInterface (name, inaddr));
}
freeifaddrs (addrs);
#else /* ! HAVE_GETIFADDRS */
int fd;
int num_interfaces = 0;
struct ifconf if_data;
struct ifreq* if_record;
if_data.ifc_len = 0;
if_data.ifc_buf = NULL;
// Open a (random) socket to have a file descriptor for the ioctl calls.
fd = _Jv_socket (PF_INET, SOCK_DGRAM, htons (IPPROTO_IP));
if (fd < 0)
throw new ::java::net::SocketException;
// Get all interfaces. If not enough buffers are available try it
// with a bigger buffer size.
do
{
num_interfaces += 16;
if_data.ifc_len = sizeof (struct ifreq) * num_interfaces;
if_data.ifc_buf =
(char*) _Jv_Realloc (if_data.ifc_buf, if_data.ifc_len);
// Try to get all local interfaces.
if (::ioctl (fd, SIOCGIFCONF, &if_data) < 0)
throw new java::net::SocketException;
}
while (if_data.ifc_len >= (int) (sizeof (struct ifreq) * num_interfaces));
// Get addresses of all interfaces.
if_record = if_data.ifc_req;
for (int n = 0; n < if_data.ifc_len; n += sizeof (struct ifreq))
{
struct ifreq ifr;
memset (&ifr, 0, sizeof (ifr));
strcpy (ifr.ifr_name, if_record->ifr_name);
// Try to get the IPv4-address of the local interface
if (::ioctl (fd, SIOCGIFADDR, &ifr) < 0)
throw new java::net::SocketException;
int len = 4;
struct sockaddr_in sa = *((sockaddr_in*) &(ifr.ifr_addr));
jbyteArray baddr = JvNewByteArray (len);
memcpy (elements (baddr), &(sa.sin_addr), len);
jstring if_name = JvNewStringLatin1 (if_record->ifr_name);
InetAddress* address = java::net::InetAddress::getByAddress (baddr);
ht->add (new NetworkInterface (if_name, address));
if_record++;
}
_Jv_Free (if_data.ifc_buf);
if (fd >= 0)
_Jv_close (fd);
#endif /* HAVE_GETIFADDRS */
return ht;
}