1
2
3
4
5 package oshi.hardware.common;
6
7 import static oshi.util.Memoizer.memoize;
8
9 import java.net.InetAddress;
10 import java.net.InterfaceAddress;
11 import java.net.NetworkInterface;
12 import java.net.SocketException;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Collections;
16 import java.util.Enumeration;
17 import java.util.List;
18 import java.util.Locale;
19 import java.util.Properties;
20 import java.util.function.Supplier;
21 import java.util.stream.Collectors;
22
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import oshi.annotation.concurrent.ThreadSafe;
27 import oshi.hardware.NetworkIF;
28 import oshi.util.Constants;
29 import oshi.util.FileUtil;
30 import oshi.util.FormatUtil;
31 import oshi.util.ParseUtil;
32
33
34
35
36 @ThreadSafe
37 public abstract class AbstractNetworkIF implements NetworkIF {
38
39 private static final Logger LOG = LoggerFactory.getLogger(AbstractNetworkIF.class);
40
41 private static final String OSHI_VM_MAC_ADDR_PROPERTIES = "oshi.vmmacaddr.properties";
42
43 private NetworkInterface networkInterface;
44 private String name;
45 private String displayName;
46 private int index;
47 private long mtu;
48 private String mac;
49 private String[] ipv4;
50 private Short[] subnetMasks;
51 private String[] ipv6;
52 private Short[] prefixLengths;
53
54 private final Supplier<Properties> vmMacAddrProps = memoize(AbstractNetworkIF::queryVmMacAddrProps);
55
56
57
58
59
60
61
62 protected AbstractNetworkIF(NetworkInterface netint) throws InstantiationException {
63 this(netint, netint.getDisplayName());
64 }
65
66
67
68
69
70
71
72
73 protected AbstractNetworkIF(NetworkInterface netint, String displayName) throws InstantiationException {
74 this.networkInterface = netint;
75 try {
76 this.name = networkInterface.getName();
77 this.displayName = displayName;
78 this.index = networkInterface.getIndex();
79
80 this.mtu = ParseUtil.unsignedIntToLong(networkInterface.getMTU());
81
82 byte[] hwmac = networkInterface.getHardwareAddress();
83 if (hwmac != null) {
84 List<String> octets = new ArrayList<>(6);
85 for (byte b : hwmac) {
86 octets.add(String.format(Locale.ROOT, "%02x", b));
87 }
88 this.mac = String.join(":", octets);
89 } else {
90 this.mac = Constants.UNKNOWN;
91 }
92
93 ArrayList<String> ipv4list = new ArrayList<>();
94 ArrayList<Short> subnetMaskList = new ArrayList<>();
95 ArrayList<String> ipv6list = new ArrayList<>();
96 ArrayList<Short> prefixLengthList = new ArrayList<>();
97
98 for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
99 InetAddress address = interfaceAddress.getAddress();
100 if (address.getHostAddress().length() > 0) {
101 if (address.getHostAddress().contains(":")) {
102 ipv6list.add(address.getHostAddress().split("%")[0]);
103 prefixLengthList.add(interfaceAddress.getNetworkPrefixLength());
104 } else {
105 ipv4list.add(address.getHostAddress());
106 subnetMaskList.add(interfaceAddress.getNetworkPrefixLength());
107 }
108 }
109 }
110
111 this.ipv4 = ipv4list.toArray(new String[0]);
112 this.subnetMasks = subnetMaskList.toArray(new Short[0]);
113 this.ipv6 = ipv6list.toArray(new String[0]);
114 this.prefixLengths = prefixLengthList.toArray(new Short[0]);
115 } catch (SocketException e) {
116 throw new InstantiationException(e.getMessage());
117 }
118 }
119
120
121
122
123
124
125
126 protected static List<NetworkInterface> getNetworkInterfaces(boolean includeLocalInterfaces) {
127 List<NetworkInterface> interfaces = getAllNetworkInterfaces();
128
129 return includeLocalInterfaces ? interfaces
130 : getAllNetworkInterfaces().stream().parallel().filter(ni -> !isLocalInterface(ni))
131 .collect(Collectors.toList());
132 }
133
134
135
136
137
138
139 private static List<NetworkInterface> getAllNetworkInterfaces() {
140 try {
141 Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
142 return interfaces == null ? Collections.emptyList() : Collections.list(interfaces);
143 } catch (SocketException ex) {
144 LOG.error("Socket exception when retrieving interfaces: {}", ex.getMessage());
145 }
146 return Collections.emptyList();
147 }
148
149 private static boolean isLocalInterface(NetworkInterface networkInterface) {
150 try {
151
152 return networkInterface.getHardwareAddress() == null;
153 } catch (SocketException e) {
154 LOG.error("Socket exception when retrieving interface information for {}: {}", networkInterface,
155 e.getMessage());
156 }
157 return false;
158 }
159
160 @Override
161 public NetworkInterface queryNetworkInterface() {
162 return this.networkInterface;
163 }
164
165 @Override
166 public String getName() {
167 return this.name;
168 }
169
170 @Override
171 public int getIndex() {
172 return this.index;
173 }
174
175 @Override
176 public String getDisplayName() {
177 return this.displayName;
178 }
179
180 @Override
181 public long getMTU() {
182 return this.mtu;
183 }
184
185 @Override
186 public String getMacaddr() {
187 return this.mac;
188 }
189
190 @Override
191 public String[] getIPv4addr() {
192 return Arrays.copyOf(this.ipv4, this.ipv4.length);
193 }
194
195 @Override
196 public Short[] getSubnetMasks() {
197 return Arrays.copyOf(this.subnetMasks, this.subnetMasks.length);
198 }
199
200 @Override
201 public String[] getIPv6addr() {
202 return Arrays.copyOf(this.ipv6, this.ipv6.length);
203 }
204
205 @Override
206 public Short[] getPrefixLengths() {
207 return Arrays.copyOf(this.prefixLengths, this.prefixLengths.length);
208 }
209
210 @Override
211 public boolean isKnownVmMacAddr() {
212 String oui = getMacaddr().length() > 7 ? getMacaddr().substring(0, 8) : getMacaddr();
213 return this.vmMacAddrProps.get().containsKey(oui.toUpperCase(Locale.ROOT));
214 }
215
216 private static Properties queryVmMacAddrProps() {
217 return FileUtil.readPropertiesFromFilename(OSHI_VM_MAC_ADDR_PROPERTIES);
218 }
219
220 @Override
221 public String toString() {
222 StringBuilder sb = new StringBuilder();
223 sb.append("Name: ").append(getName());
224 if (!getName().equals(getDisplayName())) {
225 sb.append(" (").append(getDisplayName()).append(")");
226 }
227 if (!getIfAlias().isEmpty()) {
228 sb.append(" [IfAlias=").append(getIfAlias()).append("]");
229 }
230 sb.append("\n");
231 sb.append(" MAC Address: ").append(getMacaddr()).append("\n");
232 sb.append(" MTU: ").append(getMTU()).append(", ").append("Speed: ").append(getSpeed()).append("\n");
233 String[] ipv4withmask = getIPv4addr();
234 if (this.ipv4.length == this.subnetMasks.length) {
235 for (int i = 0; i < this.subnetMasks.length; i++) {
236 ipv4withmask[i] += "/" + this.subnetMasks[i];
237 }
238 }
239 sb.append(" IPv4: ").append(Arrays.toString(ipv4withmask)).append("\n");
240 String[] ipv6withprefixlength = getIPv6addr();
241 if (this.ipv6.length == this.prefixLengths.length) {
242 for (int j = 0; j < this.prefixLengths.length; j++) {
243 ipv6withprefixlength[j] += "/" + this.prefixLengths[j];
244 }
245 }
246 sb.append(" IPv6: ").append(Arrays.toString(ipv6withprefixlength)).append("\n");
247 sb.append(" Traffic: received ").append(getPacketsRecv()).append(" packets/")
248 .append(FormatUtil.formatBytes(getBytesRecv())).append(" (" + getInErrors() + " err, ")
249 .append(getInDrops() + " drop);");
250 sb.append(" transmitted ").append(getPacketsSent()).append(" packets/")
251 .append(FormatUtil.formatBytes(getBytesSent())).append(" (" + getOutErrors() + " err, ")
252 .append(getCollisions() + " coll);");
253 return sb.toString();
254 }
255 }