View Javadoc
1   /*
2    * Copyright 2020-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.platform.windows;
6   
7   import java.net.NetworkInterface;
8   import java.util.ArrayList;
9   import java.util.List;
10  
11  import org.slf4j.Logger;
12  import org.slf4j.LoggerFactory;
13  
14  import com.sun.jna.Native;
15  import com.sun.jna.platform.win32.IPHlpAPI;
16  import com.sun.jna.platform.win32.VersionHelpers;
17  
18  import oshi.annotation.concurrent.ThreadSafe;
19  import oshi.hardware.NetworkIF;
20  import oshi.hardware.common.AbstractNetworkIF;
21  import oshi.jna.Struct.CloseableMibIfRow;
22  import oshi.jna.Struct.CloseableMibIfRow2;
23  import oshi.util.ParseUtil;
24  
25  /**
26   * WindowsNetworks class.
27   */
28  @ThreadSafe
29  public final class WindowsNetworkIF extends AbstractNetworkIF {
30  
31      private static final Logger LOG = LoggerFactory.getLogger(WindowsNetworkIF.class);
32  
33      private static final boolean IS_VISTA_OR_GREATER = VersionHelpers.IsWindowsVistaOrGreater();
34      private static final byte CONNECTOR_PRESENT_BIT = 0b00000100;
35  
36      private int ifType;
37      private int ndisPhysicalMediumType;
38      private boolean connectorPresent;
39      private long bytesRecv;
40      private long bytesSent;
41      private long packetsRecv;
42      private long packetsSent;
43      private long inErrors;
44      private long outErrors;
45      private long inDrops;
46      private long collisions;
47      private long speed;
48      private long timeStamp;
49      private String ifAlias;
50      private IfOperStatus ifOperStatus;
51  
52      public WindowsNetworkIF(NetworkInterface netint) throws InstantiationException {
53          super(netint);
54          updateAttributes();
55      }
56  
57      /**
58       * Gets all network interfaces on this machine
59       *
60       * @param includeLocalInterfaces include local interfaces in the result
61       * @return A list of {@link NetworkIF} objects representing the interfaces
62       */
63      public static List<NetworkIF> getNetworks(boolean includeLocalInterfaces) {
64          List<NetworkIF> ifList = new ArrayList<>();
65          for (NetworkInterface ni : getNetworkInterfaces(includeLocalInterfaces)) {
66              try {
67                  ifList.add(new WindowsNetworkIF(ni));
68              } catch (InstantiationException e) {
69                  LOG.debug("Network Interface Instantiation failed: {}", e.getMessage());
70              }
71          }
72          return ifList;
73      }
74  
75      @Override
76      public int getIfType() {
77          return this.ifType;
78      }
79  
80      @Override
81      public int getNdisPhysicalMediumType() {
82          return this.ndisPhysicalMediumType;
83      }
84  
85      @Override
86      public boolean isConnectorPresent() {
87          return this.connectorPresent;
88      }
89  
90      @Override
91      public long getBytesRecv() {
92          return this.bytesRecv;
93      }
94  
95      @Override
96      public long getBytesSent() {
97          return this.bytesSent;
98      }
99  
100     @Override
101     public long getPacketsRecv() {
102         return this.packetsRecv;
103     }
104 
105     @Override
106     public long getPacketsSent() {
107         return this.packetsSent;
108     }
109 
110     @Override
111     public long getInErrors() {
112         return this.inErrors;
113     }
114 
115     @Override
116     public long getOutErrors() {
117         return this.outErrors;
118     }
119 
120     @Override
121     public long getInDrops() {
122         return this.inDrops;
123     }
124 
125     @Override
126     public long getCollisions() {
127         return this.collisions;
128     }
129 
130     @Override
131     public long getSpeed() {
132         return this.speed;
133     }
134 
135     @Override
136     public long getTimeStamp() {
137         return this.timeStamp;
138     }
139 
140     @Override
141     public String getIfAlias() {
142         return ifAlias;
143     }
144 
145     @Override
146     public IfOperStatus getIfOperStatus() {
147         return ifOperStatus;
148     }
149 
150     @Override
151     public boolean updateAttributes() {
152         // MIB_IFROW2 requires Vista (6.0) or later.
153         if (IS_VISTA_OR_GREATER) {
154             // Create new MIB_IFROW2 and set index to this interface index
155             try (CloseableMibIfRow2 ifRow = new CloseableMibIfRow2()) {
156                 ifRow.InterfaceIndex = queryNetworkInterface().getIndex();
157                 if (0 != IPHlpAPI.INSTANCE.GetIfEntry2(ifRow)) {
158                     // Error, abort
159                     LOG.error("Failed to retrieve data for interface {}, {}", queryNetworkInterface().getIndex(),
160                             getName());
161                     return false;
162                 }
163                 this.ifType = ifRow.Type;
164                 this.ndisPhysicalMediumType = ifRow.PhysicalMediumType;
165                 this.connectorPresent = (ifRow.InterfaceAndOperStatusFlags & CONNECTOR_PRESENT_BIT) > 0;
166                 this.bytesSent = ifRow.OutOctets;
167                 this.bytesRecv = ifRow.InOctets;
168                 this.packetsSent = ifRow.OutUcastPkts;
169                 this.packetsRecv = ifRow.InUcastPkts;
170                 this.outErrors = ifRow.OutErrors;
171                 this.inErrors = ifRow.InErrors;
172                 this.collisions = ifRow.OutDiscards; // closest proxy
173                 this.inDrops = ifRow.InDiscards; // closest proxy
174                 this.speed = ifRow.ReceiveLinkSpeed;
175                 this.ifAlias = Native.toString(ifRow.Alias);
176                 this.ifOperStatus = IfOperStatus.byValue(ifRow.OperStatus);
177             }
178         } else {
179             // Create new MIB_IFROW and set index to this interface index
180             try (CloseableMibIfRow ifRow = new CloseableMibIfRow()) {
181                 ifRow.dwIndex = queryNetworkInterface().getIndex();
182                 if (0 != IPHlpAPI.INSTANCE.GetIfEntry(ifRow)) {
183                     // Error, abort
184                     LOG.error("Failed to retrieve data for interface {}, {}", queryNetworkInterface().getIndex(),
185                             getName());
186                     return false;
187                 }
188                 this.ifType = ifRow.dwType;
189                 // These are unsigned ints. Widen them to longs.
190                 this.bytesSent = ParseUtil.unsignedIntToLong(ifRow.dwOutOctets);
191                 this.bytesRecv = ParseUtil.unsignedIntToLong(ifRow.dwInOctets);
192                 this.packetsSent = ParseUtil.unsignedIntToLong(ifRow.dwOutUcastPkts);
193                 this.packetsRecv = ParseUtil.unsignedIntToLong(ifRow.dwInUcastPkts);
194                 this.outErrors = ParseUtil.unsignedIntToLong(ifRow.dwOutErrors);
195                 this.inErrors = ParseUtil.unsignedIntToLong(ifRow.dwInErrors);
196                 this.collisions = ParseUtil.unsignedIntToLong(ifRow.dwOutDiscards); // closest proxy
197                 this.inDrops = ParseUtil.unsignedIntToLong(ifRow.dwInDiscards); // closest proxy
198                 this.speed = ParseUtil.unsignedIntToLong(ifRow.dwSpeed);
199                 this.ifAlias = ""; // not supported by MIB_IFROW
200                 this.ifOperStatus = IfOperStatus.UNKNOWN; // not supported
201             }
202         }
203         this.timeStamp = System.currentTimeMillis();
204         return true;
205     }
206 }