natVMNetworkInterfacePosix.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* Copyright (C) 2003, 2005, 2006 Free Software Foundation
  2. This file is part of libgcj.
  3. This software is copyrighted work licensed under the terms of the
  4. Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
  5. details. */
  6. #include <config.h>
  7. #include <platform.h>
  8. #ifdef HAVE_UNISTD_H
  9. #include <unistd.h>
  10. #endif
  11. #include <string.h>
  12. #include <errno.h>
  13. #include <stdlib.h>
  14. #include <sys/param.h>
  15. #include <sys/types.h>
  16. #ifdef HAVE_NETINET_IN_H
  17. #include <netinet/in.h>
  18. #endif
  19. #ifdef HAVE_ARPA_INET_H
  20. #include <arpa/inet.h>
  21. #endif
  22. #ifdef HAVE_NETDB_H
  23. #include <netdb.h>
  24. #endif
  25. #ifdef HAVE_SYS_IOCTL_H
  26. #define BSD_COMP /* Get FIONREAD on Solaris2. */
  27. #include <sys/ioctl.h>
  28. #endif
  29. #ifdef HAVE_NET_IF_H
  30. #include <net/if.h>
  31. #endif
  32. #ifdef HAVE_IFADDRS_H
  33. #include <ifaddrs.h>
  34. #endif
  35. #include <gcj/cni.h>
  36. #include <jvm.h>
  37. #include <java/net/InetAddress.h>
  38. #include <java/net/NetworkInterface.h>
  39. #include <java/net/SocketException.h>
  40. #include <java/net/VMNetworkInterface.h>
  41. #include <java/util/Vector.h>
  42. ::java::util::Vector*
  43. java::net::VMNetworkInterface::getInterfaces ()
  44. {
  45. ::java::util::Vector* ht = new ::java::util::Vector ();
  46. #ifdef HAVE_GETIFADDRS
  47. struct ifaddrs *addrs;
  48. if (::getifaddrs (&addrs) == -1)
  49. throw new ::java::net::SocketException(JvNewStringUTF (strerror (errno)));
  50. for (struct ifaddrs *work = addrs; work != NULL; work = work->ifa_next)
  51. {
  52. // Sometimes the address can be NULL; I don't know why but
  53. // there's nothing we can do with this.
  54. if (! work->ifa_addr)
  55. continue;
  56. // We only return Inet4 or Inet6 addresses.
  57. jbyteArray laddr;
  58. if (work->ifa_addr->sa_family == AF_INET)
  59. {
  60. sockaddr_in *real = reinterpret_cast<sockaddr_in *> (work->ifa_addr);
  61. laddr = JvNewByteArray(4);
  62. memcpy (elements (laddr), &real->sin_addr, 4);
  63. }
  64. #ifdef HAVE_INET6
  65. else if (work->ifa_addr->sa_family == AF_INET6)
  66. {
  67. sockaddr_in6 *real
  68. = reinterpret_cast<sockaddr_in6 *> (work->ifa_addr);
  69. laddr = JvNewByteArray(16);
  70. memcpy (elements (laddr), &real->sin6_addr, 16);
  71. }
  72. #endif
  73. else
  74. continue;
  75. ::java::net::InetAddress *inaddr
  76. = ::java::net::InetAddress::getByAddress(laddr);
  77. // It is ok to make a new NetworkInterface for each struct; the
  78. // java code will unify these as necessary; see
  79. // NetworkInterface.condense().
  80. jstring name = JvNewStringUTF (work->ifa_name);
  81. ht->add (new NetworkInterface (name, inaddr));
  82. }
  83. freeifaddrs (addrs);
  84. #else /* ! HAVE_GETIFADDRS */
  85. int fd;
  86. int num_interfaces = 0;
  87. struct ifconf if_data;
  88. struct ifreq* if_record;
  89. if_data.ifc_len = 0;
  90. if_data.ifc_buf = NULL;
  91. // Open a (random) socket to have a file descriptor for the ioctl calls.
  92. fd = _Jv_socket (PF_INET, SOCK_DGRAM, htons (IPPROTO_IP));
  93. if (fd < 0)
  94. throw new ::java::net::SocketException;
  95. // Get all interfaces. If not enough buffers are available try it
  96. // with a bigger buffer size.
  97. do
  98. {
  99. num_interfaces += 16;
  100. if_data.ifc_len = sizeof (struct ifreq) * num_interfaces;
  101. if_data.ifc_buf =
  102. (char*) _Jv_Realloc (if_data.ifc_buf, if_data.ifc_len);
  103. // Try to get all local interfaces.
  104. if (::ioctl (fd, SIOCGIFCONF, &if_data) < 0)
  105. throw new java::net::SocketException;
  106. }
  107. while (if_data.ifc_len >= (int) (sizeof (struct ifreq) * num_interfaces));
  108. // Get addresses of all interfaces.
  109. if_record = if_data.ifc_req;
  110. for (int n = 0; n < if_data.ifc_len; n += sizeof (struct ifreq))
  111. {
  112. struct ifreq ifr;
  113. memset (&ifr, 0, sizeof (ifr));
  114. strcpy (ifr.ifr_name, if_record->ifr_name);
  115. // Try to get the IPv4-address of the local interface
  116. if (::ioctl (fd, SIOCGIFADDR, &ifr) < 0)
  117. throw new java::net::SocketException;
  118. int len = 4;
  119. struct sockaddr_in sa = *((sockaddr_in*) &(ifr.ifr_addr));
  120. jbyteArray baddr = JvNewByteArray (len);
  121. memcpy (elements (baddr), &(sa.sin_addr), len);
  122. jstring if_name = JvNewStringLatin1 (if_record->ifr_name);
  123. InetAddress* address = java::net::InetAddress::getByAddress (baddr);
  124. ht->add (new NetworkInterface (if_name, address));
  125. if_record++;
  126. }
  127. _Jv_Free (if_data.ifc_buf);
  128. if (fd >= 0)
  129. _Jv_close (fd);
  130. #endif /* HAVE_GETIFADDRS */
  131. return ht;
  132. }