1 /*
2  * NetBSD implementation for mapping the IP stat arrays into struct's
3  * Required for NetBSD versions produced after April 7th 2008 (4+)
4  *
5  * Based on: http://mail-index.netbsd.org/pkgsrc-users/2008/04/27/msg007095.html
6  */
7 
8 #include <sys/param.h>
9 #include <sys/sysctl.h>
10 #include <sys/protosw.h>
11 
12 #include <netinet/in.h>
13 #include <netinet/in_systm.h>
14 #include <netinet/ip.h>
15 #include <netinet/ip_icmp.h>
16 #include <netinet/ip_var.h>
17 #include <netinet/icmp_var.h>
18 #include <netinet/icmp6.h>
19 #include <netinet/tcp.h>
20 #include <netinet/tcp_timer.h>
21 #include <netinet/tcp_var.h>
22 #include <netinet/udp.h>
23 #include <netinet/udp_var.h>
24 
25 #include <net-snmp/net-snmp-config.h>
26 #include <net-snmp/net-snmp-includes.h>
27 #include <net-snmp/agent/net-snmp-agent-includes.h>
28 
29 #include "kernel_netbsd.h"
30 
31 #if defined(NETBSD_STATS_VIA_SYSCTL)
32 
33 int
netbsd_read_icmp_stat(struct icmp_mib * mib)34 netbsd_read_icmp_stat(struct icmp_mib *mib)
35 {
36     uint64_t icmpstat[ICMP_NSTATS];
37     size_t   size = sizeof(icmpstat);
38     int      i;
39 
40     (void)memset(mib, 0, sizeof(*mib));
41 
42     if (-1 == sysctlbyname("net.inet.icmp.stats", icmpstat, &size, NULL, 0)) {
43 	snmp_perror("netbsd_read_icmp_stat: net.inet.icmp.stats");
44         return -1;
45     }
46 
47     mib->icmpInMsgs = icmpstat[ICMP_STAT_BADCODE]
48         + icmpstat[ICMP_STAT_TOOSHORT]
49         + icmpstat[ICMP_STAT_CHECKSUM]
50         + icmpstat[ICMP_STAT_BADLEN];
51     for (i = 0; i <= ICMP_MAXTYPE; i++)
52         mib->icmpInMsgs  += icmpstat[ICMP_STAT_INHIST + i];
53     mib->icmpInErrors = icmpstat[ICMP_STAT_BADCODE]
54         + icmpstat[ICMP_STAT_TOOSHORT]
55         + icmpstat[ICMP_STAT_CHECKSUM]
56         + icmpstat[ICMP_STAT_BADLEN];
57     mib->icmpInDestUnreachs = icmpstat[ICMP_STAT_INHIST + ICMP_UNREACH];
58     mib->icmpInTimeExcds = icmpstat[ICMP_STAT_INHIST + ICMP_TIMXCEED];
59     mib->icmpInParmProbs = icmpstat[ICMP_STAT_INHIST + ICMP_PARAMPROB];
60     mib->icmpInSrcQuenchs = icmpstat[ICMP_STAT_INHIST + ICMP_SOURCEQUENCH];
61     mib->icmpInRedirects = icmpstat[ICMP_STAT_INHIST + ICMP_REDIRECT];
62     mib->icmpInEchos = icmpstat[ICMP_STAT_INHIST + ICMP_ECHO];
63     mib->icmpInEchoReps = icmpstat[ICMP_STAT_INHIST + ICMP_ECHOREPLY];
64     mib->icmpInTimestamps = icmpstat[ICMP_STAT_INHIST + ICMP_TSTAMP];
65     mib->icmpInTimestampReps
66         = icmpstat[ICMP_STAT_INHIST + ICMP_TSTAMPREPLY];
67     mib->icmpInAddrMasks = icmpstat[ICMP_STAT_INHIST + ICMP_MASKREQ];
68     mib->icmpInAddrMaskReps = icmpstat[ICMP_STAT_INHIST + ICMP_MASKREPLY];
69     mib->icmpOutMsgs = icmpstat[ICMP_STAT_OLDSHORT]
70         + icmpstat[ICMP_STAT_OLDICMP];
71     for (i = 0; i <= ICMP_MAXTYPE; i++)
72         mib->icmpOutMsgs += icmpstat[ICMP_STAT_OUTHIST + i];
73     mib->icmpOutErrors = icmpstat[ICMP_STAT_OLDSHORT]
74         + icmpstat[ICMP_STAT_OLDICMP];
75     mib->icmpOutDestUnreachs = icmpstat[ICMP_STAT_OUTHIST + ICMP_UNREACH];
76     mib->icmpOutTimeExcds = icmpstat[ICMP_STAT_OUTHIST + ICMP_TIMXCEED];
77     mib->icmpOutParmProbs = icmpstat[ICMP_STAT_OUTHIST + ICMP_PARAMPROB];
78     mib->icmpOutSrcQuenchs
79         = icmpstat[ICMP_STAT_OUTHIST + ICMP_SOURCEQUENCH];
80     mib->icmpOutRedirects = icmpstat[ICMP_STAT_OUTHIST + ICMP_REDIRECT];
81     mib->icmpOutEchos = icmpstat[ICMP_STAT_OUTHIST + ICMP_ECHO];
82     mib->icmpOutEchoReps = icmpstat[ICMP_STAT_OUTHIST + ICMP_ECHOREPLY];
83     mib->icmpOutTimestamps = icmpstat[ICMP_STAT_OUTHIST + ICMP_TSTAMP];
84     mib->icmpOutTimestampReps
85         = icmpstat[ICMP_STAT_OUTHIST + ICMP_TSTAMPREPLY];
86     mib->icmpOutAddrMasks = icmpstat[ICMP_STAT_OUTHIST + ICMP_MASKREQ];
87     mib->icmpOutAddrMaskReps = icmpstat[ICMP_STAT_OUTHIST + ICMP_MASKREPLY];
88 
89     return 0;
90 }
91 
92 
93 int
netbsd_read_icmp6_stat(struct icmp6_mib * mib)94 netbsd_read_icmp6_stat(struct icmp6_mib *mib)
95 {
96     uint64_t icmpstat[ICMP6_NSTATS];
97     size_t   size = sizeof(icmpstat);
98     int      i;
99 
100     (void)memset(mib, 0, sizeof(*mib));
101 
102     if (-1 == sysctlbyname("net.inet6.icmp6.stats", icmpstat, &size, NULL, 0)) {
103 	snmp_perror("netbsd_read_icmp6_stat: net.inet6.icmp6.stats");
104         return -1;
105     }
106 
107     mib->icmp6InMsgs = icmpstat[ICMP6_STAT_BADCODE]
108             + icmpstat[ICMP_STAT_TOOSHORT]
109 	    + icmpstat[ICMP_STAT_CHECKSUM]
110             + icmpstat[ICMP_STAT_BADLEN];
111     for (i = 0; i <= ICMP6_MAXTYPE; i++)
112         mib->icmp6InMsgs  += icmpstat[ICMP6_STAT_INHIST + i];
113     mib->icmp6InErrors = icmpstat[ICMP6_STAT_BADCODE]
114         + icmpstat[ICMP6_STAT_TOOSHORT]
115         + icmpstat[ICMP6_STAT_CHECKSUM]
116         + icmpstat[ICMP6_STAT_BADLEN];
117     mib->icmp6InDestUnreachs = icmpstat[ICMP6_STAT_INHIST + ICMP6_DST_UNREACH];
118     mib->icmp6InPktTooBigs = icmpstat[ICMP6_STAT_INHIST + ICMP6_PACKET_TOO_BIG];
119     mib->icmp6InTimeExcds = icmpstat[ICMP6_STAT_INHIST + ICMP6_TIME_EXCEEDED];
120     mib->icmp6InParmProblems = icmpstat[ICMP6_STAT_INHIST + ICMP6_PARAM_PROB];
121     mib->icmp6InEchos = icmpstat[ICMP6_STAT_INHIST + ICMP6_ECHO_REQUEST];
122     mib->icmp6InEchoReplies = icmpstat[ICMP6_STAT_INHIST + ICMP6_ECHO_REPLY];
123     mib->icmp6InGroupMembQueries = icmpstat[ICMP6_STAT_INHIST + MLD_LISTENER_QUERY];
124     mib->icmp6InGroupMembResponses = icmpstat[ICMP6_STAT_INHIST + MLD_LISTENER_REPORT];
125     mib->icmp6InRouterSolicits = icmpstat[ICMP6_STAT_INHIST + ND_ROUTER_SOLICIT];
126     mib->icmp6InRouterAdvertisements = icmpstat[ICMP6_STAT_INHIST + ND_ROUTER_ADVERT];
127     mib->icmp6InNeighborSolicits = icmpstat[ICMP6_STAT_INHIST + ND_NEIGHBOR_SOLICIT];
128     mib->icmp6InNeighborAdvertisements = icmpstat[ICMP6_STAT_INHIST + ND_NEIGHBOR_ADVERT];
129     mib->icmp6InRedirects = icmpstat[ICMP6_STAT_INHIST + ND_REDIRECT];
130 
131     mib->icmp6OutMsgs = icmpstat[ICMP6_STAT_BADCODE]
132         + icmpstat[ICMP6_STAT_TOOSHORT]
133         + icmpstat[ICMP6_STAT_CHECKSUM]
134         + icmpstat[ICMP6_STAT_BADLEN];
135     for (i = 0; i <= ICMP6_MAXTYPE; i++)
136         mib->icmp6OutMsgs += icmpstat[ICMP6_STAT_OUTHIST + i];
137     mib->icmp6OutDestUnreachs = icmpstat[ICMP6_STAT_OUTHIST + ICMP6_DST_UNREACH];
138     mib->icmp6OutPktTooBigs =  icmpstat[ICMP6_STAT_OUTHIST + ICMP6_PACKET_TOO_BIG];
139     mib->icmp6OutTimeExcds = icmpstat[ICMP6_STAT_OUTHIST + ICMP6_TIME_EXCEEDED];
140     mib->icmp6OutParmProblems = icmpstat[ICMP6_STAT_OUTHIST + ICMP6_PARAM_PROB];
141     mib->icmp6OutEchos = icmpstat[ICMP6_STAT_OUTHIST + ICMP6_ECHO_REQUEST];
142     mib->icmp6OutEchoReplies = icmpstat[ICMP6_STAT_OUTHIST + ICMP6_ECHO_REPLY];
143     mib->icmp6OutRouterSolicits =  icmpstat[ICMP6_STAT_OUTHIST + ND_ROUTER_SOLICIT];
144     mib->icmp6OutNeighborSolicits =  icmpstat[ICMP6_STAT_OUTHIST + ND_NEIGHBOR_SOLICIT];
145     mib->icmp6OutNeighborAdvertisements =  icmpstat[ICMP6_STAT_OUTHIST + ND_NEIGHBOR_ADVERT];
146     mib->icmp6OutRedirects = icmpstat[ICMP6_STAT_OUTHIST + ND_REDIRECT];
147     mib->icmp6OutGroupMembResponses =  icmpstat[ICMP6_STAT_OUTHIST + MLD_LISTENER_REPORT];
148     mib->icmp6OutGroupMembReductions =  icmpstat[ICMP6_STAT_OUTHIST + MLD_LISTENER_DONE];
149 
150     return 0;
151 }
152 
153 
154 int
netbsd_read_icmp_msg_stat(struct icmp_mib * mib,struct icmp4_msg_mib * msgmib,int * flag)155 netbsd_read_icmp_msg_stat(struct icmp_mib *mib,
156                           struct icmp4_msg_mib *msgmib,
157 			  int *flag)
158 {
159     netbsd_read_icmp_stat(mib);
160     *flag = 0;
161     return 0;
162 }
163 
164 
165 int
netbsd_read_icmp6_msg_stat(struct icmp6_mib * mib,struct icmp6_msg_mib * msgmib,int * support)166 netbsd_read_icmp6_msg_stat(struct icmp6_mib *mib,
167                            struct icmp6_msg_mib *msgmib,
168 			   int *support)
169 {
170     uint64_t icmpstat[ICMP6_NSTATS];
171     size_t   size = sizeof(icmpstat);
172     int      i;
173 
174     netbsd_read_icmp6_stat(mib);
175 
176     if (-1 == sysctlbyname("net.inet6.icmp6.stats", icmpstat, &size, NULL, 0)) {
177 	snmp_perror("netbsd_read_icmp6_stat: net.inet6.icmp6.stats");
178         return -1;
179     }
180 
181     for (i = 0; i < 256; i++) {
182 	msgmib->vals[i].InType = icmpstat[ICMP6_STAT_INHIST+i];
183 	msgmib->vals[i].OutType = icmpstat[ICMP6_STAT_OUTHIST+i];
184     }
185     *support = 1;
186     return 0;
187 }
188 
189 
190 int
netbsd_read_ip_stat(struct ip_mib * mib)191 netbsd_read_ip_stat(struct ip_mib *mib)
192 {
193     uint64_t ipstat[IP_NSTATS];
194     size_t   size = sizeof(ipstat);
195     int      i;
196     static   int sname[4] = { 4, 2, 0, 0 }; /* CTL_NET, PF_INET, IPPROTO_IP, 0 */
197     size_t   len;
198 
199     (void)memset(mib, 0, sizeof(*mib));
200 
201     if (-1 == sysctlbyname("net.inet.ip.stats", ipstat, &size, NULL, 0)) {
202 	snmp_perror("netbsd_read_ip_stat: net.inet.ip.stats");
203         return -1;
204     }
205 
206     mib->ipForwarding = 0;
207     len = sizeof i;
208     sname[3] = IPCTL_FORWARDING;
209     if (0 == sysctl(sname, 4, &i, &len, 0, 0)) {
210         mib->ipForwarding = (long)i;
211     }
212 
213     mib->ipDefaultTTL = 0;
214     sname[3] = IPCTL_DEFTTL;
215     if (0 == sysctl(sname, 4, &i, &len, 0, 0)) {
216         mib->ipDefaultTTL = (long)i;
217     }
218 
219     mib->ipInReceives = ipstat[IP_STAT_TOTAL];
220     mib->ipInHdrErrors = ipstat[IP_STAT_BADSUM]
221         + ipstat[IP_STAT_TOOSHORT] + ipstat[IP_STAT_TOOSMALL]
222         + ipstat[IP_STAT_BADHLEN] + ipstat[IP_STAT_BADLEN];
223     mib->ipInAddrErrors = ipstat[IP_STAT_CANTFORWARD];
224     mib->ipForwDatagrams = ipstat[IP_STAT_FORWARD];
225     mib->ipInUnknownProtos = ipstat[IP_STAT_NOPROTO];
226     mib->ipInDiscards = ipstat[IP_STAT_FRAGDROPPED]; /* FIXME */
227     mib->ipInDelivers = ipstat[IP_STAT_DELIVERED];
228     mib->ipOutRequests = ipstat[IP_STAT_LOCALOUT];
229     mib->ipOutDiscards = ipstat[IP_STAT_ODROPPED];
230     mib->ipOutNoRoutes = 0; /* FIXME */
231     mib->ipReasmTimeout = 0; /* IPFRAGTTL; */
232     mib->ipReasmReqds = ipstat[IP_STAT_FRAGMENTS];
233     mib->ipReasmOKs = ipstat[IP_STAT_REASSEMBLED];
234     mib->ipReasmFails = ipstat[IP_STAT_FRAGDROPPED]
235         + ipstat[IP_STAT_FRAGTIMEOUT];
236     mib->ipFragOKs = ipstat[IP_STAT_FRAGMENTS];
237     mib->ipFragFails = ipstat[IP_STAT_CANTFRAG];
238     mib->ipFragCreates = ipstat[IP_STAT_OFRAGMENTS];
239     mib->ipRoutingDiscards = ipstat[IP_STAT_NOROUTE];
240 
241     return 0;
242 }
243 
244 
245 int
netbsd_read_tcp_stat(struct tcp_mib * mib)246 netbsd_read_tcp_stat(struct tcp_mib *mib)
247 {
248     uint64_t tcpstat[TCP_NSTATS];
249     size_t   size = sizeof(tcpstat);
250 
251     (void)memset(mib, 0, sizeof(*mib));
252 
253     if (-1 == sysctlbyname("net.inet.tcp.stats", tcpstat, &size, NULL, 0)) {
254 	snmp_perror("netbsd_read_tcp_stat: net.inet.tcp.stats");
255         return -1;
256     }
257 
258     mib->tcpRtoAlgorithm = 4; /* Assume Van Jacobsen's algorithm */
259     mib->tcpRtoMin = TCPTV_MIN;
260     mib->tcpRtoMax = TCPTV_REXMTMAX;
261     mib->tcpMaxConn = -1; /* Dynamic Maximum */
262     mib->tcpActiveOpens = tcpstat[TCP_STAT_CONNATTEMPT];
263     mib->tcpPassiveOpens = tcpstat[TCP_STAT_ACCEPTS];
264     mib->tcpAttemptFails = tcpstat[TCP_STAT_CONNDROPS];
265     mib->tcpEstabResets = tcpstat[TCP_STAT_DROPS];
266     mib->tcpCurrEstab = 0; /* FIXME */
267     mib->tcpInSegs = tcpstat[TCP_STAT_RCVTOTAL];
268     mib->tcpOutSegs = tcpstat[TCP_STAT_SNDTOTAL]
269         - tcpstat[TCP_STAT_SNDREXMITPACK];
270     mib->tcpRetransSegs = tcpstat[TCP_STAT_SNDREXMITPACK];
271     mib->tcpInErrs = tcpstat[TCP_STAT_RCVBADSUM]
272         + tcpstat[TCP_STAT_RCVBADOFF]
273         + tcpstat[TCP_STAT_RCVMEMDROP]
274         + tcpstat[TCP_STAT_RCVSHORT];
275     mib->tcpOutRsts = tcpstat[TCP_STAT_SNDCTRL]
276         - tcpstat[TCP_STAT_CLOSED];
277     mib->tcpInErrsValid = mib->tcpInErrs; /* FIXME */
278     mib->tcpOutRstsValid = mib->tcpOutRsts; /* FIXME */
279 
280     return 0;
281 }
282 
283 
284 int
netbsd_read_udp_stat(struct udp_mib * mib)285 netbsd_read_udp_stat(struct udp_mib *mib)
286 {
287     uint64_t udpstat[UDP_NSTATS];
288     size_t   size = sizeof(udpstat);
289 
290     (void)memset(mib, 0, sizeof(*mib));
291 
292     if (-1 == sysctlbyname("net.inet.udp.stats", udpstat, &size, NULL, 0)) {
293 	snmp_perror("netbsd_read_udp_stat: net.inet.udp.stats");
294         return -1;
295     }
296 
297     mib->udpInDatagrams = udpstat[UDP_STAT_IPACKETS];
298     mib->udpNoPorts = udpstat[UDP_STAT_NOPORT];
299     mib->udpOutDatagrams = udpstat[UDP_STAT_OPACKETS];
300     mib->udpInErrors = udpstat[UDP_STAT_HDROPS]
301         + udpstat[UDP_STAT_BADSUM] /* + udpstat[UDP_STAT_DISCARD] */ /* FIXME */
302         + udpstat[UDP_STAT_FULLSOCK] + udpstat[UDP_STAT_BADLEN];
303 
304     return 0;
305 }
306 
307 #endif
308