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