1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * INET An implementation of the TCP/IP protocol suite for the LINUX |
4 | * operating system. INET is implemented using the BSD Socket |
5 | * interface as the means of communication with the user level. |
6 | * |
7 | * This file implements the various access functions for the |
8 | * PROC file system. It is mainly used for debugging and |
9 | * statistics. |
10 | * |
11 | * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de> |
13 | * Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de> |
14 | * Erik Schoenfelder, <schoenfr@ibr.cs.tu-bs.de> |
15 | * |
16 | * Fixes: |
17 | * Alan Cox : UDP sockets show the rxqueue/txqueue |
18 | * using hint flag for the netinfo. |
19 | * Pauline Middelink : identd support |
20 | * Alan Cox : Make /proc safer. |
21 | * Erik Schoenfelder : /proc/net/snmp |
22 | * Alan Cox : Handle dead sockets properly. |
23 | * Gerhard Koerting : Show both timers |
24 | * Alan Cox : Allow inode to be NULL (kernel socket) |
25 | * Andi Kleen : Add support for open_requests and |
26 | * split functions for more readibility. |
27 | * Andi Kleen : Add support for /proc/net/netstat |
28 | * Arnaldo C. Melo : Convert to seq_file |
29 | */ |
30 | #include <linux/types.h> |
31 | #include <net/net_namespace.h> |
32 | #include <net/icmp.h> |
33 | #include <net/protocol.h> |
34 | #include <net/tcp.h> |
35 | #include <net/mptcp.h> |
36 | #include <net/udp.h> |
37 | #include <net/udplite.h> |
38 | #include <linux/bottom_half.h> |
39 | #include <linux/inetdevice.h> |
40 | #include <linux/proc_fs.h> |
41 | #include <linux/seq_file.h> |
42 | #include <linux/export.h> |
43 | #include <net/sock.h> |
44 | #include <net/raw.h> |
45 | |
46 | #define TCPUDP_MIB_MAX max_t(u32, UDP_MIB_MAX, TCP_MIB_MAX) |
47 | |
48 | /* |
49 | * Report socket allocation statistics [mea@utu.fi] |
50 | */ |
51 | static int sockstat_seq_show(struct seq_file *seq, void *v) |
52 | { |
53 | struct net *net = seq->private; |
54 | int orphans, sockets; |
55 | |
56 | orphans = tcp_orphan_count_sum(); |
57 | sockets = proto_sockets_allocated_sum_positive(prot: &tcp_prot); |
58 | |
59 | socket_seq_show(seq); |
60 | seq_printf(m: seq, fmt: "TCP: inuse %d orphan %d tw %d alloc %d mem %ld\n" , |
61 | sock_prot_inuse_get(net, proto: &tcp_prot), orphans, |
62 | refcount_read(r: &net->ipv4.tcp_death_row.tw_refcount) - 1, |
63 | sockets, proto_memory_allocated(prot: &tcp_prot)); |
64 | seq_printf(m: seq, fmt: "UDP: inuse %d mem %ld\n" , |
65 | sock_prot_inuse_get(net, proto: &udp_prot), |
66 | proto_memory_allocated(prot: &udp_prot)); |
67 | seq_printf(m: seq, fmt: "UDPLITE: inuse %d\n" , |
68 | sock_prot_inuse_get(net, proto: &udplite_prot)); |
69 | seq_printf(m: seq, fmt: "RAW: inuse %d\n" , |
70 | sock_prot_inuse_get(net, proto: &raw_prot)); |
71 | seq_printf(m: seq, fmt: "FRAG: inuse %u memory %lu\n" , |
72 | atomic_read(v: &net->ipv4.fqdir->rhashtable.nelems), |
73 | frag_mem_limit(fqdir: net->ipv4.fqdir)); |
74 | return 0; |
75 | } |
76 | |
77 | /* snmp items */ |
78 | static const struct snmp_mib snmp4_ipstats_list[] = { |
79 | SNMP_MIB_ITEM("InReceives" , IPSTATS_MIB_INPKTS), |
80 | SNMP_MIB_ITEM("InHdrErrors" , IPSTATS_MIB_INHDRERRORS), |
81 | SNMP_MIB_ITEM("InAddrErrors" , IPSTATS_MIB_INADDRERRORS), |
82 | SNMP_MIB_ITEM("ForwDatagrams" , IPSTATS_MIB_OUTFORWDATAGRAMS), |
83 | SNMP_MIB_ITEM("InUnknownProtos" , IPSTATS_MIB_INUNKNOWNPROTOS), |
84 | SNMP_MIB_ITEM("InDiscards" , IPSTATS_MIB_INDISCARDS), |
85 | SNMP_MIB_ITEM("InDelivers" , IPSTATS_MIB_INDELIVERS), |
86 | SNMP_MIB_ITEM("OutRequests" , IPSTATS_MIB_OUTREQUESTS), |
87 | SNMP_MIB_ITEM("OutDiscards" , IPSTATS_MIB_OUTDISCARDS), |
88 | SNMP_MIB_ITEM("OutNoRoutes" , IPSTATS_MIB_OUTNOROUTES), |
89 | SNMP_MIB_ITEM("ReasmTimeout" , IPSTATS_MIB_REASMTIMEOUT), |
90 | SNMP_MIB_ITEM("ReasmReqds" , IPSTATS_MIB_REASMREQDS), |
91 | SNMP_MIB_ITEM("ReasmOKs" , IPSTATS_MIB_REASMOKS), |
92 | SNMP_MIB_ITEM("ReasmFails" , IPSTATS_MIB_REASMFAILS), |
93 | SNMP_MIB_ITEM("FragOKs" , IPSTATS_MIB_FRAGOKS), |
94 | SNMP_MIB_ITEM("FragFails" , IPSTATS_MIB_FRAGFAILS), |
95 | SNMP_MIB_ITEM("FragCreates" , IPSTATS_MIB_FRAGCREATES), |
96 | SNMP_MIB_ITEM("OutTransmits" , IPSTATS_MIB_OUTPKTS), |
97 | SNMP_MIB_SENTINEL |
98 | }; |
99 | |
100 | /* Following items are displayed in /proc/net/netstat */ |
101 | static const struct snmp_mib snmp4_ipextstats_list[] = { |
102 | SNMP_MIB_ITEM("InNoRoutes" , IPSTATS_MIB_INNOROUTES), |
103 | SNMP_MIB_ITEM("InTruncatedPkts" , IPSTATS_MIB_INTRUNCATEDPKTS), |
104 | SNMP_MIB_ITEM("InMcastPkts" , IPSTATS_MIB_INMCASTPKTS), |
105 | SNMP_MIB_ITEM("OutMcastPkts" , IPSTATS_MIB_OUTMCASTPKTS), |
106 | SNMP_MIB_ITEM("InBcastPkts" , IPSTATS_MIB_INBCASTPKTS), |
107 | SNMP_MIB_ITEM("OutBcastPkts" , IPSTATS_MIB_OUTBCASTPKTS), |
108 | SNMP_MIB_ITEM("InOctets" , IPSTATS_MIB_INOCTETS), |
109 | SNMP_MIB_ITEM("OutOctets" , IPSTATS_MIB_OUTOCTETS), |
110 | SNMP_MIB_ITEM("InMcastOctets" , IPSTATS_MIB_INMCASTOCTETS), |
111 | SNMP_MIB_ITEM("OutMcastOctets" , IPSTATS_MIB_OUTMCASTOCTETS), |
112 | SNMP_MIB_ITEM("InBcastOctets" , IPSTATS_MIB_INBCASTOCTETS), |
113 | SNMP_MIB_ITEM("OutBcastOctets" , IPSTATS_MIB_OUTBCASTOCTETS), |
114 | /* Non RFC4293 fields */ |
115 | SNMP_MIB_ITEM("InCsumErrors" , IPSTATS_MIB_CSUMERRORS), |
116 | SNMP_MIB_ITEM("InNoECTPkts" , IPSTATS_MIB_NOECTPKTS), |
117 | SNMP_MIB_ITEM("InECT1Pkts" , IPSTATS_MIB_ECT1PKTS), |
118 | SNMP_MIB_ITEM("InECT0Pkts" , IPSTATS_MIB_ECT0PKTS), |
119 | SNMP_MIB_ITEM("InCEPkts" , IPSTATS_MIB_CEPKTS), |
120 | SNMP_MIB_ITEM("ReasmOverlaps" , IPSTATS_MIB_REASM_OVERLAPS), |
121 | SNMP_MIB_SENTINEL |
122 | }; |
123 | |
124 | static const struct { |
125 | const char *name; |
126 | int index; |
127 | } icmpmibmap[] = { |
128 | { "DestUnreachs" , ICMP_DEST_UNREACH }, |
129 | { "TimeExcds" , ICMP_TIME_EXCEEDED }, |
130 | { "ParmProbs" , ICMP_PARAMETERPROB }, |
131 | { "SrcQuenchs" , ICMP_SOURCE_QUENCH }, |
132 | { "Redirects" , ICMP_REDIRECT }, |
133 | { "Echos" , ICMP_ECHO }, |
134 | { "EchoReps" , ICMP_ECHOREPLY }, |
135 | { "Timestamps" , ICMP_TIMESTAMP }, |
136 | { "TimestampReps" , ICMP_TIMESTAMPREPLY }, |
137 | { "AddrMasks" , ICMP_ADDRESS }, |
138 | { "AddrMaskReps" , ICMP_ADDRESSREPLY }, |
139 | { NULL, 0 } |
140 | }; |
141 | |
142 | |
143 | static const struct snmp_mib snmp4_tcp_list[] = { |
144 | SNMP_MIB_ITEM("RtoAlgorithm" , TCP_MIB_RTOALGORITHM), |
145 | SNMP_MIB_ITEM("RtoMin" , TCP_MIB_RTOMIN), |
146 | SNMP_MIB_ITEM("RtoMax" , TCP_MIB_RTOMAX), |
147 | SNMP_MIB_ITEM("MaxConn" , TCP_MIB_MAXCONN), |
148 | SNMP_MIB_ITEM("ActiveOpens" , TCP_MIB_ACTIVEOPENS), |
149 | SNMP_MIB_ITEM("PassiveOpens" , TCP_MIB_PASSIVEOPENS), |
150 | SNMP_MIB_ITEM("AttemptFails" , TCP_MIB_ATTEMPTFAILS), |
151 | SNMP_MIB_ITEM("EstabResets" , TCP_MIB_ESTABRESETS), |
152 | SNMP_MIB_ITEM("CurrEstab" , TCP_MIB_CURRESTAB), |
153 | SNMP_MIB_ITEM("InSegs" , TCP_MIB_INSEGS), |
154 | SNMP_MIB_ITEM("OutSegs" , TCP_MIB_OUTSEGS), |
155 | SNMP_MIB_ITEM("RetransSegs" , TCP_MIB_RETRANSSEGS), |
156 | SNMP_MIB_ITEM("InErrs" , TCP_MIB_INERRS), |
157 | SNMP_MIB_ITEM("OutRsts" , TCP_MIB_OUTRSTS), |
158 | SNMP_MIB_ITEM("InCsumErrors" , TCP_MIB_CSUMERRORS), |
159 | SNMP_MIB_SENTINEL |
160 | }; |
161 | |
162 | static const struct snmp_mib snmp4_udp_list[] = { |
163 | SNMP_MIB_ITEM("InDatagrams" , UDP_MIB_INDATAGRAMS), |
164 | SNMP_MIB_ITEM("NoPorts" , UDP_MIB_NOPORTS), |
165 | SNMP_MIB_ITEM("InErrors" , UDP_MIB_INERRORS), |
166 | SNMP_MIB_ITEM("OutDatagrams" , UDP_MIB_OUTDATAGRAMS), |
167 | SNMP_MIB_ITEM("RcvbufErrors" , UDP_MIB_RCVBUFERRORS), |
168 | SNMP_MIB_ITEM("SndbufErrors" , UDP_MIB_SNDBUFERRORS), |
169 | SNMP_MIB_ITEM("InCsumErrors" , UDP_MIB_CSUMERRORS), |
170 | SNMP_MIB_ITEM("IgnoredMulti" , UDP_MIB_IGNOREDMULTI), |
171 | SNMP_MIB_ITEM("MemErrors" , UDP_MIB_MEMERRORS), |
172 | SNMP_MIB_SENTINEL |
173 | }; |
174 | |
175 | static const struct snmp_mib snmp4_net_list[] = { |
176 | SNMP_MIB_ITEM("SyncookiesSent" , LINUX_MIB_SYNCOOKIESSENT), |
177 | SNMP_MIB_ITEM("SyncookiesRecv" , LINUX_MIB_SYNCOOKIESRECV), |
178 | SNMP_MIB_ITEM("SyncookiesFailed" , LINUX_MIB_SYNCOOKIESFAILED), |
179 | SNMP_MIB_ITEM("EmbryonicRsts" , LINUX_MIB_EMBRYONICRSTS), |
180 | SNMP_MIB_ITEM("PruneCalled" , LINUX_MIB_PRUNECALLED), |
181 | SNMP_MIB_ITEM("RcvPruned" , LINUX_MIB_RCVPRUNED), |
182 | SNMP_MIB_ITEM("OfoPruned" , LINUX_MIB_OFOPRUNED), |
183 | SNMP_MIB_ITEM("OutOfWindowIcmps" , LINUX_MIB_OUTOFWINDOWICMPS), |
184 | SNMP_MIB_ITEM("LockDroppedIcmps" , LINUX_MIB_LOCKDROPPEDICMPS), |
185 | SNMP_MIB_ITEM("ArpFilter" , LINUX_MIB_ARPFILTER), |
186 | SNMP_MIB_ITEM("TW" , LINUX_MIB_TIMEWAITED), |
187 | SNMP_MIB_ITEM("TWRecycled" , LINUX_MIB_TIMEWAITRECYCLED), |
188 | SNMP_MIB_ITEM("TWKilled" , LINUX_MIB_TIMEWAITKILLED), |
189 | SNMP_MIB_ITEM("PAWSActive" , LINUX_MIB_PAWSACTIVEREJECTED), |
190 | SNMP_MIB_ITEM("PAWSEstab" , LINUX_MIB_PAWSESTABREJECTED), |
191 | SNMP_MIB_ITEM("DelayedACKs" , LINUX_MIB_DELAYEDACKS), |
192 | SNMP_MIB_ITEM("DelayedACKLocked" , LINUX_MIB_DELAYEDACKLOCKED), |
193 | SNMP_MIB_ITEM("DelayedACKLost" , LINUX_MIB_DELAYEDACKLOST), |
194 | SNMP_MIB_ITEM("ListenOverflows" , LINUX_MIB_LISTENOVERFLOWS), |
195 | SNMP_MIB_ITEM("ListenDrops" , LINUX_MIB_LISTENDROPS), |
196 | SNMP_MIB_ITEM("TCPHPHits" , LINUX_MIB_TCPHPHITS), |
197 | SNMP_MIB_ITEM("TCPPureAcks" , LINUX_MIB_TCPPUREACKS), |
198 | SNMP_MIB_ITEM("TCPHPAcks" , LINUX_MIB_TCPHPACKS), |
199 | SNMP_MIB_ITEM("TCPRenoRecovery" , LINUX_MIB_TCPRENORECOVERY), |
200 | SNMP_MIB_ITEM("TCPSackRecovery" , LINUX_MIB_TCPSACKRECOVERY), |
201 | SNMP_MIB_ITEM("TCPSACKReneging" , LINUX_MIB_TCPSACKRENEGING), |
202 | SNMP_MIB_ITEM("TCPSACKReorder" , LINUX_MIB_TCPSACKREORDER), |
203 | SNMP_MIB_ITEM("TCPRenoReorder" , LINUX_MIB_TCPRENOREORDER), |
204 | SNMP_MIB_ITEM("TCPTSReorder" , LINUX_MIB_TCPTSREORDER), |
205 | SNMP_MIB_ITEM("TCPFullUndo" , LINUX_MIB_TCPFULLUNDO), |
206 | SNMP_MIB_ITEM("TCPPartialUndo" , LINUX_MIB_TCPPARTIALUNDO), |
207 | SNMP_MIB_ITEM("TCPDSACKUndo" , LINUX_MIB_TCPDSACKUNDO), |
208 | SNMP_MIB_ITEM("TCPLossUndo" , LINUX_MIB_TCPLOSSUNDO), |
209 | SNMP_MIB_ITEM("TCPLostRetransmit" , LINUX_MIB_TCPLOSTRETRANSMIT), |
210 | SNMP_MIB_ITEM("TCPRenoFailures" , LINUX_MIB_TCPRENOFAILURES), |
211 | SNMP_MIB_ITEM("TCPSackFailures" , LINUX_MIB_TCPSACKFAILURES), |
212 | SNMP_MIB_ITEM("TCPLossFailures" , LINUX_MIB_TCPLOSSFAILURES), |
213 | SNMP_MIB_ITEM("TCPFastRetrans" , LINUX_MIB_TCPFASTRETRANS), |
214 | SNMP_MIB_ITEM("TCPSlowStartRetrans" , LINUX_MIB_TCPSLOWSTARTRETRANS), |
215 | SNMP_MIB_ITEM("TCPTimeouts" , LINUX_MIB_TCPTIMEOUTS), |
216 | SNMP_MIB_ITEM("TCPLossProbes" , LINUX_MIB_TCPLOSSPROBES), |
217 | SNMP_MIB_ITEM("TCPLossProbeRecovery" , LINUX_MIB_TCPLOSSPROBERECOVERY), |
218 | SNMP_MIB_ITEM("TCPRenoRecoveryFail" , LINUX_MIB_TCPRENORECOVERYFAIL), |
219 | SNMP_MIB_ITEM("TCPSackRecoveryFail" , LINUX_MIB_TCPSACKRECOVERYFAIL), |
220 | SNMP_MIB_ITEM("TCPRcvCollapsed" , LINUX_MIB_TCPRCVCOLLAPSED), |
221 | SNMP_MIB_ITEM("TCPBacklogCoalesce" , LINUX_MIB_TCPBACKLOGCOALESCE), |
222 | SNMP_MIB_ITEM("TCPDSACKOldSent" , LINUX_MIB_TCPDSACKOLDSENT), |
223 | SNMP_MIB_ITEM("TCPDSACKOfoSent" , LINUX_MIB_TCPDSACKOFOSENT), |
224 | SNMP_MIB_ITEM("TCPDSACKRecv" , LINUX_MIB_TCPDSACKRECV), |
225 | SNMP_MIB_ITEM("TCPDSACKOfoRecv" , LINUX_MIB_TCPDSACKOFORECV), |
226 | SNMP_MIB_ITEM("TCPAbortOnData" , LINUX_MIB_TCPABORTONDATA), |
227 | SNMP_MIB_ITEM("TCPAbortOnClose" , LINUX_MIB_TCPABORTONCLOSE), |
228 | SNMP_MIB_ITEM("TCPAbortOnMemory" , LINUX_MIB_TCPABORTONMEMORY), |
229 | SNMP_MIB_ITEM("TCPAbortOnTimeout" , LINUX_MIB_TCPABORTONTIMEOUT), |
230 | SNMP_MIB_ITEM("TCPAbortOnLinger" , LINUX_MIB_TCPABORTONLINGER), |
231 | SNMP_MIB_ITEM("TCPAbortFailed" , LINUX_MIB_TCPABORTFAILED), |
232 | SNMP_MIB_ITEM("TCPMemoryPressures" , LINUX_MIB_TCPMEMORYPRESSURES), |
233 | SNMP_MIB_ITEM("TCPMemoryPressuresChrono" , LINUX_MIB_TCPMEMORYPRESSURESCHRONO), |
234 | SNMP_MIB_ITEM("TCPSACKDiscard" , LINUX_MIB_TCPSACKDISCARD), |
235 | SNMP_MIB_ITEM("TCPDSACKIgnoredOld" , LINUX_MIB_TCPDSACKIGNOREDOLD), |
236 | SNMP_MIB_ITEM("TCPDSACKIgnoredNoUndo" , LINUX_MIB_TCPDSACKIGNOREDNOUNDO), |
237 | SNMP_MIB_ITEM("TCPSpuriousRTOs" , LINUX_MIB_TCPSPURIOUSRTOS), |
238 | SNMP_MIB_ITEM("TCPMD5NotFound" , LINUX_MIB_TCPMD5NOTFOUND), |
239 | SNMP_MIB_ITEM("TCPMD5Unexpected" , LINUX_MIB_TCPMD5UNEXPECTED), |
240 | SNMP_MIB_ITEM("TCPMD5Failure" , LINUX_MIB_TCPMD5FAILURE), |
241 | SNMP_MIB_ITEM("TCPSackShifted" , LINUX_MIB_SACKSHIFTED), |
242 | SNMP_MIB_ITEM("TCPSackMerged" , LINUX_MIB_SACKMERGED), |
243 | SNMP_MIB_ITEM("TCPSackShiftFallback" , LINUX_MIB_SACKSHIFTFALLBACK), |
244 | SNMP_MIB_ITEM("TCPBacklogDrop" , LINUX_MIB_TCPBACKLOGDROP), |
245 | SNMP_MIB_ITEM("PFMemallocDrop" , LINUX_MIB_PFMEMALLOCDROP), |
246 | SNMP_MIB_ITEM("TCPMinTTLDrop" , LINUX_MIB_TCPMINTTLDROP), |
247 | SNMP_MIB_ITEM("TCPDeferAcceptDrop" , LINUX_MIB_TCPDEFERACCEPTDROP), |
248 | SNMP_MIB_ITEM("IPReversePathFilter" , LINUX_MIB_IPRPFILTER), |
249 | SNMP_MIB_ITEM("TCPTimeWaitOverflow" , LINUX_MIB_TCPTIMEWAITOVERFLOW), |
250 | SNMP_MIB_ITEM("TCPReqQFullDoCookies" , LINUX_MIB_TCPREQQFULLDOCOOKIES), |
251 | SNMP_MIB_ITEM("TCPReqQFullDrop" , LINUX_MIB_TCPREQQFULLDROP), |
252 | SNMP_MIB_ITEM("TCPRetransFail" , LINUX_MIB_TCPRETRANSFAIL), |
253 | SNMP_MIB_ITEM("TCPRcvCoalesce" , LINUX_MIB_TCPRCVCOALESCE), |
254 | SNMP_MIB_ITEM("TCPOFOQueue" , LINUX_MIB_TCPOFOQUEUE), |
255 | SNMP_MIB_ITEM("TCPOFODrop" , LINUX_MIB_TCPOFODROP), |
256 | SNMP_MIB_ITEM("TCPOFOMerge" , LINUX_MIB_TCPOFOMERGE), |
257 | SNMP_MIB_ITEM("TCPChallengeACK" , LINUX_MIB_TCPCHALLENGEACK), |
258 | SNMP_MIB_ITEM("TCPSYNChallenge" , LINUX_MIB_TCPSYNCHALLENGE), |
259 | SNMP_MIB_ITEM("TCPFastOpenActive" , LINUX_MIB_TCPFASTOPENACTIVE), |
260 | SNMP_MIB_ITEM("TCPFastOpenActiveFail" , LINUX_MIB_TCPFASTOPENACTIVEFAIL), |
261 | SNMP_MIB_ITEM("TCPFastOpenPassive" , LINUX_MIB_TCPFASTOPENPASSIVE), |
262 | SNMP_MIB_ITEM("TCPFastOpenPassiveFail" , LINUX_MIB_TCPFASTOPENPASSIVEFAIL), |
263 | SNMP_MIB_ITEM("TCPFastOpenListenOverflow" , LINUX_MIB_TCPFASTOPENLISTENOVERFLOW), |
264 | SNMP_MIB_ITEM("TCPFastOpenCookieReqd" , LINUX_MIB_TCPFASTOPENCOOKIEREQD), |
265 | SNMP_MIB_ITEM("TCPFastOpenBlackhole" , LINUX_MIB_TCPFASTOPENBLACKHOLE), |
266 | SNMP_MIB_ITEM("TCPSpuriousRtxHostQueues" , LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES), |
267 | SNMP_MIB_ITEM("BusyPollRxPackets" , LINUX_MIB_BUSYPOLLRXPACKETS), |
268 | SNMP_MIB_ITEM("TCPAutoCorking" , LINUX_MIB_TCPAUTOCORKING), |
269 | SNMP_MIB_ITEM("TCPFromZeroWindowAdv" , LINUX_MIB_TCPFROMZEROWINDOWADV), |
270 | SNMP_MIB_ITEM("TCPToZeroWindowAdv" , LINUX_MIB_TCPTOZEROWINDOWADV), |
271 | SNMP_MIB_ITEM("TCPWantZeroWindowAdv" , LINUX_MIB_TCPWANTZEROWINDOWADV), |
272 | SNMP_MIB_ITEM("TCPSynRetrans" , LINUX_MIB_TCPSYNRETRANS), |
273 | SNMP_MIB_ITEM("TCPOrigDataSent" , LINUX_MIB_TCPORIGDATASENT), |
274 | SNMP_MIB_ITEM("TCPHystartTrainDetect" , LINUX_MIB_TCPHYSTARTTRAINDETECT), |
275 | SNMP_MIB_ITEM("TCPHystartTrainCwnd" , LINUX_MIB_TCPHYSTARTTRAINCWND), |
276 | SNMP_MIB_ITEM("TCPHystartDelayDetect" , LINUX_MIB_TCPHYSTARTDELAYDETECT), |
277 | SNMP_MIB_ITEM("TCPHystartDelayCwnd" , LINUX_MIB_TCPHYSTARTDELAYCWND), |
278 | SNMP_MIB_ITEM("TCPACKSkippedSynRecv" , LINUX_MIB_TCPACKSKIPPEDSYNRECV), |
279 | SNMP_MIB_ITEM("TCPACKSkippedPAWS" , LINUX_MIB_TCPACKSKIPPEDPAWS), |
280 | SNMP_MIB_ITEM("TCPACKSkippedSeq" , LINUX_MIB_TCPACKSKIPPEDSEQ), |
281 | SNMP_MIB_ITEM("TCPACKSkippedFinWait2" , LINUX_MIB_TCPACKSKIPPEDFINWAIT2), |
282 | SNMP_MIB_ITEM("TCPACKSkippedTimeWait" , LINUX_MIB_TCPACKSKIPPEDTIMEWAIT), |
283 | SNMP_MIB_ITEM("TCPACKSkippedChallenge" , LINUX_MIB_TCPACKSKIPPEDCHALLENGE), |
284 | SNMP_MIB_ITEM("TCPWinProbe" , LINUX_MIB_TCPWINPROBE), |
285 | SNMP_MIB_ITEM("TCPKeepAlive" , LINUX_MIB_TCPKEEPALIVE), |
286 | SNMP_MIB_ITEM("TCPMTUPFail" , LINUX_MIB_TCPMTUPFAIL), |
287 | SNMP_MIB_ITEM("TCPMTUPSuccess" , LINUX_MIB_TCPMTUPSUCCESS), |
288 | SNMP_MIB_ITEM("TCPDelivered" , LINUX_MIB_TCPDELIVERED), |
289 | SNMP_MIB_ITEM("TCPDeliveredCE" , LINUX_MIB_TCPDELIVEREDCE), |
290 | SNMP_MIB_ITEM("TCPAckCompressed" , LINUX_MIB_TCPACKCOMPRESSED), |
291 | SNMP_MIB_ITEM("TCPZeroWindowDrop" , LINUX_MIB_TCPZEROWINDOWDROP), |
292 | SNMP_MIB_ITEM("TCPRcvQDrop" , LINUX_MIB_TCPRCVQDROP), |
293 | SNMP_MIB_ITEM("TCPWqueueTooBig" , LINUX_MIB_TCPWQUEUETOOBIG), |
294 | SNMP_MIB_ITEM("TCPFastOpenPassiveAltKey" , LINUX_MIB_TCPFASTOPENPASSIVEALTKEY), |
295 | SNMP_MIB_ITEM("TcpTimeoutRehash" , LINUX_MIB_TCPTIMEOUTREHASH), |
296 | SNMP_MIB_ITEM("TcpDuplicateDataRehash" , LINUX_MIB_TCPDUPLICATEDATAREHASH), |
297 | SNMP_MIB_ITEM("TCPDSACKRecvSegs" , LINUX_MIB_TCPDSACKRECVSEGS), |
298 | SNMP_MIB_ITEM("TCPDSACKIgnoredDubious" , LINUX_MIB_TCPDSACKIGNOREDDUBIOUS), |
299 | SNMP_MIB_ITEM("TCPMigrateReqSuccess" , LINUX_MIB_TCPMIGRATEREQSUCCESS), |
300 | SNMP_MIB_ITEM("TCPMigrateReqFailure" , LINUX_MIB_TCPMIGRATEREQFAILURE), |
301 | SNMP_MIB_ITEM("TCPPLBRehash" , LINUX_MIB_TCPPLBREHASH), |
302 | SNMP_MIB_ITEM("TCPAORequired" , LINUX_MIB_TCPAOREQUIRED), |
303 | SNMP_MIB_ITEM("TCPAOBad" , LINUX_MIB_TCPAOBAD), |
304 | SNMP_MIB_ITEM("TCPAOKeyNotFound" , LINUX_MIB_TCPAOKEYNOTFOUND), |
305 | SNMP_MIB_ITEM("TCPAOGood" , LINUX_MIB_TCPAOGOOD), |
306 | SNMP_MIB_ITEM("TCPAODroppedIcmps" , LINUX_MIB_TCPAODROPPEDICMPS), |
307 | SNMP_MIB_SENTINEL |
308 | }; |
309 | |
310 | static void icmpmsg_put_line(struct seq_file *seq, unsigned long *vals, |
311 | unsigned short *type, int count) |
312 | { |
313 | int j; |
314 | |
315 | if (count) { |
316 | seq_puts(m: seq, s: "\nIcmpMsg:" ); |
317 | for (j = 0; j < count; ++j) |
318 | seq_printf(m: seq, fmt: " %sType%u" , |
319 | type[j] & 0x100 ? "Out" : "In" , |
320 | type[j] & 0xff); |
321 | seq_puts(m: seq, s: "\nIcmpMsg:" ); |
322 | for (j = 0; j < count; ++j) |
323 | seq_printf(m: seq, fmt: " %lu" , vals[j]); |
324 | } |
325 | } |
326 | |
327 | static void icmpmsg_put(struct seq_file *seq) |
328 | { |
329 | #define PERLINE 16 |
330 | |
331 | int i, count; |
332 | unsigned short type[PERLINE]; |
333 | unsigned long vals[PERLINE], val; |
334 | struct net *net = seq->private; |
335 | |
336 | count = 0; |
337 | for (i = 0; i < ICMPMSG_MIB_MAX; i++) { |
338 | val = atomic_long_read(v: &net->mib.icmpmsg_statistics->mibs[i]); |
339 | if (val) { |
340 | type[count] = i; |
341 | vals[count++] = val; |
342 | } |
343 | if (count == PERLINE) { |
344 | icmpmsg_put_line(seq, vals, type, count); |
345 | count = 0; |
346 | } |
347 | } |
348 | icmpmsg_put_line(seq, vals, type, count); |
349 | |
350 | #undef PERLINE |
351 | } |
352 | |
353 | static void icmp_put(struct seq_file *seq) |
354 | { |
355 | int i; |
356 | struct net *net = seq->private; |
357 | atomic_long_t *ptr = net->mib.icmpmsg_statistics->mibs; |
358 | |
359 | seq_puts(m: seq, s: "\nIcmp: InMsgs InErrors InCsumErrors" ); |
360 | for (i = 0; icmpmibmap[i].name; i++) |
361 | seq_printf(m: seq, fmt: " In%s" , icmpmibmap[i].name); |
362 | seq_puts(m: seq, s: " OutMsgs OutErrors OutRateLimitGlobal OutRateLimitHost" ); |
363 | for (i = 0; icmpmibmap[i].name; i++) |
364 | seq_printf(m: seq, fmt: " Out%s" , icmpmibmap[i].name); |
365 | seq_printf(m: seq, fmt: "\nIcmp: %lu %lu %lu" , |
366 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_INMSGS), |
367 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_INERRORS), |
368 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_CSUMERRORS)); |
369 | for (i = 0; icmpmibmap[i].name; i++) |
370 | seq_printf(m: seq, fmt: " %lu" , |
371 | atomic_long_read(v: ptr + icmpmibmap[i].index)); |
372 | seq_printf(m: seq, fmt: " %lu %lu %lu %lu" , |
373 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_OUTMSGS), |
374 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_OUTERRORS), |
375 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_RATELIMITGLOBAL), |
376 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_RATELIMITHOST)); |
377 | for (i = 0; icmpmibmap[i].name; i++) |
378 | seq_printf(m: seq, fmt: " %lu" , |
379 | atomic_long_read(v: ptr + (icmpmibmap[i].index | 0x100))); |
380 | } |
381 | |
382 | /* |
383 | * Called from the PROCfs module. This outputs /proc/net/snmp. |
384 | */ |
385 | static int snmp_seq_show_ipstats(struct seq_file *seq, void *v) |
386 | { |
387 | struct net *net = seq->private; |
388 | u64 buff64[IPSTATS_MIB_MAX]; |
389 | int i; |
390 | |
391 | memset(buff64, 0, IPSTATS_MIB_MAX * sizeof(u64)); |
392 | |
393 | seq_puts(m: seq, s: "Ip: Forwarding DefaultTTL" ); |
394 | for (i = 0; snmp4_ipstats_list[i].name; i++) |
395 | seq_printf(m: seq, fmt: " %s" , snmp4_ipstats_list[i].name); |
396 | |
397 | seq_printf(m: seq, fmt: "\nIp: %d %d" , |
398 | IPV4_DEVCONF_ALL(net, FORWARDING) ? 1 : 2, |
399 | READ_ONCE(net->ipv4.sysctl_ip_default_ttl)); |
400 | |
401 | BUILD_BUG_ON(offsetof(struct ipstats_mib, mibs) != 0); |
402 | snmp_get_cpu_field64_batch(buff64, snmp4_ipstats_list, |
403 | net->mib.ip_statistics, |
404 | offsetof(struct ipstats_mib, syncp)); |
405 | for (i = 0; snmp4_ipstats_list[i].name; i++) |
406 | seq_printf(m: seq, fmt: " %llu" , buff64[i]); |
407 | |
408 | return 0; |
409 | } |
410 | |
411 | static int snmp_seq_show_tcp_udp(struct seq_file *seq, void *v) |
412 | { |
413 | unsigned long buff[TCPUDP_MIB_MAX]; |
414 | struct net *net = seq->private; |
415 | int i; |
416 | |
417 | memset(buff, 0, TCPUDP_MIB_MAX * sizeof(unsigned long)); |
418 | |
419 | seq_puts(m: seq, s: "\nTcp:" ); |
420 | for (i = 0; snmp4_tcp_list[i].name; i++) |
421 | seq_printf(m: seq, fmt: " %s" , snmp4_tcp_list[i].name); |
422 | |
423 | seq_puts(m: seq, s: "\nTcp:" ); |
424 | snmp_get_cpu_field_batch(buff, snmp4_tcp_list, |
425 | net->mib.tcp_statistics); |
426 | for (i = 0; snmp4_tcp_list[i].name; i++) { |
427 | /* MaxConn field is signed, RFC 2012 */ |
428 | if (snmp4_tcp_list[i].entry == TCP_MIB_MAXCONN) |
429 | seq_printf(m: seq, fmt: " %ld" , buff[i]); |
430 | else |
431 | seq_printf(m: seq, fmt: " %lu" , buff[i]); |
432 | } |
433 | |
434 | memset(buff, 0, TCPUDP_MIB_MAX * sizeof(unsigned long)); |
435 | |
436 | snmp_get_cpu_field_batch(buff, snmp4_udp_list, |
437 | net->mib.udp_statistics); |
438 | seq_puts(m: seq, s: "\nUdp:" ); |
439 | for (i = 0; snmp4_udp_list[i].name; i++) |
440 | seq_printf(m: seq, fmt: " %s" , snmp4_udp_list[i].name); |
441 | seq_puts(m: seq, s: "\nUdp:" ); |
442 | for (i = 0; snmp4_udp_list[i].name; i++) |
443 | seq_printf(m: seq, fmt: " %lu" , buff[i]); |
444 | |
445 | memset(buff, 0, TCPUDP_MIB_MAX * sizeof(unsigned long)); |
446 | |
447 | /* the UDP and UDP-Lite MIBs are the same */ |
448 | seq_puts(m: seq, s: "\nUdpLite:" ); |
449 | snmp_get_cpu_field_batch(buff, snmp4_udp_list, |
450 | net->mib.udplite_statistics); |
451 | for (i = 0; snmp4_udp_list[i].name; i++) |
452 | seq_printf(m: seq, fmt: " %s" , snmp4_udp_list[i].name); |
453 | seq_puts(m: seq, s: "\nUdpLite:" ); |
454 | for (i = 0; snmp4_udp_list[i].name; i++) |
455 | seq_printf(m: seq, fmt: " %lu" , buff[i]); |
456 | |
457 | seq_putc(m: seq, c: '\n'); |
458 | return 0; |
459 | } |
460 | |
461 | static int snmp_seq_show(struct seq_file *seq, void *v) |
462 | { |
463 | snmp_seq_show_ipstats(seq, v); |
464 | |
465 | icmp_put(seq); /* RFC 2011 compatibility */ |
466 | icmpmsg_put(seq); |
467 | |
468 | snmp_seq_show_tcp_udp(seq, v); |
469 | |
470 | return 0; |
471 | } |
472 | |
473 | /* |
474 | * Output /proc/net/netstat |
475 | */ |
476 | static int netstat_seq_show(struct seq_file *seq, void *v) |
477 | { |
478 | const int ip_cnt = ARRAY_SIZE(snmp4_ipextstats_list) - 1; |
479 | const int tcp_cnt = ARRAY_SIZE(snmp4_net_list) - 1; |
480 | struct net *net = seq->private; |
481 | unsigned long *buff; |
482 | int i; |
483 | |
484 | seq_puts(m: seq, s: "TcpExt:" ); |
485 | for (i = 0; i < tcp_cnt; i++) |
486 | seq_printf(m: seq, fmt: " %s" , snmp4_net_list[i].name); |
487 | |
488 | seq_puts(m: seq, s: "\nTcpExt:" ); |
489 | buff = kzalloc(max(tcp_cnt * sizeof(long), ip_cnt * sizeof(u64)), |
490 | GFP_KERNEL); |
491 | if (buff) { |
492 | snmp_get_cpu_field_batch(buff, snmp4_net_list, |
493 | net->mib.net_statistics); |
494 | for (i = 0; i < tcp_cnt; i++) |
495 | seq_printf(m: seq, fmt: " %lu" , buff[i]); |
496 | } else { |
497 | for (i = 0; i < tcp_cnt; i++) |
498 | seq_printf(m: seq, fmt: " %lu" , |
499 | snmp_fold_field(mib: net->mib.net_statistics, |
500 | offt: snmp4_net_list[i].entry)); |
501 | } |
502 | seq_puts(m: seq, s: "\nIpExt:" ); |
503 | for (i = 0; i < ip_cnt; i++) |
504 | seq_printf(m: seq, fmt: " %s" , snmp4_ipextstats_list[i].name); |
505 | |
506 | seq_puts(m: seq, s: "\nIpExt:" ); |
507 | if (buff) { |
508 | u64 *buff64 = (u64 *)buff; |
509 | |
510 | memset(buff64, 0, ip_cnt * sizeof(u64)); |
511 | snmp_get_cpu_field64_batch(buff64, snmp4_ipextstats_list, |
512 | net->mib.ip_statistics, |
513 | offsetof(struct ipstats_mib, syncp)); |
514 | for (i = 0; i < ip_cnt; i++) |
515 | seq_printf(m: seq, fmt: " %llu" , buff64[i]); |
516 | } else { |
517 | for (i = 0; i < ip_cnt; i++) |
518 | seq_printf(m: seq, fmt: " %llu" , |
519 | snmp_fold_field64(mib: net->mib.ip_statistics, |
520 | offt: snmp4_ipextstats_list[i].entry, |
521 | offsetof(struct ipstats_mib, syncp))); |
522 | } |
523 | kfree(objp: buff); |
524 | seq_putc(m: seq, c: '\n'); |
525 | mptcp_seq_show(seq); |
526 | return 0; |
527 | } |
528 | |
529 | static __net_init int ip_proc_init_net(struct net *net) |
530 | { |
531 | if (!proc_create_net_single(name: "sockstat" , mode: 0444, parent: net->proc_net, |
532 | show: sockstat_seq_show, NULL)) |
533 | goto out_sockstat; |
534 | if (!proc_create_net_single(name: "netstat" , mode: 0444, parent: net->proc_net, |
535 | show: netstat_seq_show, NULL)) |
536 | goto out_netstat; |
537 | if (!proc_create_net_single(name: "snmp" , mode: 0444, parent: net->proc_net, show: snmp_seq_show, |
538 | NULL)) |
539 | goto out_snmp; |
540 | |
541 | return 0; |
542 | |
543 | out_snmp: |
544 | remove_proc_entry("netstat" , net->proc_net); |
545 | out_netstat: |
546 | remove_proc_entry("sockstat" , net->proc_net); |
547 | out_sockstat: |
548 | return -ENOMEM; |
549 | } |
550 | |
551 | static __net_exit void ip_proc_exit_net(struct net *net) |
552 | { |
553 | remove_proc_entry("snmp" , net->proc_net); |
554 | remove_proc_entry("netstat" , net->proc_net); |
555 | remove_proc_entry("sockstat" , net->proc_net); |
556 | } |
557 | |
558 | static __net_initdata struct pernet_operations ip_proc_ops = { |
559 | .init = ip_proc_init_net, |
560 | .exit = ip_proc_exit_net, |
561 | }; |
562 | |
563 | int __init ip_misc_proc_init(void) |
564 | { |
565 | return register_pernet_subsys(&ip_proc_ops); |
566 | } |
567 | |