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