aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/net/natVMNetworkInterfaceWin32.cc
blob: 257e06d1778e79baac09f32b5d28841a9e97644d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* 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/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;
}