/* 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 #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_NETDB_H #include #endif #ifdef HAVE_SYS_IOCTL_H #define BSD_COMP /* Get FIONREAD on Solaris2. */ #include #endif #ifdef HAVE_NET_IF_H #include #endif #ifdef HAVE_IFADDRS_H #include #endif #include #include #include #include #include #include #include ::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 (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 (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; }