1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "iphlp_interface.hpp"
  26 #include "runtime/os.hpp"
  27 
  28 // IPHLP API
  29 typedef DWORD(WINAPI *GetIfTable2_Fn)(PMIB_IF_TABLE2*);
  30 typedef DWORD(WINAPI *FreeMibTable_Fn)(PVOID);
  31 
  32 // IPHLP statics
  33 GetIfTable2_Fn IphlpDll::_GetIfTable2 = NULL;
  34 FreeMibTable_Fn IphlpDll::_FreeMibTable = NULL;
  35 
  36 LONG IphlpDll::_critical_section = 0;
  37 LONG IphlpDll::_initialized = 0;
  38 LONG IphlpDll::_iphlp_reference_count = 0;
  39 HMODULE IphlpDll::_hModule = NULL;
  40 
  41 void IphlpDll::initialize(void) {
  42   _hModule = os::win32::load_Windows_dll("iphlpapi.dll", NULL, 0);
  43 
  44   if (NULL == _hModule) {
  45     return;
  46   }
  47 
  48   // The 'A' at the end means the ANSI (not the UNICODE) vesions of the methods
  49   _GetIfTable2 = (GetIfTable2_Fn)::GetProcAddress(_hModule, "GetIfTable2");
  50   _FreeMibTable = (FreeMibTable_Fn)::GetProcAddress(_hModule, "FreeMibTable");
  51 
  52   // interlock is used for fencing
  53   InterlockedExchange(&_initialized, 1);
  54 }
  55 
  56 bool IphlpDll::IphlpDetach(void) {
  57   LONG prev_ref_count = InterlockedExchangeAdd(&_iphlp_reference_count, -1);
  58   BOOL ret = false;
  59 
  60   if (1 == prev_ref_count) {
  61     if (_initialized && _hModule != NULL) {
  62       ret = FreeLibrary(_hModule);
  63       if (ret) {
  64         _hModule = NULL;
  65         _GetIfTable2 = NULL;
  66         _FreeMibTable = NULL;
  67         InterlockedExchange(&_initialized, 0);
  68       }
  69     }
  70   }
  71   return ret != 0;
  72 }
  73 
  74 bool IphlpDll::IphlpAttach(void) {
  75   InterlockedExchangeAdd(&_iphlp_reference_count, 1);
  76 
  77   if (1 == _initialized) {
  78     return true;
  79   }
  80 
  81   while (InterlockedCompareExchange(&_critical_section, 1, 0) == 1);
  82 
  83   if (0 == _initialized) {
  84     initialize();
  85   }
  86 
  87   while (InterlockedCompareExchange(&_critical_section, 0, 1) == 0);
  88 
  89   return (_GetIfTable2 != NULL && _FreeMibTable != NULL);
  90 }
  91 
  92 DWORD IphlpDll::GetIfTable2(PMIB_IF_TABLE2* Table) {
  93   assert(_initialized && _GetIfTable2 != NULL,
  94          "IphlpAttach() not yet called");
  95 
  96   return _GetIfTable2(Table);
  97 }
  98 
  99 DWORD IphlpDll::FreeMibTable(PVOID Memory) {
 100   assert(_initialized && _FreeMibTable != NULL,
 101          "IphlpAttach() not yet called");
 102 
 103   return _FreeMibTable(Memory);
 104 }