1 | /*- |
---|
2 | * Copyright (c) 1983, 1988, 1993, 1995 |
---|
3 | * The Regents of the University of California. All rights reserved. |
---|
4 | * |
---|
5 | * Redistribution and use in source and binary forms, with or without |
---|
6 | * modification, are permitted provided that the following conditions |
---|
7 | * are met: |
---|
8 | * 1. Redistributions of source code must retain the above copyright |
---|
9 | * notice, this list of conditions and the following disclaimer. |
---|
10 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
11 | * notice, this list of conditions and the following disclaimer in the |
---|
12 | * documentation and/or other materials provided with the distribution. |
---|
13 | * 3. All advertising materials mentioning features or use of this software |
---|
14 | * must display the following acknowledgement: |
---|
15 | * This product includes software developed by the University of |
---|
16 | * California, Berkeley and its contributors. |
---|
17 | * 4. Neither the name of the University nor the names of its contributors |
---|
18 | * may be used to endorse or promote products derived from this software |
---|
19 | * without specific prior written permission. |
---|
20 | * |
---|
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
---|
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
---|
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
---|
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
---|
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
---|
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
---|
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
---|
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
---|
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
---|
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
---|
31 | * SUCH DAMAGE. |
---|
32 | */ |
---|
33 | |
---|
34 | #if 0 |
---|
35 | #ifndef lint |
---|
36 | static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; |
---|
37 | #endif /* not lint */ |
---|
38 | #endif |
---|
39 | |
---|
40 | #include <sys/cdefs.h> |
---|
41 | __FBSDID("$FreeBSD$"); |
---|
42 | |
---|
43 | #include <rtems/bsd/sys/param.h> |
---|
44 | #include <sys/queue.h> |
---|
45 | #include <sys/domain.h> |
---|
46 | #include <sys/protosw.h> |
---|
47 | #include <sys/socket.h> |
---|
48 | #include <sys/socketvar.h> |
---|
49 | #include <sys/sysctl.h> |
---|
50 | |
---|
51 | #include <net/route.h> |
---|
52 | #include <net/if_arp.h> |
---|
53 | #include <netinet/in.h> |
---|
54 | #include <netinet/in_systm.h> |
---|
55 | #include <netinet/ip.h> |
---|
56 | #include <netinet/ip_carp.h> |
---|
57 | #ifdef INET6 |
---|
58 | #include <netinet/ip6.h> |
---|
59 | #endif /* INET6 */ |
---|
60 | #include <netinet/in_pcb.h> |
---|
61 | #include <netinet/ip_icmp.h> |
---|
62 | #include <netinet/icmp_var.h> |
---|
63 | #include <netinet/igmp_var.h> |
---|
64 | #include <netinet/ip_var.h> |
---|
65 | #include <netinet/pim_var.h> |
---|
66 | #include <netinet/tcp.h> |
---|
67 | #include <netinet/tcpip.h> |
---|
68 | #include <netinet/tcp_seq.h> |
---|
69 | #define TCPSTATES |
---|
70 | #include <netinet/tcp_fsm.h> |
---|
71 | #include <netinet/tcp_timer.h> |
---|
72 | #include <netinet/tcp_var.h> |
---|
73 | #include <netinet/tcp_debug.h> |
---|
74 | #include <netinet/udp.h> |
---|
75 | #include <netinet/udp_var.h> |
---|
76 | |
---|
77 | #include <arpa/inet.h> |
---|
78 | #include <err.h> |
---|
79 | #include <errno.h> |
---|
80 | #include <libutil.h> |
---|
81 | #include <netdb.h> |
---|
82 | #include <stdint.h> |
---|
83 | #include <stdio.h> |
---|
84 | #include <stdlib.h> |
---|
85 | #include <string.h> |
---|
86 | #include <unistd.h> |
---|
87 | #include "netstat.h" |
---|
88 | |
---|
89 | char *inetname(struct in_addr *); |
---|
90 | void inetprint(struct in_addr *, int, const char *, int); |
---|
91 | #ifdef INET6 |
---|
92 | static int udp_done, tcp_done; |
---|
93 | #endif /* INET6 */ |
---|
94 | |
---|
95 | static int |
---|
96 | pcblist_sysctl(int proto, char **bufp, int istcp) |
---|
97 | { |
---|
98 | const char *mibvar; |
---|
99 | char *buf; |
---|
100 | size_t len; |
---|
101 | |
---|
102 | switch (proto) { |
---|
103 | case IPPROTO_TCP: |
---|
104 | mibvar = "net.inet.tcp.pcblist"; |
---|
105 | break; |
---|
106 | case IPPROTO_UDP: |
---|
107 | mibvar = "net.inet.udp.pcblist"; |
---|
108 | break; |
---|
109 | case IPPROTO_DIVERT: |
---|
110 | mibvar = "net.inet.divert.pcblist"; |
---|
111 | break; |
---|
112 | default: |
---|
113 | mibvar = "net.inet.raw.pcblist"; |
---|
114 | break; |
---|
115 | } |
---|
116 | |
---|
117 | len = 0; |
---|
118 | if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { |
---|
119 | if (errno != ENOENT) |
---|
120 | warn("sysctl: %s", mibvar); |
---|
121 | return (0); |
---|
122 | } |
---|
123 | if ((buf = malloc(len)) == 0) { |
---|
124 | warnx("malloc %lu bytes", (u_long)len); |
---|
125 | return (0); |
---|
126 | } |
---|
127 | if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { |
---|
128 | warn("sysctl: %s", mibvar); |
---|
129 | free(buf); |
---|
130 | return (0); |
---|
131 | } |
---|
132 | *bufp = buf; |
---|
133 | return (1); |
---|
134 | } |
---|
135 | |
---|
136 | /* |
---|
137 | * Copied directly from uipc_socket2.c. We leave out some fields that are in |
---|
138 | * nested structures that aren't used to avoid extra work. |
---|
139 | */ |
---|
140 | static void |
---|
141 | sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb) |
---|
142 | { |
---|
143 | xsb->sb_cc = sb->sb_cc; |
---|
144 | xsb->sb_hiwat = sb->sb_hiwat; |
---|
145 | xsb->sb_mbcnt = sb->sb_mbcnt; |
---|
146 | xsb->sb_mcnt = sb->sb_mcnt; |
---|
147 | xsb->sb_ccnt = sb->sb_ccnt; |
---|
148 | xsb->sb_mbmax = sb->sb_mbmax; |
---|
149 | xsb->sb_lowat = sb->sb_lowat; |
---|
150 | xsb->sb_flags = sb->sb_flags; |
---|
151 | xsb->sb_timeo = sb->sb_timeo; |
---|
152 | } |
---|
153 | |
---|
154 | int |
---|
155 | sotoxsocket(struct socket *so, struct xsocket *xso) |
---|
156 | { |
---|
157 | struct protosw proto; |
---|
158 | struct domain domain; |
---|
159 | |
---|
160 | bzero(xso, sizeof *xso); |
---|
161 | xso->xso_len = sizeof *xso; |
---|
162 | xso->xso_so = so; |
---|
163 | xso->so_type = so->so_type; |
---|
164 | xso->so_options = so->so_options; |
---|
165 | xso->so_linger = so->so_linger; |
---|
166 | xso->so_state = so->so_state; |
---|
167 | xso->so_pcb = so->so_pcb; |
---|
168 | if (kread((uintptr_t)so->so_proto, &proto, sizeof(proto)) != 0) |
---|
169 | return (-1); |
---|
170 | xso->xso_protocol = proto.pr_protocol; |
---|
171 | if (kread((uintptr_t)proto.pr_domain, &domain, sizeof(domain)) != 0) |
---|
172 | return (-1); |
---|
173 | xso->xso_family = domain.dom_family; |
---|
174 | xso->so_qlen = so->so_qlen; |
---|
175 | xso->so_incqlen = so->so_incqlen; |
---|
176 | xso->so_qlimit = so->so_qlimit; |
---|
177 | xso->so_timeo = so->so_timeo; |
---|
178 | xso->so_error = so->so_error; |
---|
179 | xso->so_oobmark = so->so_oobmark; |
---|
180 | sbtoxsockbuf(&so->so_snd, &xso->so_snd); |
---|
181 | sbtoxsockbuf(&so->so_rcv, &xso->so_rcv); |
---|
182 | return (0); |
---|
183 | } |
---|
184 | |
---|
185 | static int |
---|
186 | pcblist_kvm(u_long off, char **bufp, int istcp) |
---|
187 | { |
---|
188 | struct inpcbinfo pcbinfo; |
---|
189 | struct inpcbhead listhead; |
---|
190 | struct inpcb *inp; |
---|
191 | struct xinpcb xi; |
---|
192 | struct xinpgen xig; |
---|
193 | struct xtcpcb xt; |
---|
194 | struct socket so; |
---|
195 | struct xsocket *xso; |
---|
196 | char *buf, *p; |
---|
197 | size_t len; |
---|
198 | |
---|
199 | if (off == 0) |
---|
200 | return (0); |
---|
201 | kread(off, &pcbinfo, sizeof(pcbinfo)); |
---|
202 | if (istcp) |
---|
203 | len = 2 * sizeof(xig) + |
---|
204 | (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) * |
---|
205 | sizeof(struct xtcpcb); |
---|
206 | else |
---|
207 | len = 2 * sizeof(xig) + |
---|
208 | (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) * |
---|
209 | sizeof(struct xinpcb); |
---|
210 | if ((buf = malloc(len)) == 0) { |
---|
211 | warnx("malloc %lu bytes", (u_long)len); |
---|
212 | return (0); |
---|
213 | } |
---|
214 | p = buf; |
---|
215 | |
---|
216 | #define COPYOUT(obj, size) do { \ |
---|
217 | if (len < (size)) { \ |
---|
218 | warnx("buffer size exceeded"); \ |
---|
219 | goto fail; \ |
---|
220 | } \ |
---|
221 | bcopy((obj), p, (size)); \ |
---|
222 | len -= (size); \ |
---|
223 | p += (size); \ |
---|
224 | } while (0) |
---|
225 | |
---|
226 | #define KREAD(off, buf, len) do { \ |
---|
227 | if (kread((uintptr_t)(off), (buf), (len)) != 0) \ |
---|
228 | goto fail; \ |
---|
229 | } while (0) |
---|
230 | |
---|
231 | /* Write out header. */ |
---|
232 | xig.xig_len = sizeof xig; |
---|
233 | xig.xig_count = pcbinfo.ipi_count; |
---|
234 | xig.xig_gen = pcbinfo.ipi_gencnt; |
---|
235 | xig.xig_sogen = 0; |
---|
236 | COPYOUT(&xig, sizeof xig); |
---|
237 | |
---|
238 | /* Walk the PCB list. */ |
---|
239 | xt.xt_len = sizeof xt; |
---|
240 | xi.xi_len = sizeof xi; |
---|
241 | if (istcp) |
---|
242 | xso = &xt.xt_socket; |
---|
243 | else |
---|
244 | xso = &xi.xi_socket; |
---|
245 | KREAD(pcbinfo.ipi_listhead, &listhead, sizeof(listhead)); |
---|
246 | LIST_FOREACH(inp, &listhead, inp_list) { |
---|
247 | if (istcp) { |
---|
248 | KREAD(inp, &xt.xt_inp, sizeof(*inp)); |
---|
249 | inp = &xt.xt_inp; |
---|
250 | } else { |
---|
251 | KREAD(inp, &xi.xi_inp, sizeof(*inp)); |
---|
252 | inp = &xi.xi_inp; |
---|
253 | } |
---|
254 | |
---|
255 | if (inp->inp_gencnt > pcbinfo.ipi_gencnt) |
---|
256 | continue; |
---|
257 | |
---|
258 | if (istcp) { |
---|
259 | if (inp->inp_ppcb == NULL) |
---|
260 | bzero(&xt.xt_tp, sizeof xt.xt_tp); |
---|
261 | else if (inp->inp_flags & INP_TIMEWAIT) { |
---|
262 | bzero(&xt.xt_tp, sizeof xt.xt_tp); |
---|
263 | xt.xt_tp.t_state = TCPS_TIME_WAIT; |
---|
264 | } else |
---|
265 | KREAD(inp->inp_ppcb, &xt.xt_tp, |
---|
266 | sizeof xt.xt_tp); |
---|
267 | } |
---|
268 | if (inp->inp_socket) { |
---|
269 | KREAD(inp->inp_socket, &so, sizeof(so)); |
---|
270 | if (sotoxsocket(&so, xso) != 0) |
---|
271 | goto fail; |
---|
272 | } else { |
---|
273 | bzero(xso, sizeof(*xso)); |
---|
274 | if (istcp) |
---|
275 | xso->xso_protocol = IPPROTO_TCP; |
---|
276 | } |
---|
277 | if (istcp) |
---|
278 | COPYOUT(&xt, sizeof xt); |
---|
279 | else |
---|
280 | COPYOUT(&xi, sizeof xi); |
---|
281 | } |
---|
282 | |
---|
283 | /* Reread the pcbinfo and write out the footer. */ |
---|
284 | kread(off, &pcbinfo, sizeof(pcbinfo)); |
---|
285 | xig.xig_count = pcbinfo.ipi_count; |
---|
286 | xig.xig_gen = pcbinfo.ipi_gencnt; |
---|
287 | COPYOUT(&xig, sizeof xig); |
---|
288 | |
---|
289 | *bufp = buf; |
---|
290 | return (1); |
---|
291 | |
---|
292 | fail: |
---|
293 | free(buf); |
---|
294 | return (0); |
---|
295 | #undef COPYOUT |
---|
296 | #undef KREAD |
---|
297 | } |
---|
298 | |
---|
299 | /* |
---|
300 | * Print a summary of connections related to an Internet |
---|
301 | * protocol. For TCP, also give state of connection. |
---|
302 | * Listening processes (aflag) are suppressed unless the |
---|
303 | * -a (all) flag is specified. |
---|
304 | */ |
---|
305 | void |
---|
306 | protopr(u_long off, const char *name, int af1, int proto) |
---|
307 | { |
---|
308 | int istcp; |
---|
309 | static int first = 1; |
---|
310 | char *buf; |
---|
311 | const char *vchar; |
---|
312 | struct tcpcb *tp = NULL; |
---|
313 | struct inpcb *inp; |
---|
314 | struct xinpgen *xig, *oxig; |
---|
315 | struct xsocket *so; |
---|
316 | |
---|
317 | istcp = 0; |
---|
318 | switch (proto) { |
---|
319 | case IPPROTO_TCP: |
---|
320 | #ifdef INET6 |
---|
321 | if (tcp_done != 0) |
---|
322 | return; |
---|
323 | else |
---|
324 | tcp_done = 1; |
---|
325 | #endif |
---|
326 | istcp = 1; |
---|
327 | break; |
---|
328 | case IPPROTO_UDP: |
---|
329 | #ifdef INET6 |
---|
330 | if (udp_done != 0) |
---|
331 | return; |
---|
332 | else |
---|
333 | udp_done = 1; |
---|
334 | #endif |
---|
335 | break; |
---|
336 | } |
---|
337 | if (live) { |
---|
338 | if (!pcblist_sysctl(proto, &buf, istcp)) |
---|
339 | return; |
---|
340 | } else { |
---|
341 | if (!pcblist_kvm(off, &buf, istcp)) |
---|
342 | return; |
---|
343 | } |
---|
344 | |
---|
345 | oxig = xig = (struct xinpgen *)buf; |
---|
346 | for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); |
---|
347 | xig->xig_len > sizeof(struct xinpgen); |
---|
348 | xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { |
---|
349 | if (istcp) { |
---|
350 | tp = &((struct xtcpcb *)xig)->xt_tp; |
---|
351 | inp = &((struct xtcpcb *)xig)->xt_inp; |
---|
352 | so = &((struct xtcpcb *)xig)->xt_socket; |
---|
353 | } else { |
---|
354 | inp = &((struct xinpcb *)xig)->xi_inp; |
---|
355 | so = &((struct xinpcb *)xig)->xi_socket; |
---|
356 | } |
---|
357 | |
---|
358 | /* Ignore sockets for protocols other than the desired one. */ |
---|
359 | if (so->xso_protocol != proto) |
---|
360 | continue; |
---|
361 | |
---|
362 | /* Ignore PCBs which were freed during copyout. */ |
---|
363 | if (inp->inp_gencnt > oxig->xig_gen) |
---|
364 | continue; |
---|
365 | |
---|
366 | if ((af1 == AF_INET && (inp->inp_vflag & INP_IPV4) == 0) |
---|
367 | #ifdef INET6 |
---|
368 | || (af1 == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0) |
---|
369 | #endif /* INET6 */ |
---|
370 | || (af1 == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0 |
---|
371 | #ifdef INET6 |
---|
372 | && (inp->inp_vflag & INP_IPV6) == 0 |
---|
373 | #endif /* INET6 */ |
---|
374 | )) |
---|
375 | ) |
---|
376 | continue; |
---|
377 | if (!aflag && |
---|
378 | ( |
---|
379 | (istcp && tp->t_state == TCPS_LISTEN) |
---|
380 | || (af1 == AF_INET && |
---|
381 | inet_lnaof(inp->inp_laddr) == INADDR_ANY) |
---|
382 | #ifdef INET6 |
---|
383 | || (af1 == AF_INET6 && |
---|
384 | IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) |
---|
385 | #endif /* INET6 */ |
---|
386 | || (af1 == AF_UNSPEC && |
---|
387 | (((inp->inp_vflag & INP_IPV4) != 0 && |
---|
388 | inet_lnaof(inp->inp_laddr) == INADDR_ANY) |
---|
389 | #ifdef INET6 |
---|
390 | || ((inp->inp_vflag & INP_IPV6) != 0 && |
---|
391 | IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) |
---|
392 | #endif |
---|
393 | )) |
---|
394 | )) |
---|
395 | continue; |
---|
396 | |
---|
397 | if (first) { |
---|
398 | if (!Lflag) { |
---|
399 | printf("Active Internet connections"); |
---|
400 | if (aflag) |
---|
401 | printf(" (including servers)"); |
---|
402 | } else |
---|
403 | printf( |
---|
404 | "Current listen queue sizes (qlen/incqlen/maxqlen)"); |
---|
405 | putchar('\n'); |
---|
406 | if (Aflag) |
---|
407 | printf("%-8.8s ", "Tcpcb"); |
---|
408 | if (Lflag) |
---|
409 | printf("%-5.5s %-14.14s %-22.22s\n", |
---|
410 | "Proto", "Listen", "Local Address"); |
---|
411 | else { |
---|
412 | printf((Aflag && !Wflag) ? |
---|
413 | "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s" : |
---|
414 | "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s", |
---|
415 | "Proto", "Recv-Q", "Send-Q", |
---|
416 | "Local Address", "Foreign Address"); |
---|
417 | if (xflag) |
---|
418 | printf("%-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %s\n", |
---|
419 | "R-MBUF", "S-MBUF", "R-CLUS", |
---|
420 | "S-CLUS", "R-HIWA", "S-HIWA", |
---|
421 | "R-LOWA", "S-LOWA", "R-BCNT", |
---|
422 | "S-BCNT", "R-BMAX", "S-BMAX", |
---|
423 | "(state)"); |
---|
424 | else |
---|
425 | printf("(state)\n"); |
---|
426 | } |
---|
427 | first = 0; |
---|
428 | } |
---|
429 | if (Lflag && so->so_qlimit == 0) |
---|
430 | continue; |
---|
431 | if (Aflag) { |
---|
432 | if (istcp) |
---|
433 | printf("%8lx ", (u_long)inp->inp_ppcb); |
---|
434 | else |
---|
435 | printf("%8lx ", (u_long)so->so_pcb); |
---|
436 | } |
---|
437 | #ifdef INET6 |
---|
438 | if ((inp->inp_vflag & INP_IPV6) != 0) |
---|
439 | vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? |
---|
440 | "46" : "6 "; |
---|
441 | else |
---|
442 | #endif |
---|
443 | vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? |
---|
444 | "4 " : " "; |
---|
445 | printf("%-3.3s%-2.2s ", name, vchar); |
---|
446 | if (Lflag) { |
---|
447 | char buf1[15]; |
---|
448 | |
---|
449 | snprintf(buf1, 15, "%d/%d/%d", so->so_qlen, |
---|
450 | so->so_incqlen, so->so_qlimit); |
---|
451 | printf("%-14.14s ", buf1); |
---|
452 | } else { |
---|
453 | printf("%6u %6u ", so->so_rcv.sb_cc, so->so_snd.sb_cc); |
---|
454 | } |
---|
455 | if (numeric_port) { |
---|
456 | if (inp->inp_vflag & INP_IPV4) { |
---|
457 | inetprint(&inp->inp_laddr, (int)inp->inp_lport, |
---|
458 | name, 1); |
---|
459 | if (!Lflag) |
---|
460 | inetprint(&inp->inp_faddr, |
---|
461 | (int)inp->inp_fport, name, 1); |
---|
462 | } |
---|
463 | #ifdef INET6 |
---|
464 | else if (inp->inp_vflag & INP_IPV6) { |
---|
465 | inet6print(&inp->in6p_laddr, |
---|
466 | (int)inp->inp_lport, name, 1); |
---|
467 | if (!Lflag) |
---|
468 | inet6print(&inp->in6p_faddr, |
---|
469 | (int)inp->inp_fport, name, 1); |
---|
470 | } /* else nothing printed now */ |
---|
471 | #endif /* INET6 */ |
---|
472 | } else if (inp->inp_flags & INP_ANONPORT) { |
---|
473 | if (inp->inp_vflag & INP_IPV4) { |
---|
474 | inetprint(&inp->inp_laddr, (int)inp->inp_lport, |
---|
475 | name, 1); |
---|
476 | if (!Lflag) |
---|
477 | inetprint(&inp->inp_faddr, |
---|
478 | (int)inp->inp_fport, name, 0); |
---|
479 | } |
---|
480 | #ifdef INET6 |
---|
481 | else if (inp->inp_vflag & INP_IPV6) { |
---|
482 | inet6print(&inp->in6p_laddr, |
---|
483 | (int)inp->inp_lport, name, 1); |
---|
484 | if (!Lflag) |
---|
485 | inet6print(&inp->in6p_faddr, |
---|
486 | (int)inp->inp_fport, name, 0); |
---|
487 | } /* else nothing printed now */ |
---|
488 | #endif /* INET6 */ |
---|
489 | } else { |
---|
490 | if (inp->inp_vflag & INP_IPV4) { |
---|
491 | inetprint(&inp->inp_laddr, (int)inp->inp_lport, |
---|
492 | name, 0); |
---|
493 | if (!Lflag) |
---|
494 | inetprint(&inp->inp_faddr, |
---|
495 | (int)inp->inp_fport, name, |
---|
496 | inp->inp_lport != inp->inp_fport); |
---|
497 | } |
---|
498 | #ifdef INET6 |
---|
499 | else if (inp->inp_vflag & INP_IPV6) { |
---|
500 | inet6print(&inp->in6p_laddr, |
---|
501 | (int)inp->inp_lport, name, 0); |
---|
502 | if (!Lflag) |
---|
503 | inet6print(&inp->in6p_faddr, |
---|
504 | (int)inp->inp_fport, name, |
---|
505 | inp->inp_lport != inp->inp_fport); |
---|
506 | } /* else nothing printed now */ |
---|
507 | #endif /* INET6 */ |
---|
508 | } |
---|
509 | if (xflag) { |
---|
510 | if (Lflag) |
---|
511 | printf("%21s %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ", |
---|
512 | " ", |
---|
513 | so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt, |
---|
514 | so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt, |
---|
515 | so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat, |
---|
516 | so->so_rcv.sb_lowat, so->so_snd.sb_lowat, |
---|
517 | so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt, |
---|
518 | so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax); |
---|
519 | else |
---|
520 | printf("%6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ", |
---|
521 | so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt, |
---|
522 | so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt, |
---|
523 | so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat, |
---|
524 | so->so_rcv.sb_lowat, so->so_snd.sb_lowat, |
---|
525 | so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt, |
---|
526 | so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax); |
---|
527 | } |
---|
528 | if (istcp && !Lflag) { |
---|
529 | if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) |
---|
530 | printf("%d", tp->t_state); |
---|
531 | else { |
---|
532 | printf("%s", tcpstates[tp->t_state]); |
---|
533 | #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) |
---|
534 | /* Show T/TCP `hidden state' */ |
---|
535 | if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) |
---|
536 | putchar('*'); |
---|
537 | #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ |
---|
538 | } |
---|
539 | } |
---|
540 | putchar('\n'); |
---|
541 | } |
---|
542 | if (xig != oxig && xig->xig_gen != oxig->xig_gen) { |
---|
543 | if (oxig->xig_count > xig->xig_count) { |
---|
544 | printf("Some %s sockets may have been deleted.\n", |
---|
545 | name); |
---|
546 | } else if (oxig->xig_count < xig->xig_count) { |
---|
547 | printf("Some %s sockets may have been created.\n", |
---|
548 | name); |
---|
549 | } else { |
---|
550 | printf( |
---|
551 | "Some %s sockets may have been created or deleted.\n", |
---|
552 | name); |
---|
553 | } |
---|
554 | } |
---|
555 | free(buf); |
---|
556 | } |
---|
557 | |
---|
558 | /* |
---|
559 | * Dump TCP statistics structure. |
---|
560 | */ |
---|
561 | void |
---|
562 | tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) |
---|
563 | { |
---|
564 | struct tcpstat tcpstat, zerostat; |
---|
565 | size_t len = sizeof tcpstat; |
---|
566 | |
---|
567 | #ifdef INET6 |
---|
568 | if (tcp_done != 0) |
---|
569 | return; |
---|
570 | else |
---|
571 | tcp_done = 1; |
---|
572 | #endif |
---|
573 | |
---|
574 | if (live) { |
---|
575 | if (zflag) |
---|
576 | memset(&zerostat, 0, len); |
---|
577 | if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, |
---|
578 | zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { |
---|
579 | warn("sysctl: net.inet.tcp.stats"); |
---|
580 | return; |
---|
581 | } |
---|
582 | } else |
---|
583 | kread(off, &tcpstat, len); |
---|
584 | |
---|
585 | printf ("%s:\n", name); |
---|
586 | |
---|
587 | #define p(f, m) if (tcpstat.f || sflag <= 1) \ |
---|
588 | printf(m, tcpstat.f, plural(tcpstat.f)) |
---|
589 | #define p1a(f, m) if (tcpstat.f || sflag <= 1) \ |
---|
590 | printf(m, tcpstat.f) |
---|
591 | #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ |
---|
592 | printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) |
---|
593 | #define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ |
---|
594 | printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2) |
---|
595 | #define p3(f, m) if (tcpstat.f || sflag <= 1) \ |
---|
596 | printf(m, tcpstat.f, pluralies(tcpstat.f)) |
---|
597 | |
---|
598 | p(tcps_sndtotal, "\t%lu packet%s sent\n"); |
---|
599 | p2(tcps_sndpack,tcps_sndbyte, "\t\t%lu data packet%s (%lu byte%s)\n"); |
---|
600 | p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, |
---|
601 | "\t\t%lu data packet%s (%lu byte%s) retransmitted\n"); |
---|
602 | p(tcps_sndrexmitbad, |
---|
603 | "\t\t%lu data packet%s unnecessarily retransmitted\n"); |
---|
604 | p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n"); |
---|
605 | p2a(tcps_sndacks, tcps_delack, |
---|
606 | "\t\t%lu ack-only packet%s (%lu delayed)\n"); |
---|
607 | p(tcps_sndurg, "\t\t%lu URG only packet%s\n"); |
---|
608 | p(tcps_sndprobe, "\t\t%lu window probe packet%s\n"); |
---|
609 | p(tcps_sndwinup, "\t\t%lu window update packet%s\n"); |
---|
610 | p(tcps_sndctrl, "\t\t%lu control packet%s\n"); |
---|
611 | p(tcps_rcvtotal, "\t%lu packet%s received\n"); |
---|
612 | p2(tcps_rcvackpack, tcps_rcvackbyte, |
---|
613 | "\t\t%lu ack%s (for %lu byte%s)\n"); |
---|
614 | p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n"); |
---|
615 | p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n"); |
---|
616 | p2(tcps_rcvpack, tcps_rcvbyte, |
---|
617 | "\t\t%lu packet%s (%lu byte%s) received in-sequence\n"); |
---|
618 | p2(tcps_rcvduppack, tcps_rcvdupbyte, |
---|
619 | "\t\t%lu completely duplicate packet%s (%lu byte%s)\n"); |
---|
620 | p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n"); |
---|
621 | p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, |
---|
622 | "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n"); |
---|
623 | p2(tcps_rcvoopack, tcps_rcvoobyte, |
---|
624 | "\t\t%lu out-of-order packet%s (%lu byte%s)\n"); |
---|
625 | p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, |
---|
626 | "\t\t%lu packet%s (%lu byte%s) of data after window\n"); |
---|
627 | p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n"); |
---|
628 | p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n"); |
---|
629 | p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n"); |
---|
630 | p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n"); |
---|
631 | p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n"); |
---|
632 | p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n"); |
---|
633 | p1a(tcps_rcvmemdrop, "\t\t%lu discarded due to memory problems\n"); |
---|
634 | p(tcps_connattempt, "\t%lu connection request%s\n"); |
---|
635 | p(tcps_accepts, "\t%lu connection accept%s\n"); |
---|
636 | p(tcps_badsyn, "\t%lu bad connection attempt%s\n"); |
---|
637 | p(tcps_listendrop, "\t%lu listen queue overflow%s\n"); |
---|
638 | p(tcps_badrst, "\t%lu ignored RSTs in the window%s\n"); |
---|
639 | p(tcps_connects, "\t%lu connection%s established (including accepts)\n"); |
---|
640 | p2(tcps_closed, tcps_drops, |
---|
641 | "\t%lu connection%s closed (including %lu drop%s)\n"); |
---|
642 | p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n"); |
---|
643 | p(tcps_cachedrttvar, |
---|
644 | "\t\t%lu connection%s updated cached RTT variance on close\n"); |
---|
645 | p(tcps_cachedssthresh, |
---|
646 | "\t\t%lu connection%s updated cached ssthresh on close\n"); |
---|
647 | p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n"); |
---|
648 | p2(tcps_rttupdated, tcps_segstimed, |
---|
649 | "\t%lu segment%s updated rtt (of %lu attempt%s)\n"); |
---|
650 | p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n"); |
---|
651 | p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n"); |
---|
652 | p(tcps_persisttimeo, "\t%lu persist timeout%s\n"); |
---|
653 | p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n"); |
---|
654 | p(tcps_finwait2_drops, |
---|
655 | "\t%lu Connection%s (fin_wait_2) dropped because of timeout\n"); |
---|
656 | p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n"); |
---|
657 | p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n"); |
---|
658 | p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n"); |
---|
659 | p(tcps_predack, "\t%lu correct ACK header prediction%s\n"); |
---|
660 | p(tcps_preddat, "\t%lu correct data packet header prediction%s\n"); |
---|
661 | |
---|
662 | p3(tcps_sc_added, "\t%lu syncache entr%s added\n"); |
---|
663 | p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n"); |
---|
664 | p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n"); |
---|
665 | p1a(tcps_sc_dropped, "\t\t%lu dropped\n"); |
---|
666 | p1a(tcps_sc_completed, "\t\t%lu completed\n"); |
---|
667 | p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n"); |
---|
668 | p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n"); |
---|
669 | p1a(tcps_sc_reset, "\t\t%lu reset\n"); |
---|
670 | p1a(tcps_sc_stale, "\t\t%lu stale\n"); |
---|
671 | p1a(tcps_sc_aborted, "\t\t%lu aborted\n"); |
---|
672 | p1a(tcps_sc_badack, "\t\t%lu badack\n"); |
---|
673 | p1a(tcps_sc_unreach, "\t\t%lu unreach\n"); |
---|
674 | p(tcps_sc_zonefail, "\t\t%lu zone failure%s\n"); |
---|
675 | p(tcps_sc_sendcookie, "\t%lu cookie%s sent\n"); |
---|
676 | p(tcps_sc_recvcookie, "\t%lu cookie%s received\n"); |
---|
677 | |
---|
678 | p(tcps_sack_recovery_episode, "\t%lu SACK recovery episode%s\n"); |
---|
679 | p(tcps_sack_rexmits, |
---|
680 | "\t%lu segment rexmit%s in SACK recovery episodes\n"); |
---|
681 | p(tcps_sack_rexmit_bytes, |
---|
682 | "\t%lu byte rexmit%s in SACK recovery episodes\n"); |
---|
683 | p(tcps_sack_rcv_blocks, |
---|
684 | "\t%lu SACK option%s (SACK blocks) received\n"); |
---|
685 | p(tcps_sack_send_blocks, "\t%lu SACK option%s (SACK blocks) sent\n"); |
---|
686 | p1a(tcps_sack_sboverflow, "\t%lu SACK scoreboard overflow\n"); |
---|
687 | |
---|
688 | p(tcps_ecn_ce, "\t%lu packet%s with ECN CE bit set\n"); |
---|
689 | p(tcps_ecn_ect0, "\t%lu packet%s with ECN ECT(0) bit set\n"); |
---|
690 | p(tcps_ecn_ect1, "\t%lu packet%s with ECN ECT(1) bit set\n"); |
---|
691 | p(tcps_ecn_shs, "\t%lu successful ECN handshake%s\n"); |
---|
692 | p(tcps_ecn_rcwnd, "\t%lu time%s ECN reduced the congestion window\n"); |
---|
693 | #undef p |
---|
694 | #undef p1a |
---|
695 | #undef p2 |
---|
696 | #undef p2a |
---|
697 | #undef p3 |
---|
698 | } |
---|
699 | |
---|
700 | /* |
---|
701 | * Dump UDP statistics structure. |
---|
702 | */ |
---|
703 | void |
---|
704 | udp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) |
---|
705 | { |
---|
706 | struct udpstat udpstat, zerostat; |
---|
707 | size_t len = sizeof udpstat; |
---|
708 | u_long delivered; |
---|
709 | |
---|
710 | #ifdef INET6 |
---|
711 | if (udp_done != 0) |
---|
712 | return; |
---|
713 | else |
---|
714 | udp_done = 1; |
---|
715 | #endif |
---|
716 | |
---|
717 | if (live) { |
---|
718 | if (zflag) |
---|
719 | memset(&zerostat, 0, len); |
---|
720 | if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, |
---|
721 | zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { |
---|
722 | warn("sysctl: net.inet.udp.stats"); |
---|
723 | return; |
---|
724 | } |
---|
725 | } else |
---|
726 | kread(off, &udpstat, len); |
---|
727 | |
---|
728 | printf("%s:\n", name); |
---|
729 | #define p(f, m) if (udpstat.f || sflag <= 1) \ |
---|
730 | printf(m, udpstat.f, plural(udpstat.f)) |
---|
731 | #define p1a(f, m) if (udpstat.f || sflag <= 1) \ |
---|
732 | printf(m, udpstat.f) |
---|
733 | p(udps_ipackets, "\t%lu datagram%s received\n"); |
---|
734 | p1a(udps_hdrops, "\t%lu with incomplete header\n"); |
---|
735 | p1a(udps_badlen, "\t%lu with bad data length field\n"); |
---|
736 | p1a(udps_badsum, "\t%lu with bad checksum\n"); |
---|
737 | p1a(udps_nosum, "\t%lu with no checksum\n"); |
---|
738 | p1a(udps_noport, "\t%lu dropped due to no socket\n"); |
---|
739 | p(udps_noportbcast, |
---|
740 | "\t%lu broadcast/multicast datagram%s undelivered\n"); |
---|
741 | p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n"); |
---|
742 | p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n"); |
---|
743 | delivered = udpstat.udps_ipackets - |
---|
744 | udpstat.udps_hdrops - |
---|
745 | udpstat.udps_badlen - |
---|
746 | udpstat.udps_badsum - |
---|
747 | udpstat.udps_noport - |
---|
748 | udpstat.udps_noportbcast - |
---|
749 | udpstat.udps_fullsock; |
---|
750 | if (delivered || sflag <= 1) |
---|
751 | printf("\t%lu delivered\n", delivered); |
---|
752 | p(udps_opackets, "\t%lu datagram%s output\n"); |
---|
753 | /* the next statistic is cumulative in udps_noportbcast */ |
---|
754 | p(udps_filtermcast, |
---|
755 | "\t%lu time%s multicast source filter matched\n"); |
---|
756 | #undef p |
---|
757 | #undef p1a |
---|
758 | } |
---|
759 | |
---|
760 | /* |
---|
761 | * Dump CARP statistics structure. |
---|
762 | */ |
---|
763 | void |
---|
764 | carp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) |
---|
765 | { |
---|
766 | struct carpstats carpstat, zerostat; |
---|
767 | size_t len = sizeof(struct carpstats); |
---|
768 | |
---|
769 | if (live) { |
---|
770 | if (zflag) |
---|
771 | memset(&zerostat, 0, len); |
---|
772 | if (sysctlbyname("net.inet.carp.stats", &carpstat, &len, |
---|
773 | zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { |
---|
774 | if (errno != ENOENT) |
---|
775 | warn("sysctl: net.inet.carp.stats"); |
---|
776 | return; |
---|
777 | } |
---|
778 | } else { |
---|
779 | if (off == 0) |
---|
780 | return; |
---|
781 | kread(off, &carpstat, len); |
---|
782 | } |
---|
783 | |
---|
784 | printf("%s:\n", name); |
---|
785 | |
---|
786 | #define p(f, m) if (carpstat.f || sflag <= 1) \ |
---|
787 | printf(m, (uintmax_t)carpstat.f, plural(carpstat.f)) |
---|
788 | #define p2(f, m) if (carpstat.f || sflag <= 1) \ |
---|
789 | printf(m, (uintmax_t)carpstat.f) |
---|
790 | |
---|
791 | p(carps_ipackets, "\t%ju packet%s received (IPv4)\n"); |
---|
792 | p(carps_ipackets6, "\t%ju packet%s received (IPv6)\n"); |
---|
793 | p(carps_badttl, "\t\t%ju packet%s discarded for wrong TTL\n"); |
---|
794 | p(carps_hdrops, "\t\t%ju packet%s shorter than header\n"); |
---|
795 | p(carps_badsum, "\t\t%ju discarded for bad checksum%s\n"); |
---|
796 | p(carps_badver, "\t\t%ju discarded packet%s with a bad version\n"); |
---|
797 | p2(carps_badlen, "\t\t%ju discarded because packet too short\n"); |
---|
798 | p2(carps_badauth, "\t\t%ju discarded for bad authentication\n"); |
---|
799 | p2(carps_badvhid, "\t\t%ju discarded for bad vhid\n"); |
---|
800 | p2(carps_badaddrs, "\t\t%ju discarded because of a bad address list\n"); |
---|
801 | p(carps_opackets, "\t%ju packet%s sent (IPv4)\n"); |
---|
802 | p(carps_opackets6, "\t%ju packet%s sent (IPv6)\n"); |
---|
803 | p2(carps_onomem, "\t\t%ju send failed due to mbuf memory error\n"); |
---|
804 | #if notyet |
---|
805 | p(carps_ostates, "\t\t%s state update%s sent\n"); |
---|
806 | #endif |
---|
807 | #undef p |
---|
808 | #undef p2 |
---|
809 | } |
---|
810 | |
---|
811 | /* |
---|
812 | * Dump IP statistics structure. |
---|
813 | */ |
---|
814 | void |
---|
815 | ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused) |
---|
816 | { |
---|
817 | struct ipstat ipstat, zerostat; |
---|
818 | size_t len = sizeof ipstat; |
---|
819 | |
---|
820 | if (live) { |
---|
821 | if (zflag) |
---|
822 | memset(&zerostat, 0, len); |
---|
823 | if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, |
---|
824 | zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { |
---|
825 | warn("sysctl: net.inet.ip.stats"); |
---|
826 | return; |
---|
827 | } |
---|
828 | } else |
---|
829 | kread(off, &ipstat, len); |
---|
830 | |
---|
831 | printf("%s:\n", name); |
---|
832 | |
---|
833 | #define p(f, m) if (ipstat.f || sflag <= 1) \ |
---|
834 | printf(m, ipstat.f, plural(ipstat.f)) |
---|
835 | #define p1a(f, m) if (ipstat.f || sflag <= 1) \ |
---|
836 | printf(m, ipstat.f) |
---|
837 | |
---|
838 | p(ips_total, "\t%lu total packet%s received\n"); |
---|
839 | p(ips_badsum, "\t%lu bad header checksum%s\n"); |
---|
840 | p1a(ips_toosmall, "\t%lu with size smaller than minimum\n"); |
---|
841 | p1a(ips_tooshort, "\t%lu with data size < data length\n"); |
---|
842 | p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n"); |
---|
843 | p1a(ips_badhlen, "\t%lu with header length < data size\n"); |
---|
844 | p1a(ips_badlen, "\t%lu with data length < header length\n"); |
---|
845 | p1a(ips_badoptions, "\t%lu with bad options\n"); |
---|
846 | p1a(ips_badvers, "\t%lu with incorrect version number\n"); |
---|
847 | p(ips_fragments, "\t%lu fragment%s received\n"); |
---|
848 | p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n"); |
---|
849 | p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n"); |
---|
850 | p(ips_reassembled, "\t%lu packet%s reassembled ok\n"); |
---|
851 | p(ips_delivered, "\t%lu packet%s for this host\n"); |
---|
852 | p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n"); |
---|
853 | p(ips_forward, "\t%lu packet%s forwarded"); |
---|
854 | p(ips_fastforward, " (%lu packet%s fast forwarded)"); |
---|
855 | if (ipstat.ips_forward || sflag <= 1) |
---|
856 | putchar('\n'); |
---|
857 | p(ips_cantforward, "\t%lu packet%s not forwardable\n"); |
---|
858 | p(ips_notmember, |
---|
859 | "\t%lu packet%s received for unknown multicast group\n"); |
---|
860 | p(ips_redirectsent, "\t%lu redirect%s sent\n"); |
---|
861 | p(ips_localout, "\t%lu packet%s sent from this host\n"); |
---|
862 | p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n"); |
---|
863 | p(ips_odropped, |
---|
864 | "\t%lu output packet%s dropped due to no bufs, etc.\n"); |
---|
865 | p(ips_noroute, "\t%lu output packet%s discarded due to no route\n"); |
---|
866 | p(ips_fragmented, "\t%lu output datagram%s fragmented\n"); |
---|
867 | p(ips_ofragments, "\t%lu fragment%s created\n"); |
---|
868 | p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n"); |
---|
869 | p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n"); |
---|
870 | p(ips_badaddr, "\t%lu datagram%s with bad address in header\n"); |
---|
871 | #undef p |
---|
872 | #undef p1a |
---|
873 | } |
---|
874 | |
---|
875 | /* |
---|
876 | * Dump ARP statistics structure. |
---|
877 | */ |
---|
878 | void |
---|
879 | arp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) |
---|
880 | { |
---|
881 | struct arpstat arpstat, zerostat; |
---|
882 | size_t len = sizeof(arpstat); |
---|
883 | |
---|
884 | if (live) { |
---|
885 | if (zflag) |
---|
886 | memset(&zerostat, 0, len); |
---|
887 | if (sysctlbyname("net.link.ether.arp.stats", &arpstat, &len, |
---|
888 | zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { |
---|
889 | warn("sysctl: net.link.ether.arp.stats"); |
---|
890 | return; |
---|
891 | } |
---|
892 | } else |
---|
893 | kread(off, &arpstat, len); |
---|
894 | |
---|
895 | printf("%s:\n", name); |
---|
896 | |
---|
897 | #define p(f, m) if (arpstat.f || sflag <= 1) \ |
---|
898 | printf(m, arpstat.f, plural(arpstat.f)) |
---|
899 | #define p2(f, m) if (arpstat.f || sflag <= 1) \ |
---|
900 | printf(m, arpstat.f, pluralies(arpstat.f)) |
---|
901 | |
---|
902 | p(txrequests, "\t%lu ARP request%s sent\n"); |
---|
903 | p2(txreplies, "\t%lu ARP repl%s sent\n"); |
---|
904 | p(rxrequests, "\t%lu ARP request%s received\n"); |
---|
905 | p2(rxreplies, "\t%lu ARP repl%s received\n"); |
---|
906 | p(received, "\t%lu ARP packet%s received\n"); |
---|
907 | p(dropped, "\t%lu total packet%s dropped due to no ARP entry\n"); |
---|
908 | p(timeouts, "\t%lu ARP entry%s timed out\n"); |
---|
909 | p(dupips, "\t%lu Duplicate IP%s seen\n"); |
---|
910 | #undef p |
---|
911 | #undef p2 |
---|
912 | } |
---|
913 | |
---|
914 | |
---|
915 | |
---|
916 | static const char *icmpnames[ICMP_MAXTYPE + 1] = { |
---|
917 | "echo reply", /* RFC 792 */ |
---|
918 | "#1", |
---|
919 | "#2", |
---|
920 | "destination unreachable", /* RFC 792 */ |
---|
921 | "source quench", /* RFC 792 */ |
---|
922 | "routing redirect", /* RFC 792 */ |
---|
923 | "#6", |
---|
924 | "#7", |
---|
925 | "echo", /* RFC 792 */ |
---|
926 | "router advertisement", /* RFC 1256 */ |
---|
927 | "router solicitation", /* RFC 1256 */ |
---|
928 | "time exceeded", /* RFC 792 */ |
---|
929 | "parameter problem", /* RFC 792 */ |
---|
930 | "time stamp", /* RFC 792 */ |
---|
931 | "time stamp reply", /* RFC 792 */ |
---|
932 | "information request", /* RFC 792 */ |
---|
933 | "information request reply", /* RFC 792 */ |
---|
934 | "address mask request", /* RFC 950 */ |
---|
935 | "address mask reply", /* RFC 950 */ |
---|
936 | "#19", |
---|
937 | "#20", |
---|
938 | "#21", |
---|
939 | "#22", |
---|
940 | "#23", |
---|
941 | "#24", |
---|
942 | "#25", |
---|
943 | "#26", |
---|
944 | "#27", |
---|
945 | "#28", |
---|
946 | "#29", |
---|
947 | "icmp traceroute", /* RFC 1393 */ |
---|
948 | "datagram conversion error", /* RFC 1475 */ |
---|
949 | "mobile host redirect", |
---|
950 | "IPv6 where-are-you", |
---|
951 | "IPv6 i-am-here", |
---|
952 | "mobile registration req", |
---|
953 | "mobile registration reply", |
---|
954 | "domain name request", /* RFC 1788 */ |
---|
955 | "domain name reply", /* RFC 1788 */ |
---|
956 | "icmp SKIP", |
---|
957 | "icmp photuris", /* RFC 2521 */ |
---|
958 | }; |
---|
959 | |
---|
960 | /* |
---|
961 | * Dump ICMP statistics. |
---|
962 | */ |
---|
963 | void |
---|
964 | icmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) |
---|
965 | { |
---|
966 | struct icmpstat icmpstat, zerostat; |
---|
967 | int i, first; |
---|
968 | size_t len; |
---|
969 | |
---|
970 | len = sizeof icmpstat; |
---|
971 | if (live) { |
---|
972 | if (zflag) |
---|
973 | memset(&zerostat, 0, len); |
---|
974 | if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len, |
---|
975 | zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { |
---|
976 | warn("sysctl: net.inet.icmp.stats"); |
---|
977 | return; |
---|
978 | } |
---|
979 | } else |
---|
980 | kread(off, &icmpstat, len); |
---|
981 | |
---|
982 | printf("%s:\n", name); |
---|
983 | |
---|
984 | #define p(f, m) if (icmpstat.f || sflag <= 1) \ |
---|
985 | printf(m, icmpstat.f, plural(icmpstat.f)) |
---|
986 | #define p1a(f, m) if (icmpstat.f || sflag <= 1) \ |
---|
987 | printf(m, icmpstat.f) |
---|
988 | #define p2(f, m) if (icmpstat.f || sflag <= 1) \ |
---|
989 | printf(m, icmpstat.f, plurales(icmpstat.f)) |
---|
990 | |
---|
991 | p(icps_error, "\t%lu call%s to icmp_error\n"); |
---|
992 | p(icps_oldicmp, |
---|
993 | "\t%lu error%s not generated in response to an icmp message\n"); |
---|
994 | for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) |
---|
995 | if (icmpstat.icps_outhist[i] != 0) { |
---|
996 | if (first) { |
---|
997 | printf("\tOutput histogram:\n"); |
---|
998 | first = 0; |
---|
999 | } |
---|
1000 | if (icmpnames[i] != NULL) |
---|
1001 | printf("\t\t%s: %lu\n", icmpnames[i], |
---|
1002 | icmpstat.icps_outhist[i]); |
---|
1003 | else |
---|
1004 | printf("\t\tunknown ICMP #%d: %lu\n", i, |
---|
1005 | icmpstat.icps_outhist[i]); |
---|
1006 | } |
---|
1007 | p(icps_badcode, "\t%lu message%s with bad code fields\n"); |
---|
1008 | p(icps_tooshort, "\t%lu message%s less than the minimum length\n"); |
---|
1009 | p(icps_checksum, "\t%lu message%s with bad checksum\n"); |
---|
1010 | p(icps_badlen, "\t%lu message%s with bad length\n"); |
---|
1011 | p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n"); |
---|
1012 | p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n"); |
---|
1013 | for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) |
---|
1014 | if (icmpstat.icps_inhist[i] != 0) { |
---|
1015 | if (first) { |
---|
1016 | printf("\tInput histogram:\n"); |
---|
1017 | first = 0; |
---|
1018 | } |
---|
1019 | if (icmpnames[i] != NULL) |
---|
1020 | printf("\t\t%s: %lu\n", icmpnames[i], |
---|
1021 | icmpstat.icps_inhist[i]); |
---|
1022 | else |
---|
1023 | printf("\t\tunknown ICMP #%d: %lu\n", i, |
---|
1024 | icmpstat.icps_inhist[i]); |
---|
1025 | } |
---|
1026 | p(icps_reflect, "\t%lu message response%s generated\n"); |
---|
1027 | p2(icps_badaddr, "\t%lu invalid return address%s\n"); |
---|
1028 | p(icps_noroute, "\t%lu no return route%s\n"); |
---|
1029 | #undef p |
---|
1030 | #undef p1a |
---|
1031 | #undef p2 |
---|
1032 | if (live) { |
---|
1033 | len = sizeof i; |
---|
1034 | if (sysctlbyname("net.inet.icmp.maskrepl", &i, &len, NULL, 0) < |
---|
1035 | 0) |
---|
1036 | return; |
---|
1037 | printf("\tICMP address mask responses are %sabled\n", |
---|
1038 | i ? "en" : "dis"); |
---|
1039 | } |
---|
1040 | } |
---|
1041 | |
---|
1042 | #ifndef BURN_BRIDGES |
---|
1043 | /* |
---|
1044 | * Dump IGMP statistics structure (pre 8.x kernel). |
---|
1045 | */ |
---|
1046 | static void |
---|
1047 | igmp_stats_live_old(u_long off, const char *name) |
---|
1048 | { |
---|
1049 | struct oigmpstat oigmpstat, zerostat; |
---|
1050 | size_t len = sizeof(oigmpstat); |
---|
1051 | |
---|
1052 | if (zflag) |
---|
1053 | memset(&zerostat, 0, len); |
---|
1054 | if (sysctlbyname("net.inet.igmp.stats", &oigmpstat, &len, |
---|
1055 | zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { |
---|
1056 | warn("sysctl: net.inet.igmp.stats"); |
---|
1057 | return; |
---|
1058 | } |
---|
1059 | |
---|
1060 | printf("%s:\n", name); |
---|
1061 | |
---|
1062 | #define p(f, m) if (oigmpstat.f || sflag <= 1) \ |
---|
1063 | printf(m, oigmpstat.f, plural(oigmpstat.f)) |
---|
1064 | #define py(f, m) if (oigmpstat.f || sflag <= 1) \ |
---|
1065 | printf(m, oigmpstat.f, oigmpstat.f != 1 ? "ies" : "y") |
---|
1066 | p(igps_rcv_total, "\t%u message%s received\n"); |
---|
1067 | p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n"); |
---|
1068 | p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n"); |
---|
1069 | py(igps_rcv_queries, "\t%u membership quer%s received\n"); |
---|
1070 | py(igps_rcv_badqueries, |
---|
1071 | "\t%u membership quer%s received with invalid field(s)\n"); |
---|
1072 | p(igps_rcv_reports, "\t%u membership report%s received\n"); |
---|
1073 | p(igps_rcv_badreports, |
---|
1074 | "\t%u membership report%s received with invalid field(s)\n"); |
---|
1075 | p(igps_rcv_ourreports, |
---|
1076 | "\t%u membership report%s received for groups to which we belong\n"); |
---|
1077 | p(igps_snd_reports, "\t%u membership report%s sent\n"); |
---|
1078 | #undef p |
---|
1079 | #undef py |
---|
1080 | } |
---|
1081 | #endif /* !BURN_BRIDGES */ |
---|
1082 | |
---|
1083 | /* |
---|
1084 | * Dump IGMP statistics structure. |
---|
1085 | */ |
---|
1086 | void |
---|
1087 | igmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) |
---|
1088 | { |
---|
1089 | struct igmpstat igmpstat, zerostat; |
---|
1090 | size_t len; |
---|
1091 | |
---|
1092 | #ifndef BURN_BRIDGES |
---|
1093 | if (live) { |
---|
1094 | /* |
---|
1095 | * Detect if we are being run against a pre-IGMPv3 kernel. |
---|
1096 | * We cannot do this for a core file as the legacy |
---|
1097 | * struct igmpstat has no size field, nor does it |
---|
1098 | * export it in any readily-available symbols. |
---|
1099 | */ |
---|
1100 | len = 0; |
---|
1101 | if (sysctlbyname("net.inet.igmp.stats", NULL, &len, NULL, |
---|
1102 | 0) < 0) { |
---|
1103 | warn("sysctl: net.inet.igmp.stats"); |
---|
1104 | return; |
---|
1105 | } |
---|
1106 | if (len < sizeof(igmpstat)) { |
---|
1107 | igmp_stats_live_old(off, name); |
---|
1108 | return; |
---|
1109 | } |
---|
1110 | } |
---|
1111 | #endif /* !BURN_BRIDGES */ |
---|
1112 | |
---|
1113 | len = sizeof(igmpstat); |
---|
1114 | if (live) { |
---|
1115 | if (zflag) |
---|
1116 | memset(&zerostat, 0, len); |
---|
1117 | if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, |
---|
1118 | zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { |
---|
1119 | warn("sysctl: net.inet.igmp.stats"); |
---|
1120 | return; |
---|
1121 | } |
---|
1122 | } else { |
---|
1123 | len = sizeof(igmpstat); |
---|
1124 | kread(off, &igmpstat, len); |
---|
1125 | } |
---|
1126 | |
---|
1127 | if (igmpstat.igps_version != IGPS_VERSION_3) { |
---|
1128 | warnx("%s: version mismatch (%d != %d)", __func__, |
---|
1129 | igmpstat.igps_version, IGPS_VERSION_3); |
---|
1130 | } |
---|
1131 | if (igmpstat.igps_len != IGPS_VERSION3_LEN) { |
---|
1132 | warnx("%s: size mismatch (%d != %d)", __func__, |
---|
1133 | igmpstat.igps_len, IGPS_VERSION3_LEN); |
---|
1134 | } |
---|
1135 | |
---|
1136 | printf("%s:\n", name); |
---|
1137 | |
---|
1138 | #define p64(f, m) if (igmpstat.f || sflag <= 1) \ |
---|
1139 | printf(m, (uintmax_t) igmpstat.f, plural(igmpstat.f)) |
---|
1140 | #define py64(f, m) if (igmpstat.f || sflag <= 1) \ |
---|
1141 | printf(m, (uintmax_t) igmpstat.f, pluralies(igmpstat.f)) |
---|
1142 | p64(igps_rcv_total, "\t%ju message%s received\n"); |
---|
1143 | p64(igps_rcv_tooshort, "\t%ju message%s received with too few bytes\n"); |
---|
1144 | p64(igps_rcv_badttl, "\t%ju message%s received with wrong TTL\n"); |
---|
1145 | p64(igps_rcv_badsum, "\t%ju message%s received with bad checksum\n"); |
---|
1146 | py64(igps_rcv_v1v2_queries, "\t%ju V1/V2 membership quer%s received\n"); |
---|
1147 | py64(igps_rcv_v3_queries, "\t%ju V3 membership quer%s received\n"); |
---|
1148 | py64(igps_rcv_badqueries, |
---|
1149 | "\t%ju membership quer%s received with invalid field(s)\n"); |
---|
1150 | py64(igps_rcv_gen_queries, "\t%ju general quer%s received\n"); |
---|
1151 | py64(igps_rcv_group_queries, "\t%ju group quer%s received\n"); |
---|
1152 | py64(igps_rcv_gsr_queries, "\t%ju group-source quer%s received\n"); |
---|
1153 | py64(igps_drop_gsr_queries, "\t%ju group-source quer%s dropped\n"); |
---|
1154 | p64(igps_rcv_reports, "\t%ju membership report%s received\n"); |
---|
1155 | p64(igps_rcv_badreports, |
---|
1156 | "\t%ju membership report%s received with invalid field(s)\n"); |
---|
1157 | p64(igps_rcv_ourreports, |
---|
1158 | "\t%ju membership report%s received for groups to which we belong\n"); |
---|
1159 | p64(igps_rcv_nora, "\t%ju V3 report%s received without Router Alert\n"); |
---|
1160 | p64(igps_snd_reports, "\t%ju membership report%s sent\n"); |
---|
1161 | #undef p64 |
---|
1162 | #undef py64 |
---|
1163 | } |
---|
1164 | |
---|
1165 | /* |
---|
1166 | * Dump PIM statistics structure. |
---|
1167 | */ |
---|
1168 | void |
---|
1169 | pim_stats(u_long off __unused, const char *name, int af1 __unused, |
---|
1170 | int proto __unused) |
---|
1171 | { |
---|
1172 | struct pimstat pimstat, zerostat; |
---|
1173 | size_t len = sizeof pimstat; |
---|
1174 | |
---|
1175 | if (live) { |
---|
1176 | if (zflag) |
---|
1177 | memset(&zerostat, 0, len); |
---|
1178 | if (sysctlbyname("net.inet.pim.stats", &pimstat, &len, |
---|
1179 | zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { |
---|
1180 | if (errno != ENOENT) |
---|
1181 | warn("sysctl: net.inet.pim.stats"); |
---|
1182 | return; |
---|
1183 | } |
---|
1184 | } else { |
---|
1185 | if (off == 0) |
---|
1186 | return; |
---|
1187 | kread(off, &pimstat, len); |
---|
1188 | } |
---|
1189 | |
---|
1190 | printf("%s:\n", name); |
---|
1191 | |
---|
1192 | #define p(f, m) if (pimstat.f || sflag <= 1) \ |
---|
1193 | printf(m, (uintmax_t)pimstat.f, plural(pimstat.f)) |
---|
1194 | #define py(f, m) if (pimstat.f || sflag <= 1) \ |
---|
1195 | printf(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y") |
---|
1196 | p(pims_rcv_total_msgs, "\t%ju message%s received\n"); |
---|
1197 | p(pims_rcv_total_bytes, "\t%ju byte%s received\n"); |
---|
1198 | p(pims_rcv_tooshort, "\t%ju message%s received with too few bytes\n"); |
---|
1199 | p(pims_rcv_badsum, "\t%ju message%s received with bad checksum\n"); |
---|
1200 | p(pims_rcv_badversion, "\t%ju message%s received with bad version\n"); |
---|
1201 | p(pims_rcv_registers_msgs, "\t%ju data register message%s received\n"); |
---|
1202 | p(pims_rcv_registers_bytes, "\t%ju data register byte%s received\n"); |
---|
1203 | p(pims_rcv_registers_wrongiif, |
---|
1204 | "\t%ju data register message%s received on wrong iif\n"); |
---|
1205 | p(pims_rcv_badregisters, "\t%ju bad register%s received\n"); |
---|
1206 | p(pims_snd_registers_msgs, "\t%ju data register message%s sent\n"); |
---|
1207 | p(pims_snd_registers_bytes, "\t%ju data register byte%s sent\n"); |
---|
1208 | #undef p |
---|
1209 | #undef py |
---|
1210 | } |
---|
1211 | |
---|
1212 | /* |
---|
1213 | * Pretty print an Internet address (net address + port). |
---|
1214 | */ |
---|
1215 | void |
---|
1216 | inetprint(struct in_addr *in, int port, const char *proto, int num_port) |
---|
1217 | { |
---|
1218 | struct servent *sp = 0; |
---|
1219 | char line[80], *cp; |
---|
1220 | int width; |
---|
1221 | |
---|
1222 | if (Wflag) |
---|
1223 | sprintf(line, "%s.", inetname(in)); |
---|
1224 | else |
---|
1225 | sprintf(line, "%.*s.", (Aflag && !num_port) ? 12 : 16, inetname(in)); |
---|
1226 | cp = index(line, '\0'); |
---|
1227 | if (!num_port && port) |
---|
1228 | sp = getservbyport((int)port, proto); |
---|
1229 | if (sp || port == 0) |
---|
1230 | sprintf(cp, "%.15s ", sp ? sp->s_name : "*"); |
---|
1231 | else |
---|
1232 | sprintf(cp, "%d ", ntohs((u_short)port)); |
---|
1233 | width = (Aflag && !Wflag) ? 18 : 22; |
---|
1234 | if (Wflag) |
---|
1235 | printf("%-*s ", width, line); |
---|
1236 | else |
---|
1237 | printf("%-*.*s ", width, width, line); |
---|
1238 | } |
---|
1239 | |
---|
1240 | /* |
---|
1241 | * Construct an Internet address representation. |
---|
1242 | * If numeric_addr has been supplied, give |
---|
1243 | * numeric value, otherwise try for symbolic name. |
---|
1244 | */ |
---|
1245 | char * |
---|
1246 | inetname(struct in_addr *inp) |
---|
1247 | { |
---|
1248 | char *cp; |
---|
1249 | static char line[MAXHOSTNAMELEN]; |
---|
1250 | struct hostent *hp; |
---|
1251 | struct netent *np; |
---|
1252 | |
---|
1253 | cp = 0; |
---|
1254 | if (!numeric_addr && inp->s_addr != INADDR_ANY) { |
---|
1255 | int net = inet_netof(*inp); |
---|
1256 | int lna = inet_lnaof(*inp); |
---|
1257 | |
---|
1258 | if (lna == INADDR_ANY) { |
---|
1259 | np = getnetbyaddr(net, AF_INET); |
---|
1260 | if (np) |
---|
1261 | cp = np->n_name; |
---|
1262 | } |
---|
1263 | if (cp == 0) { |
---|
1264 | hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); |
---|
1265 | if (hp) { |
---|
1266 | cp = hp->h_name; |
---|
1267 | trimdomain(cp, strlen(cp)); |
---|
1268 | } |
---|
1269 | } |
---|
1270 | } |
---|
1271 | if (inp->s_addr == INADDR_ANY) |
---|
1272 | strcpy(line, "*"); |
---|
1273 | else if (cp) { |
---|
1274 | strlcpy(line, cp, sizeof(line)); |
---|
1275 | } else { |
---|
1276 | inp->s_addr = ntohl(inp->s_addr); |
---|
1277 | #define C(x) ((u_int)((x) & 0xff)) |
---|
1278 | sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24), |
---|
1279 | C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr)); |
---|
1280 | } |
---|
1281 | return (line); |
---|
1282 | } |
---|