1
2
3
4
5 package oshi.driver.unix;
6
7 import java.net.InetAddress;
8 import java.net.UnknownHostException;
9 import java.util.ArrayList;
10 import java.util.List;
11
12 import oshi.annotation.concurrent.ThreadSafe;
13 import oshi.software.os.InternetProtocolStats.IPConnection;
14 import oshi.software.os.InternetProtocolStats.TcpState;
15 import oshi.software.os.InternetProtocolStats.TcpStats;
16 import oshi.software.os.InternetProtocolStats.UdpStats;
17 import oshi.util.ExecutingCommand;
18 import oshi.util.ParseUtil;
19 import oshi.util.tuples.Pair;
20
21
22
23
24 @ThreadSafe
25 public final class NetStat {
26
27 private NetStat() {
28 }
29
30
31
32
33
34
35 public static Pair<Long, Long> queryTcpnetstat() {
36 long tcp4 = 0L;
37 long tcp6 = 0L;
38 List<String> activeConns = ExecutingCommand.runNative("netstat -n -p tcp");
39 for (String s : activeConns) {
40 if (s.endsWith("ESTABLISHED")) {
41 if (s.startsWith("tcp4")) {
42 tcp4++;
43 } else if (s.startsWith("tcp6")) {
44 tcp6++;
45 }
46 }
47 }
48 return new Pair<>(tcp4, tcp6);
49 }
50
51
52
53
54
55
56 public static List<IPConnection> queryNetstat() {
57 List<IPConnection> connections = new ArrayList<>();
58 List<String> activeConns = ExecutingCommand.runNative("netstat -n");
59 for (String s : activeConns) {
60 String[] split = null;
61 if (s.startsWith("tcp") || s.startsWith("udp")) {
62 split = ParseUtil.whitespaces.split(s);
63 if (split.length >= 5) {
64 String state = (split.length == 6) ? split[5] : null;
65
66 if ("SYN_RCVD".equals(state)) {
67 state = "SYN_RECV";
68 }
69 String type = split[0];
70 Pair<byte[], Integer> local = parseIP(split[3]);
71 Pair<byte[], Integer> foreign = parseIP(split[4]);
72 connections.add(new IPConnection(type, local.getA(), local.getB(), foreign.getA(), foreign.getB(),
73 state == null ? TcpState.NONE : TcpState.valueOf(state),
74 ParseUtil.parseIntOrDefault(split[2], 0), ParseUtil.parseIntOrDefault(split[1], 0), -1));
75 }
76 }
77 }
78 return connections;
79 }
80
81 private static Pair<byte[], Integer> parseIP(String s) {
82
83
84
85 int portPos = s.lastIndexOf('.');
86 if (portPos > 0 && s.length() > portPos) {
87 int port = ParseUtil.parseIntOrDefault(s.substring(portPos + 1), 0);
88 String ip = s.substring(0, portPos);
89 try {
90
91 return new Pair<>(InetAddress.getByName(ip).getAddress(), port);
92 } catch (UnknownHostException e) {
93 try {
94
95 if (ip.endsWith(":") && ip.contains("::")) {
96 ip = ip + "0";
97 } else if (ip.endsWith(":") || ip.contains("::")) {
98 ip = ip + ":0";
99 } else {
100 ip = ip + "::0";
101 }
102 return new Pair<>(InetAddress.getByName(ip).getAddress(), port);
103 } catch (UnknownHostException e2) {
104 return new Pair<>(new byte[0], port);
105 }
106 }
107 }
108 return new Pair<>(new byte[0], 0);
109 }
110
111
112
113
114
115
116
117 public static TcpStats queryTcpStats(String netstatStr) {
118 long connectionsEstablished = 0;
119 long connectionsActive = 0;
120 long connectionsPassive = 0;
121 long connectionFailures = 0;
122 long connectionsReset = 0;
123 long segmentsSent = 0;
124 long segmentsReceived = 0;
125 long segmentsRetransmitted = 0;
126 long inErrors = 0;
127 long outResets = 0;
128 List<String> netstat = ExecutingCommand.runNative(netstatStr);
129 for (String s : netstat) {
130 String[] split = s.trim().split(" ", 2);
131 if (split.length == 2) {
132 switch (split[1]) {
133 case "connections established":
134 case "connection established (including accepts)":
135 case "connections established (including accepts)":
136 connectionsEstablished = ParseUtil.parseLongOrDefault(split[0], 0L);
137 break;
138 case "active connection openings":
139 connectionsActive = ParseUtil.parseLongOrDefault(split[0], 0L);
140 break;
141 case "passive connection openings":
142 connectionsPassive = ParseUtil.parseLongOrDefault(split[0], 0L);
143 break;
144 case "failed connection attempts":
145 case "bad connection attempts":
146 connectionFailures = ParseUtil.parseLongOrDefault(split[0], 0L);
147 break;
148 case "connection resets received":
149 case "dropped due to RST":
150 connectionsReset = ParseUtil.parseLongOrDefault(split[0], 0L);
151 break;
152 case "segments sent out":
153 case "packet sent":
154 case "packets sent":
155 segmentsSent = ParseUtil.parseLongOrDefault(split[0], 0L);
156 break;
157 case "segments received":
158 case "packet received":
159 case "packets received":
160 segmentsReceived = ParseUtil.parseLongOrDefault(split[0], 0L);
161 break;
162 case "segments retransmitted":
163 segmentsRetransmitted = ParseUtil.parseLongOrDefault(split[0], 0L);
164 break;
165 case "bad segments received":
166 case "discarded for bad checksum":
167 case "discarded for bad checksums":
168 case "discarded for bad header offset field":
169 case "discarded for bad header offset fields":
170 case "discarded because packet too short":
171 case "discarded for missing IPsec protection":
172 inErrors += ParseUtil.parseLongOrDefault(split[0], 0L);
173 break;
174 case "resets sent":
175 outResets = ParseUtil.parseLongOrDefault(split[0], 0L);
176 break;
177 default:
178
179 if (split[1].contains("retransmitted") && split[1].contains("data packet")) {
180 segmentsRetransmitted += ParseUtil.parseLongOrDefault(split[0], 0L);
181 }
182 break;
183 }
184
185 }
186
187 }
188 return new TcpStats(connectionsEstablished, connectionsActive, connectionsPassive, connectionFailures,
189 connectionsReset, segmentsSent, segmentsReceived, segmentsRetransmitted, inErrors, outResets);
190 }
191
192
193
194
195
196
197
198 public static UdpStats queryUdpStats(String netstatStr) {
199 long datagramsSent = 0;
200 long datagramsReceived = 0;
201 long datagramsNoPort = 0;
202 long datagramsReceivedErrors = 0;
203 List<String> netstat = ExecutingCommand.runNative(netstatStr);
204 for (String s : netstat) {
205 String[] split = s.trim().split(" ", 2);
206 if (split.length == 2) {
207 switch (split[1]) {
208 case "packets sent":
209 case "datagram output":
210 case "datagrams output":
211 datagramsSent = ParseUtil.parseLongOrDefault(split[0], 0L);
212 break;
213 case "packets received":
214 case "datagram received":
215 case "datagrams received":
216 datagramsReceived = ParseUtil.parseLongOrDefault(split[0], 0L);
217 break;
218 case "packets to unknown port received":
219 case "dropped due to no socket":
220 case "broadcast/multicast datagram dropped due to no socket":
221 case "broadcast/multicast datagrams dropped due to no socket":
222 datagramsNoPort += ParseUtil.parseLongOrDefault(split[0], 0L);
223 break;
224 case "packet receive errors":
225 case "with incomplete header":
226 case "with bad data length field":
227 case "with bad checksum":
228 case "woth no checksum":
229 datagramsReceivedErrors += ParseUtil.parseLongOrDefault(split[0], 0L);
230 break;
231 default:
232 break;
233 }
234 }
235 }
236 return new UdpStats(datagramsSent, datagramsReceived, datagramsNoPort, datagramsReceivedErrors);
237 }
238 }