View Javadoc
1   /*
2    * Copyright 2017-2023 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.software.os.windows;
6   
7   import java.nio.charset.StandardCharsets;
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.Memory;
15  import com.sun.jna.Native;
16  import com.sun.jna.platform.win32.IPHlpAPI;
17  import com.sun.jna.platform.win32.IPHlpAPI.FIXED_INFO;
18  import com.sun.jna.platform.win32.IPHlpAPI.IP_ADDR_STRING;
19  import com.sun.jna.platform.win32.Kernel32;
20  import com.sun.jna.platform.win32.Kernel32Util;
21  import com.sun.jna.platform.win32.Win32Exception;
22  import com.sun.jna.platform.win32.WinError;
23  
24  import oshi.annotation.concurrent.ThreadSafe;
25  import oshi.jna.ByRef.CloseableIntByReference;
26  import oshi.software.common.AbstractNetworkParams;
27  import oshi.util.ExecutingCommand;
28  import oshi.util.ParseUtil;
29  
30  /**
31   * WindowsNetworkParams class.
32   */
33  @ThreadSafe
34  final class WindowsNetworkParams extends AbstractNetworkParams {
35  
36      private static final Logger LOG = LoggerFactory.getLogger(WindowsNetworkParams.class);
37  
38      private static final int COMPUTER_NAME_DNS_DOMAIN_FULLY_QUALIFIED = 3;
39  
40      @Override
41      public String getDomainName() {
42          char[] buffer = new char[256];
43          try (CloseableIntByReference bufferSize = new CloseableIntByReference(buffer.length)) {
44              if (!Kernel32.INSTANCE.GetComputerNameEx(COMPUTER_NAME_DNS_DOMAIN_FULLY_QUALIFIED, buffer, bufferSize)) {
45                  LOG.error("Failed to get dns domain name. Error code: {}", Kernel32.INSTANCE.GetLastError());
46                  return "";
47              }
48          }
49          return Native.toString(buffer);
50      }
51  
52      @Override
53      public String[] getDnsServers() {
54          try (CloseableIntByReference bufferSize = new CloseableIntByReference()) {
55              int ret = IPHlpAPI.INSTANCE.GetNetworkParams(null, bufferSize);
56              if (ret != WinError.ERROR_BUFFER_OVERFLOW) {
57                  LOG.error("Failed to get network parameters buffer size. Error code: {}", ret);
58                  return new String[0];
59              }
60  
61              try (Memory buffer = new Memory(bufferSize.getValue())) {
62                  ret = IPHlpAPI.INSTANCE.GetNetworkParams(buffer, bufferSize);
63                  if (ret != 0) {
64                      LOG.error("Failed to get network parameters. Error code: {}", ret);
65                      return new String[0];
66                  }
67                  FIXED_INFO fixedInfo = new FIXED_INFO(buffer);
68  
69                  List<String> list = new ArrayList<>();
70                  IP_ADDR_STRING dns = fixedInfo.DnsServerList;
71                  while (dns != null) {
72                      // a char array of size 16.
73                      // This array holds an IPv4 address in dotted decimal notation.
74                      String addr = Native.toString(dns.IpAddress.String, StandardCharsets.US_ASCII);
75                      int nullPos = addr.indexOf(0);
76                      if (nullPos != -1) {
77                          addr = addr.substring(0, nullPos);
78                      }
79                      list.add(addr);
80                      dns = dns.Next;
81                  }
82                  return list.toArray(new String[0]);
83              }
84          }
85      }
86  
87      @Override
88      public String getHostName() {
89          try {
90              return Kernel32Util.getComputerName();
91          } catch (Win32Exception e) {
92              return super.getHostName();
93          }
94      }
95  
96      @Override
97      public String getIpv4DefaultGateway() {
98          return parseIpv4Route();
99      }
100 
101     @Override
102     public String getIpv6DefaultGateway() {
103         return parseIpv6Route();
104     }
105 
106     private static String parseIpv4Route() {
107         List<String> lines = ExecutingCommand.runNative("route print -4 0.0.0.0");
108         for (String line : lines) {
109             String[] fields = ParseUtil.whitespaces.split(line.trim());
110             if (fields.length > 2 && "0.0.0.0".equals(fields[0])) {
111                 return fields[2];
112             }
113         }
114         return "";
115     }
116 
117     private static String parseIpv6Route() {
118         List<String> lines = ExecutingCommand.runNative("route print -6 ::/0");
119         for (String line : lines) {
120             String[] fields = ParseUtil.whitespaces.split(line.trim());
121             if (fields.length > 3 && "::/0".equals(fields[2])) {
122                 return fields[3];
123             }
124         }
125         return "";
126     }
127 }