| /* Copyright (C) 2003 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 |
| |
| #include <gcj/cni.h> |
| #include <jvm.h> |
| #include <java/net/NetworkInterface.h> |
| #include <java/net/Inet4Address.h> |
| #include <java/net/SocketException.h> |
| #include <java/util/Vector.h> |
| |
| ::java::util::Vector* |
| java::net::NetworkInterface::getRealNetworkInterfaces () |
| { |
| int fd; |
| int num_interfaces = 0; |
| struct ifconf if_data; |
| struct ifreq* if_record; |
| ::java::util::Vector* ht = new ::java::util::Vector (); |
| |
| 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 >= (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); |
| Inet4Address* address = |
| new java::net::Inet4Address (baddr, JvNewStringLatin1 ("")); |
| ht->add (new NetworkInterface (if_name, address)); |
| if_record++; |
| } |
| |
| #ifdef HAVE_INET6 |
| // FIXME: read /proc/net/if_inet6 (on Linux 2.4) |
| #endif |
| |
| _Jv_Free (if_data.ifc_buf); |
| |
| if (fd >= 0) |
| _Jv_close (fd); |
| |
| return ht; |
| } |