1 /* $NetBSD: trpt.c,v 1.25 2008/07/21 13:37:00 lukem Exp $ */
4 * Copyright (c) 1997, 2005, 2006 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1983, 1988, 1993
35 * The Regents of the University of California. All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 #include <sys/cdefs.h>
64 __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\
65 The Regents of the University of California. All rights reserved.");
70 static char sccsid
[] = "@(#)trpt.c 8.1 (Berkeley) 6/6/93";
72 __RCSID("$NetBSD: trpt.c,v 1.25 2008/07/21 13:37:00 lukem Exp $");
76 #define _CALLOUT_PRIVATE /* for defs in sys/callout.h */
78 #include <sys/param.h>
79 #include <sys/queue.h>
80 #include <sys/socket.h>
81 #include <sys/socketvar.h>
82 #include <sys/sysctl.h>
84 #include <sys/protosw.h>
87 #include <net/route.h>
90 #include <netinet/in.h>
91 #include <netinet/in_systm.h>
92 #include <netinet/ip.h>
93 #include <netinet/in_pcb.h>
94 #include <netinet/ip_var.h>
98 #include <netinet/in.h>
100 #include <netinet/ip6.h>
103 #include <netinet/tcp.h>
105 #include <netinet/tcp_fsm.h>
106 #include <netinet/tcp_seq.h>
108 #include <netinet/tcp_timer.h>
109 #include <netinet/tcp_var.h>
110 #include <netinet/tcpip.h>
112 #include <netinet/tcp_debug.h>
114 #include <arpa/inet.h>
126 struct nlist nl
[] = {
127 #define N_HARDCLOCK_TICKS 0
128 { "_hardclock_ticks", 0, 0, 0, 0 },
129 #define N_TCP_DEBUG 1
130 { "_tcp_debug", 0, 0, 0, 0 },
132 { "_tcp_debx", 0, 0, 0, 0 },
133 { NULL
, 0, 0, 0, 0 },
136 static caddr_t tcp_pcbs
[TCP_NDEBUG
];
138 static int aflag
, follow
, sflag
, tflag
;
140 /* see sys/netinet/tcp_debug.c */
141 struct tcp_debug tcp_debug
[TCP_NDEBUG
];
144 int main(int, char *[]);
145 void dotrace(caddr_t
);
146 void tcp_trace(short, short, struct tcpcb
*, struct tcpcb
*,
148 int numeric(const void *, const void *);
155 main(int argc
, char *argv
[])
157 int ch
, i
, jflag
, npcbs
;
158 char *kernel
, *core
, *cp
, errbuf
[_POSIX2_LINE_MAX
];
162 kernel
= core
= NULL
;
164 while ((ch
= getopt(argc
, argv
, "afjp:stN:M:")) != -1) {
177 if (npcbs
>= TCP_NDEBUG
)
178 errx(1, "too many pcbs specified");
181 l
= strtoul(optarg
, &cp
, 16);
182 tcp_pcbs
[npcbs
] = (caddr_t
)l
;
183 if (*optarg
== '\0' || *cp
!= '\0' || errno
||
184 (unsigned long)tcp_pcbs
[npcbs
] != l
)
185 errx(1, "invalid address: %s", optarg
);
211 use_sysctl
= (kernel
== NULL
&& core
== NULL
);
214 size_t lenx
= sizeof(tcp_debx
);
215 size_t lend
= sizeof(tcp_debug
);
217 if (sysctlbyname("net.inet.tcp.debx", &tcp_debx
, &lenx
,
219 err(1, "net.inet.tcp.debx");
220 if (sysctlbyname("net.inet.tcp.debug", &tcp_debug
, &lend
,
222 err(1, "net.inet.tcp.debug");
224 kd
= kvm_openfiles(kernel
, core
, NULL
, O_RDONLY
, errbuf
);
226 errx(1, "can't open kmem: %s", errbuf
);
228 if (kvm_nlist(kd
, nl
))
229 errx(2, "%s: no namelist", kernel
);
231 if (kvm_read(kd
, nl
[N_TCP_DEBX
].n_value
, (char *)&tcp_debx
,
232 sizeof(tcp_debx
)) != sizeof(tcp_debx
))
233 errx(3, "tcp_debx: %s", kvm_geterr(kd
));
235 if (kvm_read(kd
, nl
[N_TCP_DEBUG
].n_value
, (char *)tcp_debug
,
236 sizeof(tcp_debug
)) != sizeof(tcp_debug
))
237 errx(3, "tcp_debug: %s", kvm_geterr(kd
));
241 * If no control blocks have been specified, figure
242 * out how many distinct one we have and summarize
243 * them in tcp_pcbs for sorting the trace records
247 for (i
= 0; i
< TCP_NDEBUG
; i
++) {
248 struct tcp_debug
*td
= &tcp_debug
[i
];
253 for (j
= 0; j
< npcbs
; j
++)
254 if (tcp_pcbs
[j
] == td
->td_tcb
)
257 tcp_pcbs
[npcbs
++] = td
->td_tcb
;
262 qsort(tcp_pcbs
, npcbs
, sizeof(caddr_t
), numeric
);
265 printf("%lx", (long)tcp_pcbs
[i
]);
272 for (i
= 0; i
< npcbs
; i
++) {
273 printf("\n%lx:\n", (long)tcp_pcbs
[i
]);
274 dotrace(tcp_pcbs
[i
]);
281 dotrace(caddr_t tcpcb
)
283 struct tcp_debug
*td
;
284 int prev_debx
= tcp_debx
;
289 tcp_debx
= TCP_NDEBUG
- 1;
290 for (i
= prev_debx
% TCP_NDEBUG
; i
< TCP_NDEBUG
; i
++) {
292 if (tcpcb
&& td
->td_tcb
!= tcpcb
)
294 ntime
= ntohl(td
->td_time
);
295 switch (td
->td_family
) {
297 tcp_trace(td
->td_act
, td
->td_ostate
,
298 (struct tcpcb
*)td
->td_tcb
, &td
->td_cb
,
299 td
->td_family
, &td
->td_ti
, td
->td_req
);
303 tcp_trace(td
->td_act
, td
->td_ostate
,
304 (struct tcpcb
*)td
->td_tcb
, &td
->td_cb
,
305 td
->td_family
, &td
->td_ti6
, td
->td_req
);
309 tcp_trace(td
->td_act
, td
->td_ostate
,
310 (struct tcpcb
*)td
->td_tcb
, &td
->td_cb
,
311 td
->td_family
, NULL
, td
->td_req
);
317 for (i
= 0; i
<= tcp_debx
% TCP_NDEBUG
; i
++) {
319 if (tcpcb
&& td
->td_tcb
!= tcpcb
)
321 ntime
= ntohl(td
->td_time
);
322 switch (td
->td_family
) {
324 tcp_trace(td
->td_act
, td
->td_ostate
,
325 (struct tcpcb
*)td
->td_tcb
, &td
->td_cb
,
326 td
->td_family
, &td
->td_ti
, td
->td_req
);
330 tcp_trace(td
->td_act
, td
->td_ostate
,
331 (struct tcpcb
*)td
->td_tcb
, &td
->td_cb
,
332 td
->td_family
, &td
->td_ti6
, td
->td_req
);
336 tcp_trace(td
->td_act
, td
->td_ostate
,
337 (struct tcpcb
*)td
->td_tcb
, &td
->td_cb
,
338 td
->td_family
, NULL
, td
->td_req
);
344 prev_debx
= tcp_debx
+ 1;
345 if (prev_debx
>= TCP_NDEBUG
)
350 size_t len
= sizeof(tcp_debx
);
352 if (sysctlbyname("net.inet.tcp.debx",
353 &tcp_debx
, &len
, NULL
, 0) == -1)
354 err(1, "net.inet.tcp.debx");
356 if (kvm_read(kd
, nl
[N_TCP_DEBX
].n_value
,
357 (char *)&tcp_debx
, sizeof(tcp_debx
)) !=
359 errx(3, "tcp_debx: %s",
361 } while (tcp_debx
== prev_debx
);
364 size_t len
= sizeof(tcp_debug
);
366 if (sysctlbyname("net.inet.tcp.debug", &tcp_debug
,
367 &len
, NULL
, 0) == -1)
368 err(1, "net.inet.tcp.debug");
370 if (kvm_read(kd
, nl
[N_TCP_DEBUG
].n_value
,
372 sizeof(tcp_debug
)) != sizeof(tcp_debug
))
373 errx(3, "tcp_debug: %s", kvm_geterr(kd
));
384 tcp_trace(short act
, short ostate
, struct tcpcb
*atp
, struct tcpcb
*tp
,
385 int family
, void *packet
, int req
)
388 int flags
, len
, win
, timer
;
389 struct tcphdr
*th
= NULL
;
390 struct ip
*ip
= NULL
;
392 struct ip6_hdr
*ip6
= NULL
;
395 char hbuf
[MAXHOSTNAMELEN
];
397 len
= 0; /* XXXGCC -Wuninitialized */
402 ip
= (struct ip
*)packet
;
403 th
= (struct tcphdr
*)(ip
+ 1);
409 ip6
= (struct ip6_hdr
*)packet
;
410 th
= (struct tcphdr
*)(ip6
+ 1);
418 printf("%03d %s:%s ", (ntime
/10) % 1000, tcpstates
[ostate
],
437 family
== AF_INET
? (void *)&ip
->ip_src
438 : (void *)&ip6
->ip6_src
,
441 printf("(src=%s,%u, ",
442 hbuf
, ntohs(th
->th_sport
));
447 family
== AF_INET
? (void *)&ip
->ip_dst
448 : (void *)&ip6
->ip6_dst
,
452 hbuf
, ntohs(th
->th_dport
));
463 if (act
== TA_OUTPUT
) {
469 if (act
== TA_OUTPUT
)
470 len
-= sizeof(struct tcphdr
);
472 printf("[%x..%x)", seq
, seq
+ len
);
477 printf("(win=%x)", win
);
478 flags
= th
->th_flags
;
480 const char *cp
= "<";
481 #define pf(flag, string) { \
482 if (th->th_flags&flag) { \
483 (void)printf("%s%s", cp, string); \
501 printf("%s", prurequests
[req
]);
502 if (req
== PRU_SLOWTIMO
|| req
== PRU_FASTTIMO
)
503 printf("<%s>", tcptimers
[timer
]);
508 printf(" -> %s", tcpstates
[tp
->t_state
]);
509 /* print out internal state of tp !?! */
512 printf("\trcv_nxt %x rcv_wnd %lx snd_una %x snd_nxt %x snd_max %x\n",
513 tp
->rcv_nxt
, tp
->rcv_wnd
, tp
->snd_una
, tp
->snd_nxt
,
515 printf("\tsnd_wl1 %x snd_wl2 %x snd_wnd %lx\n", tp
->snd_wl1
,
516 tp
->snd_wl2
, tp
->snd_wnd
);
518 /* print out timers? */
520 const char *cp
= "\t";
525 size_t hlen
= sizeof(hardticks
);
527 if (sysctlbyname("kern.hardclock_ticks", &hardticks
,
528 &hlen
, NULL
, 0) == -1)
529 err(1, "kern.hardclock_ticks");
531 if (kvm_read(kd
, nl
[N_HARDCLOCK_TICKS
].n_value
,
533 sizeof(hardticks
)) != sizeof(hardticks
))
534 errx(3, "hardclock_ticks: %s", kvm_geterr(kd
));
536 for (i
= 0; i
< TCPT_NTIMERS
; i
++) {
537 ci
= (callout_impl_t
*)&tp
->t_timer
[i
];
538 if ((ci
->c_flags
& CALLOUT_PENDING
) == 0)
540 printf("%s%s=%d", cp
, tcptimers
[i
],
541 ci
->c_time
- hardticks
);
543 printf(" (t_rxtshft=%d)",
554 numeric(const void *v1
, const void *v2
)
556 const caddr_t
*c1
= v1
;
557 const caddr_t
*c2
= v2
;
574 (void) fprintf(stderr
, "usage: %s [-afjst] [-p hex-address]"
575 " [-N system] [-M core]\n", getprogname());