mirror of
https://github.com/autc04/Retro68.git
synced 2024-09-10 03:54:48 +00:00
164 lines
4.2 KiB
C++
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;
|
|
}
|