mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			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;
 | |
| }
 |