| /* Copyright (C) 2003, 2005 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> |
| |
| #undef STRICT |
| |
| #include <java/net/NetworkInterface.h> |
| #include <java/net/Inet4Address.h> |
| #include <java/net/SocketException.h> |
| #include <java/net/VMNetworkInterface.h> |
| #include <java/util/Vector.h> |
| |
| /* As of this writing, NetworkInterface.java has |
| getName() == getDisplayName() and only one IP address |
| per interface. If this changes, we'll need to use |
| iphlpapi (not supported on Win95) to retrieve richer |
| adapter information via GetAdaptersInfo(). In this |
| module, we provide the necessary hooks to detect the |
| presence of iphlpapi and use it if necessary, but |
| comment things out for now to avoid compiler warnings. */ |
| |
| enum {MAX_INTERFACES = 50}; |
| |
| typedef int |
| (*PfnGetRealNetworkInterfaces) (jstring* pjstrName, |
| java::net::InetAddress** ppAddress); |
| |
| static int |
| winsock2GetRealNetworkInterfaces (jstring* pjstrName, |
| java::net::InetAddress** ppAddress) |
| { |
| // FIXME: Add IPv6 support. |
| |
| INTERFACE_INFO arInterfaceInfo[MAX_INTERFACES]; |
| |
| // Open a (random) socket to have a file descriptor for the WSAIoctl call. |
| SOCKET skt = ::socket (AF_INET, SOCK_DGRAM, 0); |
| if (skt == INVALID_SOCKET) |
| _Jv_ThrowSocketException (); |
| |
| DWORD dwOutBufSize; |
| int nRetCode = ::WSAIoctl (skt, SIO_GET_INTERFACE_LIST, |
| NULL, 0, &arInterfaceInfo, sizeof(arInterfaceInfo), |
| &dwOutBufSize, NULL, NULL); |
| |
| if (nRetCode == SOCKET_ERROR) |
| { |
| DWORD dwLastErrorCode = WSAGetLastError (); |
| ::closesocket (skt); |
| _Jv_ThrowSocketException (dwLastErrorCode); |
| } |
| |
| // Get addresses of all interfaces. |
| int nNbInterfaces = dwOutBufSize / sizeof(INTERFACE_INFO); |
| int nCurETHInterface = 0; |
| for (int i=0; i < nNbInterfaces; ++i) |
| { |
| int len = 4; |
| jbyteArray baddr = JvNewByteArray (len); |
| SOCKADDR_IN* pAddr = (SOCKADDR_IN*) &arInterfaceInfo[i].iiAddress; |
| memcpy (elements (baddr), &(pAddr->sin_addr), len); |
| |
| // Concoct a name for this interface. Since we don't |
| // have access to the real name under Winsock 2, we use |
| // "lo" for the loopback interface and ethX for the |
| // real ones. |
| TCHAR szName[30]; |
| u_long lFlags = arInterfaceInfo[i].iiFlags; |
| |
| if (lFlags & IFF_LOOPBACK) |
| _tcscpy (szName, _T("lo")); |
| else |
| { |
| _tcscpy (szName, _T("eth")); |
| wsprintf(szName+3, _T("%d"), nCurETHInterface++); |
| } |
| |
| jstring if_name = _Jv_Win32NewString (szName); |
| java::net::Inet4Address* address = |
| new java::net::Inet4Address (baddr, JvNewStringLatin1 ("")); |
| pjstrName[i] = if_name; |
| ppAddress[i] = address; |
| } |
| |
| ::closesocket (skt); |
| |
| return nNbInterfaces; |
| } |
| |
| /* |
| static int |
| iphlpapiGetRealNetworkInterfaces (jstring* pjstrName, |
| java::net::InetAddress** ppAddress) |
| { |
| return 0; |
| } |
| */ |
| |
| static PfnGetRealNetworkInterfaces |
| determineGetRealNetworkInterfacesFN () |
| { |
| /* FIXME: Try to dynamically load iphlpapi.dll and |
| detect the presence of GetAdaptersInfo() using |
| GetProcAddress(). If successful, return |
| iphlpapiGetRealNetworkInterfaces; if not, |
| return winsock2GetRealNetworkInterfaces */ |
| return &winsock2GetRealNetworkInterfaces; |
| } |
| |
| ::java::util::Vector* |
| java::net::VMNetworkInterface::getInterfaces () |
| { |
| // This next declaration used to be a static local, |
| // but this introduced a dependency on libsupc++ due |
| // to _cxa_guard_acquire and _cxa_guard_release. |
| // When Win95 is gone and we eventually get rid of |
| // winsock2GetRealNetworkInterfaces, we can rework |
| // all of this. Alternatively, we could move this all |
| // to win32.cc and initialize this at startup time, |
| // but that seems more trouble than it's worth at |
| // the moment. |
| PfnGetRealNetworkInterfaces pfn = |
| determineGetRealNetworkInterfacesFN (); |
| |
| jstring arIFName[MAX_INTERFACES]; |
| InetAddress* arpInetAddress[MAX_INTERFACES]; |
| ::java::util::Vector* ht = new ::java::util::Vector (); |
| |
| int nNbInterfaces = (*pfn) (arIFName, arpInetAddress); |
| for (int i=0; i < nNbInterfaces; ++i) |
| { |
| ht->add (new java::net::NetworkInterface (arIFName[i], |
| arpInetAddress[i])); |
| } |
| |
| return ht; |
| } |