| /* 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; | |
| } |