1 /* Copyright (C) 2003, 2005, 2006 Free Software Foundation
3 This file is part of libgcj.
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
19 #include <sys/param.h>
20 #include <sys/types.h>
21 #ifdef HAVE_NETINET_IN_H
22 #include <netinet/in.h>
24 #ifdef HAVE_ARPA_INET_H
25 #include <arpa/inet.h>
30 #ifdef HAVE_SYS_IOCTL_H
31 #define BSD_COMP /* Get FIONREAD on Solaris2. */
32 #include <sys/ioctl.h>
43 #include <java/net/InetAddress.h>
44 #include <java/net/NetworkInterface.h>
45 #include <java/net/SocketException.h>
46 #include <java/net/VMNetworkInterface.h>
47 #include <java/util/Vector.h>
50 java::net::VMNetworkInterface::getInterfaces ()
52 ::java::util::Vector
* ht
= new ::java::util::Vector ();
54 #ifdef HAVE_GETIFADDRS
56 struct ifaddrs
*addrs
;
57 if (::getifaddrs (&addrs
) == -1)
58 throw new ::java::net::SocketException(JvNewStringUTF (strerror (errno
)));
60 for (struct ifaddrs
*work
= addrs
; work
!= NULL
; work
= work
->ifa_next
)
62 // Sometimes the address can be NULL; I don't know why but
63 // there's nothing we can do with this.
66 // We only return Inet4 or Inet6 addresses.
68 if (work
->ifa_addr
->sa_family
== AF_INET
)
70 sockaddr_in
*real
= reinterpret_cast<sockaddr_in
*> (work
->ifa_addr
);
71 laddr
= JvNewByteArray(4);
72 memcpy (elements (laddr
), &real
->sin_addr
, 4);
75 else if (work
->ifa_addr
->sa_family
== AF_INET6
)
78 = reinterpret_cast<sockaddr_in6
*> (work
->ifa_addr
);
79 laddr
= JvNewByteArray(16);
80 memcpy (elements (laddr
), &real
->sin6_addr
, 16);
86 ::java::net::InetAddress
*inaddr
87 = ::java::net::InetAddress::getByAddress(laddr
);
89 // It is ok to make a new NetworkInterface for each struct; the
90 // java code will unify these as necessary; see
91 // NetworkInterface.condense().
92 jstring name
= JvNewStringUTF (work
->ifa_name
);
94 ht
->add (new NetworkInterface (name
, inaddr
));
99 #else /* ! HAVE_GETIFADDRS */
102 int num_interfaces
= 0;
103 struct ifconf if_data
;
104 struct ifreq
* if_record
;
107 if_data
.ifc_buf
= NULL
;
109 // Open a (random) socket to have a file descriptor for the ioctl calls.
110 fd
= _Jv_socket (PF_INET
, SOCK_DGRAM
, htons (IPPROTO_IP
));
113 throw new ::java::net::SocketException
;
115 // Get all interfaces. If not enough buffers are available try it
116 // with a bigger buffer size.
119 num_interfaces
+= 16;
121 if_data
.ifc_len
= sizeof (struct ifreq
) * num_interfaces
;
123 (char*) _Jv_Realloc (if_data
.ifc_buf
, if_data
.ifc_len
);
125 // Try to get all local interfaces.
126 if (::ioctl (fd
, SIOCGIFCONF
, &if_data
) < 0)
127 throw new java::net::SocketException
;
129 while (if_data
.ifc_len
>= (int) (sizeof (struct ifreq
) * num_interfaces
));
131 // Get addresses of all interfaces.
132 if_record
= if_data
.ifc_req
;
134 for (int n
= 0; n
< if_data
.ifc_len
; n
+= sizeof (struct ifreq
))
138 memset (&ifr
, 0, sizeof (ifr
));
139 strcpy (ifr
.ifr_name
, if_record
->ifr_name
);
141 // Try to get the IPv4-address of the local interface
142 if (::ioctl (fd
, SIOCGIFADDR
, &ifr
) < 0)
143 throw new java::net::SocketException
;
146 struct sockaddr_in sa
= *((sockaddr_in
*) &(ifr
.ifr_addr
));
148 jbyteArray baddr
= JvNewByteArray (len
);
149 memcpy (elements (baddr
), &(sa
.sin_addr
), len
);
150 jstring if_name
= JvNewStringLatin1 (if_record
->ifr_name
);
151 InetAddress
* address
= java::net::InetAddress::getByAddress (baddr
);
152 ht
->add (new NetworkInterface (if_name
, address
));
156 _Jv_Free (if_data
.ifc_buf
);
160 #endif /* HAVE_GETIFADDRS */