Home | History | Annotate | Line # | Download | only in trpt
trpt.c revision 1.23.10.1
      1  1.23.10.1      yamt /*	$NetBSD: trpt.c,v 1.23.10.1 2008/05/18 12:36:23 yamt Exp $	*/
      2        1.5   thorpej 
      3        1.5   thorpej /*-
      4       1.22    rpaulo  * Copyright (c) 1997, 2005, 2006 The NetBSD Foundation, Inc.
      5        1.5   thorpej  * All rights reserved.
      6        1.5   thorpej  *
      7        1.5   thorpej  * This code is derived from software contributed to The NetBSD Foundation
      8        1.5   thorpej  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9        1.5   thorpej  * NASA Ames Research Center.
     10        1.5   thorpej  *
     11        1.5   thorpej  * Redistribution and use in source and binary forms, with or without
     12        1.5   thorpej  * modification, are permitted provided that the following conditions
     13        1.5   thorpej  * are met:
     14        1.5   thorpej  * 1. Redistributions of source code must retain the above copyright
     15        1.5   thorpej  *    notice, this list of conditions and the following disclaimer.
     16        1.5   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     17        1.5   thorpej  *    notice, this list of conditions and the following disclaimer in the
     18        1.5   thorpej  *    documentation and/or other materials provided with the distribution.
     19        1.5   thorpej  *
     20        1.5   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21        1.5   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22        1.5   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23        1.5   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24        1.5   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25        1.5   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26        1.5   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27        1.5   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28        1.5   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29        1.5   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30        1.5   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     31        1.5   thorpej  */
     32        1.4     mikel 
     33        1.1       cgd /*
     34        1.4     mikel  * Copyright (c) 1983, 1988, 1993
     35        1.4     mikel  *	The Regents of the University of California.  All rights reserved.
     36        1.1       cgd  *
     37        1.1       cgd  * Redistribution and use in source and binary forms, with or without
     38        1.1       cgd  * modification, are permitted provided that the following conditions
     39        1.1       cgd  * are met:
     40        1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     41        1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     42        1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     43        1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     44        1.1       cgd  *    documentation and/or other materials provided with the distribution.
     45       1.17       agc  * 3. Neither the name of the University nor the names of its contributors
     46        1.1       cgd  *    may be used to endorse or promote products derived from this software
     47        1.1       cgd  *    without specific prior written permission.
     48        1.1       cgd  *
     49        1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     50        1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     51        1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     52        1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     53        1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     54        1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     55        1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     56        1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     57        1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     58        1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     59        1.1       cgd  * SUCH DAMAGE.
     60        1.1       cgd  */
     61        1.1       cgd 
     62        1.5   thorpej #include <sys/cdefs.h>
     63        1.1       cgd #ifndef lint
     64        1.5   thorpej __COPYRIGHT(
     65        1.4     mikel "@(#) Copyright (c) 1983, 1988, 1993\n\
     66        1.5   thorpej 	The Regents of the University of California.  All rights reserved.\n");
     67        1.1       cgd #endif /* not lint */
     68        1.1       cgd 
     69        1.1       cgd #ifndef lint
     70        1.4     mikel #if 0
     71        1.4     mikel static char sccsid[] = "@(#)trpt.c	8.1 (Berkeley) 6/6/93";
     72        1.4     mikel #else
     73  1.23.10.1      yamt __RCSID("$NetBSD: trpt.c,v 1.23.10.1 2008/05/18 12:36:23 yamt Exp $");
     74        1.4     mikel #endif
     75        1.1       cgd #endif /* not lint */
     76        1.1       cgd 
     77       1.23  jmcneill #define _CALLOUT_PRIVATE	/* for defs in sys/callout.h */
     78       1.23  jmcneill 
     79        1.1       cgd #include <sys/param.h>
     80        1.3       cgd #include <sys/queue.h>
     81        1.1       cgd #include <sys/socket.h>
     82        1.1       cgd #include <sys/socketvar.h>
     83       1.21    rpaulo #include <sys/sysctl.h>
     84        1.1       cgd #define PRUREQUESTS
     85        1.1       cgd #include <sys/protosw.h>
     86        1.1       cgd #include <sys/file.h>
     87        1.1       cgd 
     88        1.1       cgd #include <net/route.h>
     89        1.1       cgd #include <net/if.h>
     90        1.1       cgd 
     91        1.1       cgd #include <netinet/in.h>
     92        1.1       cgd #include <netinet/in_systm.h>
     93        1.1       cgd #include <netinet/ip.h>
     94        1.1       cgd #include <netinet/in_pcb.h>
     95        1.1       cgd #include <netinet/ip_var.h>
     96        1.9    itojun 
     97        1.9    itojun #ifdef INET6
     98        1.9    itojun #ifndef INET
     99        1.9    itojun #include <netinet/in.h>
    100        1.9    itojun #endif
    101        1.9    itojun #include <netinet/ip6.h>
    102        1.9    itojun #endif
    103        1.9    itojun 
    104        1.1       cgd #include <netinet/tcp.h>
    105        1.1       cgd #define TCPSTATES
    106        1.1       cgd #include <netinet/tcp_fsm.h>
    107        1.1       cgd #include <netinet/tcp_seq.h>
    108        1.1       cgd #define	TCPTIMERS
    109        1.1       cgd #include <netinet/tcp_timer.h>
    110        1.1       cgd #include <netinet/tcp_var.h>
    111        1.1       cgd #include <netinet/tcpip.h>
    112        1.1       cgd #define	TANAMES
    113        1.1       cgd #include <netinet/tcp_debug.h>
    114        1.1       cgd 
    115        1.1       cgd #include <arpa/inet.h>
    116        1.1       cgd 
    117        1.5   thorpej #include <err.h>
    118        1.1       cgd #include <stdio.h>
    119        1.1       cgd #include <errno.h>
    120        1.5   thorpej #include <kvm.h>
    121        1.1       cgd #include <nlist.h>
    122        1.1       cgd #include <paths.h>
    123        1.5   thorpej #include <limits.h>
    124        1.5   thorpej #include <stdlib.h>
    125        1.5   thorpej #include <unistd.h>
    126        1.1       cgd 
    127        1.1       cgd struct nlist nl[] = {
    128       1.16   thorpej #define	N_HARDCLOCK_TICKS	0
    129       1.16   thorpej 	{ "_hardclock_ticks" },
    130       1.16   thorpej #define	N_TCP_DEBUG		1
    131        1.1       cgd 	{ "_tcp_debug" },
    132       1.16   thorpej #define	N_TCP_DEBX		2
    133        1.1       cgd 	{ "_tcp_debx" },
    134        1.5   thorpej 	{ NULL },
    135        1.1       cgd };
    136        1.1       cgd 
    137        1.1       cgd static caddr_t tcp_pcbs[TCP_NDEBUG];
    138        1.1       cgd static n_time ntime;
    139        1.5   thorpej static int aflag, follow, sflag, tflag;
    140       1.11    itojun 
    141       1.11    itojun /* see sys/netinet/tcp_debug.c */
    142       1.11    itojun struct  tcp_debug tcp_debug[TCP_NDEBUG];
    143       1.11    itojun int tcp_debx;
    144        1.5   thorpej 
    145       1.19     perry int	main(int, char *[]);
    146       1.19     perry void	dotrace(caddr_t);
    147       1.19     perry void	tcp_trace(short, short, struct tcpcb *, struct tcpcb *,
    148       1.19     perry 	    int, void *, int);
    149       1.19     perry int	numeric(const void *, const void *);
    150       1.19     perry void	usage(void);
    151        1.1       cgd 
    152        1.5   thorpej kvm_t	*kd;
    153       1.21    rpaulo int     use_sysctl;
    154        1.5   thorpej 
    155        1.5   thorpej int
    156       1.19     perry main(int argc, char *argv[])
    157        1.1       cgd {
    158        1.5   thorpej 	int ch, i, jflag, npcbs;
    159        1.5   thorpej 	char *system, *core, *cp, errbuf[_POSIX2_LINE_MAX];
    160       1.14    itojun 	unsigned long l;
    161        1.5   thorpej 
    162       1.21    rpaulo 	jflag = npcbs = 0;
    163        1.5   thorpej 	system = core = NULL;
    164        1.1       cgd 
    165       1.13      soda 	while ((ch = getopt(argc, argv, "afjp:stN:M:")) != -1) {
    166        1.1       cgd 		switch (ch) {
    167        1.1       cgd 		case 'a':
    168        1.1       cgd 			++aflag;
    169        1.1       cgd 			break;
    170        1.1       cgd 		case 'f':
    171        1.1       cgd 			++follow;
    172        1.1       cgd 			setlinebuf(stdout);
    173        1.1       cgd 			break;
    174        1.1       cgd 		case 'j':
    175        1.1       cgd 			++jflag;
    176        1.1       cgd 			break;
    177        1.1       cgd 		case 'p':
    178        1.5   thorpej 			if (npcbs >= TCP_NDEBUG)
    179        1.5   thorpej 				errx(1, "too many pcbs specified");
    180        1.5   thorpej 			errno = 0;
    181       1.14    itojun 			cp = NULL;
    182       1.14    itojun 			l = strtoul(optarg, &cp, 16);
    183       1.14    itojun 			tcp_pcbs[npcbs] = (caddr_t)l;
    184       1.14    itojun 			if (*optarg == '\0' || *cp != '\0' || errno ||
    185       1.14    itojun 			    (unsigned long)tcp_pcbs[npcbs] != l)
    186        1.5   thorpej 				errx(1, "invalid address: %s", optarg);
    187       1.14    itojun 			npcbs++;
    188        1.1       cgd 			break;
    189        1.1       cgd 		case 's':
    190        1.1       cgd 			++sflag;
    191        1.1       cgd 			break;
    192        1.1       cgd 		case 't':
    193        1.1       cgd 			++tflag;
    194        1.1       cgd 			break;
    195        1.5   thorpej 		case 'N':
    196        1.5   thorpej 			system = optarg;
    197        1.5   thorpej 			break;
    198        1.5   thorpej 		case 'M':
    199        1.5   thorpej 			core = optarg;
    200        1.5   thorpej 			break;
    201        1.1       cgd 		default:
    202        1.5   thorpej 			usage();
    203        1.5   thorpej 			/* NOTREACHED */
    204        1.1       cgd 		}
    205        1.5   thorpej 	}
    206        1.1       cgd 	argc -= optind;
    207        1.1       cgd 	argv += optind;
    208        1.1       cgd 
    209        1.5   thorpej 	if (argc)
    210        1.5   thorpej 		usage();
    211        1.5   thorpej 
    212       1.21    rpaulo 	use_sysctl = (system == NULL && core == NULL);
    213        1.1       cgd 
    214       1.21    rpaulo 	if (use_sysctl) {
    215       1.21    rpaulo 		size_t lenx = sizeof(tcp_debx);
    216       1.21    rpaulo 		size_t lend = sizeof(tcp_debug);
    217       1.21    rpaulo 
    218       1.21    rpaulo 		if (sysctlbyname("net.inet.tcp.debx", &tcp_debx, &lenx,
    219       1.21    rpaulo 		    NULL, 0) == -1)
    220       1.21    rpaulo 			err(1, "net.inet.tcp.debx");
    221       1.21    rpaulo 		if (sysctlbyname("net.inet.tcp.debug", &tcp_debug, &lend,
    222       1.21    rpaulo 		    NULL, 0) == -1)
    223       1.21    rpaulo 			err(1, "net.inet.tcp.debug");
    224       1.21    rpaulo 	} else {
    225       1.21    rpaulo 		kd = kvm_openfiles(system, core, NULL, O_RDONLY, errbuf);
    226       1.21    rpaulo 		if (kd == NULL)
    227       1.21    rpaulo 			errx(1, "can't open kmem: %s", errbuf);
    228       1.21    rpaulo 
    229       1.21    rpaulo 		if (kvm_nlist(kd, nl))
    230       1.21    rpaulo 			errx(2, "%s: no namelist", system);
    231       1.21    rpaulo 
    232       1.21    rpaulo 		if (kvm_read(kd, nl[N_TCP_DEBX].n_value, (char *)&tcp_debx,
    233       1.21    rpaulo 		    sizeof(tcp_debx)) != sizeof(tcp_debx))
    234       1.21    rpaulo 			errx(3, "tcp_debx: %s", kvm_geterr(kd));
    235       1.21    rpaulo 
    236       1.21    rpaulo 		if (kvm_read(kd, nl[N_TCP_DEBUG].n_value, (char *)tcp_debug,
    237       1.21    rpaulo 		    sizeof(tcp_debug)) != sizeof(tcp_debug))
    238       1.21    rpaulo 			errx(3, "tcp_debug: %s", kvm_geterr(kd));
    239       1.21    rpaulo 	}
    240        1.1       cgd 
    241        1.1       cgd 	/*
    242        1.1       cgd 	 * If no control blocks have been specified, figure
    243        1.1       cgd 	 * out how many distinct one we have and summarize
    244        1.1       cgd 	 * them in tcp_pcbs for sorting the trace records
    245        1.1       cgd 	 * below.
    246        1.1       cgd 	 */
    247        1.5   thorpej 	if (npcbs == 0) {
    248        1.1       cgd 		for (i = 0; i < TCP_NDEBUG; i++) {
    249        1.5   thorpej 			struct tcp_debug *td = &tcp_debug[i];
    250        1.5   thorpej 			int j;
    251        1.1       cgd 
    252        1.1       cgd 			if (td->td_tcb == 0)
    253        1.1       cgd 				continue;
    254        1.1       cgd 			for (j = 0; j < npcbs; j++)
    255        1.1       cgd 				if (tcp_pcbs[j] == td->td_tcb)
    256        1.1       cgd 					break;
    257        1.1       cgd 			if (j >= npcbs)
    258        1.1       cgd 				tcp_pcbs[npcbs++] = td->td_tcb;
    259        1.1       cgd 		}
    260        1.5   thorpej 		if (npcbs == 0)
    261        1.1       cgd 			exit(0);
    262        1.1       cgd 	}
    263        1.1       cgd 	qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric);
    264        1.1       cgd 	if (jflag) {
    265        1.1       cgd 		for (i = 0;;) {
    266        1.3       cgd 			printf("%lx", (long)tcp_pcbs[i]);
    267        1.1       cgd 			if (++i == npcbs)
    268        1.1       cgd 				break;
    269        1.1       cgd 			fputs(", ", stdout);
    270        1.1       cgd 		}
    271        1.1       cgd 		putchar('\n');
    272        1.5   thorpej 	} else {
    273        1.5   thorpej 		for (i = 0; i < npcbs; i++) {
    274        1.5   thorpej 			printf("\n%lx:\n", (long)tcp_pcbs[i]);
    275        1.5   thorpej 			dotrace(tcp_pcbs[i]);
    276        1.5   thorpej 		}
    277        1.1       cgd 	}
    278        1.1       cgd 	exit(0);
    279        1.1       cgd }
    280        1.1       cgd 
    281        1.5   thorpej void
    282       1.19     perry dotrace(caddr_t tcpcb)
    283        1.1       cgd {
    284        1.5   thorpej 	struct tcp_debug *td;
    285        1.1       cgd 	int prev_debx = tcp_debx;
    286        1.5   thorpej 	int i;
    287        1.1       cgd 
    288        1.5   thorpej  again:
    289        1.5   thorpej 	if (--tcp_debx < 0)
    290        1.1       cgd 		tcp_debx = TCP_NDEBUG - 1;
    291        1.1       cgd 	for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) {
    292        1.1       cgd 		td = &tcp_debug[i];
    293        1.1       cgd 		if (tcpcb && td->td_tcb != tcpcb)
    294        1.1       cgd 			continue;
    295        1.1       cgd 		ntime = ntohl(td->td_time);
    296        1.9    itojun 		switch (td->td_family) {
    297        1.9    itojun 		case AF_INET:
    298        1.9    itojun 			tcp_trace(td->td_act, td->td_ostate,
    299        1.9    itojun 			    (struct tcpcb *)td->td_tcb, &td->td_cb,
    300        1.9    itojun 			    td->td_family, &td->td_ti, td->td_req);
    301        1.9    itojun 			break;
    302        1.9    itojun #ifdef INET6
    303        1.9    itojun 		case AF_INET6:
    304        1.9    itojun 			tcp_trace(td->td_act, td->td_ostate,
    305        1.9    itojun 			    (struct tcpcb *)td->td_tcb, &td->td_cb,
    306        1.9    itojun 			    td->td_family, &td->td_ti6, td->td_req);
    307        1.9    itojun 			break;
    308        1.9    itojun #endif
    309        1.9    itojun 		default:
    310        1.9    itojun 			tcp_trace(td->td_act, td->td_ostate,
    311        1.9    itojun 			    (struct tcpcb *)td->td_tcb, &td->td_cb,
    312        1.9    itojun 			    td->td_family, NULL, td->td_req);
    313        1.9    itojun 			break;
    314        1.9    itojun 		}
    315        1.1       cgd 		if (i == tcp_debx)
    316        1.1       cgd 			goto done;
    317        1.1       cgd 	}
    318        1.1       cgd 	for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) {
    319        1.1       cgd 		td = &tcp_debug[i];
    320        1.1       cgd 		if (tcpcb && td->td_tcb != tcpcb)
    321        1.1       cgd 			continue;
    322        1.1       cgd 		ntime = ntohl(td->td_time);
    323        1.9    itojun 		switch (td->td_family) {
    324        1.9    itojun 		case AF_INET:
    325        1.9    itojun 			tcp_trace(td->td_act, td->td_ostate,
    326        1.9    itojun 			    (struct tcpcb *)td->td_tcb, &td->td_cb,
    327        1.9    itojun 			    td->td_family, &td->td_ti, td->td_req);
    328        1.9    itojun 			break;
    329        1.9    itojun #ifdef INET6
    330        1.9    itojun 		case AF_INET6:
    331        1.9    itojun 			tcp_trace(td->td_act, td->td_ostate,
    332        1.9    itojun 			    (struct tcpcb *)td->td_tcb, &td->td_cb,
    333        1.9    itojun 			    td->td_family, &td->td_ti6, td->td_req);
    334        1.9    itojun 			break;
    335        1.9    itojun #endif
    336        1.9    itojun 		default:
    337        1.9    itojun 			tcp_trace(td->td_act, td->td_ostate,
    338        1.9    itojun 			    (struct tcpcb *)td->td_tcb, &td->td_cb,
    339        1.9    itojun 			    td->td_family, NULL, td->td_req);
    340        1.9    itojun 			break;
    341        1.9    itojun 		}
    342        1.1       cgd 	}
    343        1.5   thorpej  done:
    344        1.5   thorpej 	if (follow) {
    345        1.1       cgd 		prev_debx = tcp_debx + 1;
    346        1.1       cgd 		if (prev_debx >= TCP_NDEBUG)
    347        1.1       cgd 			prev_debx = 0;
    348        1.1       cgd 		do {
    349        1.1       cgd 			sleep(1);
    350       1.21    rpaulo 			if (use_sysctl) {
    351       1.21    rpaulo 				size_t len = sizeof(tcp_debx);
    352       1.21    rpaulo 
    353       1.21    rpaulo 				if (sysctlbyname("net.inet.tcp.debx",
    354       1.21    rpaulo 				    &tcp_debx, &len, NULL, 0) == -1)
    355       1.21    rpaulo 					err(1, "net.inet.tcp.debx");
    356       1.21    rpaulo 			} else
    357       1.21    rpaulo 				if (kvm_read(kd, nl[N_TCP_DEBX].n_value,
    358       1.21    rpaulo 				    (char *)&tcp_debx, sizeof(tcp_debx)) !=
    359       1.21    rpaulo 				    sizeof(tcp_debx))
    360       1.21    rpaulo 					errx(3, "tcp_debx: %s",
    361       1.21    rpaulo 					    kvm_geterr(kd));
    362        1.1       cgd 		} while (tcp_debx == prev_debx);
    363        1.5   thorpej 
    364       1.21    rpaulo 		if (use_sysctl) {
    365       1.21    rpaulo 			size_t len = sizeof(tcp_debug);
    366       1.21    rpaulo 
    367       1.21    rpaulo 			if (sysctlbyname("net.inet.tcp.debug", &tcp_debug,
    368       1.21    rpaulo 			    &len, NULL, 0) == -1)
    369       1.21    rpaulo 				err(1, "net.inet.tcp.debug");
    370       1.21    rpaulo 		} else
    371       1.21    rpaulo 			if (kvm_read(kd, nl[N_TCP_DEBUG].n_value,
    372       1.21    rpaulo 			    (char *)tcp_debug,
    373       1.21    rpaulo 			    sizeof(tcp_debug)) != sizeof(tcp_debug))
    374       1.21    rpaulo 				errx(3, "tcp_debug: %s", kvm_geterr(kd));
    375        1.5   thorpej 
    376        1.1       cgd 		goto again;
    377        1.1       cgd 	}
    378        1.1       cgd }
    379        1.1       cgd 
    380        1.1       cgd /*
    381        1.1       cgd  * Tcp debug routines
    382        1.1       cgd  */
    383        1.1       cgd /*ARGSUSED*/
    384        1.5   thorpej void
    385       1.19     perry tcp_trace(short act, short ostate, struct tcpcb *atp, struct tcpcb *tp,
    386       1.19     perry     int family, void *packet, int req)
    387        1.1       cgd {
    388        1.1       cgd 	tcp_seq seq, ack;
    389        1.1       cgd 	int flags, len, win, timer;
    390        1.9    itojun 	struct tcphdr *th = NULL;
    391        1.9    itojun 	struct ip *ip = NULL;
    392        1.9    itojun #ifdef INET6
    393        1.9    itojun 	struct ip6_hdr *ip6 = NULL;
    394        1.9    itojun #endif
    395       1.23  jmcneill 	callout_impl_t *ci;
    396        1.9    itojun 	char hbuf[MAXHOSTNAMELEN];
    397        1.9    itojun 
    398       1.20     lukem 	len = 0;	/* XXXGCC -Wuninitialized */
    399       1.20     lukem 
    400        1.9    itojun 	switch (family) {
    401        1.9    itojun 	case AF_INET:
    402        1.9    itojun 		if (packet) {
    403        1.9    itojun 			ip = (struct ip *)packet;
    404        1.9    itojun 			th = (struct tcphdr *)(ip + 1);
    405        1.9    itojun 		}
    406        1.9    itojun 		break;
    407        1.9    itojun #ifdef INET6
    408        1.9    itojun 	case AF_INET6:
    409        1.9    itojun 		if (packet) {
    410        1.9    itojun 			ip6 = (struct ip6_hdr *)packet;
    411        1.9    itojun 			th = (struct tcphdr *)(ip6 + 1);
    412        1.9    itojun 		}
    413        1.9    itojun 		break;
    414        1.9    itojun #endif
    415        1.9    itojun 	default:
    416        1.9    itojun 		return;
    417        1.9    itojun 	}
    418        1.1       cgd 
    419        1.5   thorpej 	printf("%03d %s:%s ", (ntime/10) % 1000, tcpstates[ostate],
    420        1.1       cgd 	    tanames[act]);
    421        1.9    itojun 
    422        1.9    itojun #ifndef INET6
    423        1.9    itojun 	if (!ip)
    424        1.9    itojun #else
    425        1.9    itojun 	if (!(ip || ip6))
    426        1.9    itojun #endif
    427        1.9    itojun 		goto skipact;
    428        1.9    itojun 
    429        1.1       cgd 	switch (act) {
    430        1.1       cgd 	case TA_INPUT:
    431        1.1       cgd 	case TA_OUTPUT:
    432        1.1       cgd 	case TA_DROP:
    433        1.1       cgd 		if (aflag) {
    434        1.9    itojun 			inet_ntop(family,
    435        1.9    itojun #ifndef INET6
    436        1.9    itojun 				(void *)&ip->ip_src,
    437        1.9    itojun #else
    438        1.9    itojun 				family == AF_INET ? (void *)&ip->ip_src
    439        1.9    itojun 						  : (void *)&ip6->ip6_src,
    440        1.9    itojun #endif
    441        1.9    itojun 				hbuf, sizeof(hbuf));
    442        1.1       cgd 			printf("(src=%s,%u, ",
    443        1.9    itojun 			    hbuf, ntohs(th->th_sport));
    444        1.9    itojun 			inet_ntop(family,
    445        1.9    itojun #ifndef INET6
    446        1.9    itojun 				(void *)&ip->ip_dst,
    447        1.9    itojun #else
    448        1.9    itojun 				family == AF_INET ? (void *)&ip->ip_dst
    449        1.9    itojun 						  : (void *)&ip6->ip6_dst,
    450        1.9    itojun #endif
    451        1.9    itojun 				hbuf, sizeof(hbuf));
    452        1.1       cgd 			printf("dst=%s,%u)",
    453        1.9    itojun 			    hbuf, ntohs(th->th_dport));
    454        1.1       cgd 		}
    455        1.9    itojun 		seq = th->th_seq;
    456        1.9    itojun 		ack = th->th_ack;
    457        1.9    itojun 		if (ip)
    458        1.9    itojun 			len = ip->ip_len;
    459        1.9    itojun #ifdef INET6
    460        1.9    itojun 		else if (ip6)
    461        1.9    itojun 			len = ip6->ip6_plen;
    462        1.9    itojun #endif
    463        1.9    itojun 		win = th->th_win;
    464        1.1       cgd 		if (act == TA_OUTPUT) {
    465        1.5   thorpej 			NTOHL(seq);
    466        1.5   thorpej 			NTOHL(ack);
    467        1.5   thorpej 			NTOHS(len);
    468        1.5   thorpej 			NTOHS(win);
    469        1.1       cgd 		}
    470        1.1       cgd 		if (act == TA_OUTPUT)
    471        1.1       cgd 			len -= sizeof(struct tcphdr);
    472        1.1       cgd 		if (len)
    473        1.5   thorpej 			printf("[%x..%x)", seq, seq + len);
    474        1.1       cgd 		else
    475        1.5   thorpej 			printf("%x", seq);
    476        1.5   thorpej 		printf("@%x", ack);
    477        1.1       cgd 		if (win)
    478        1.1       cgd 			printf("(win=%x)", win);
    479        1.9    itojun 		flags = th->th_flags;
    480        1.1       cgd 		if (flags) {
    481       1.19     perry 			char *cp = "<";
    482        1.1       cgd #define	pf(flag, string) { \
    483        1.9    itojun 	if (th->th_flags&flag) { \
    484        1.1       cgd 		(void)printf("%s%s", cp, string); \
    485        1.1       cgd 		cp = ","; \
    486        1.1       cgd 	} \
    487        1.1       cgd }
    488        1.1       cgd 			pf(TH_SYN, "SYN");
    489        1.1       cgd 			pf(TH_ACK, "ACK");
    490        1.1       cgd 			pf(TH_FIN, "FIN");
    491        1.1       cgd 			pf(TH_RST, "RST");
    492        1.1       cgd 			pf(TH_PUSH, "PUSH");
    493        1.1       cgd 			pf(TH_URG, "URG");
    494       1.22    rpaulo 			pf(TH_CWR, "CWR");
    495       1.22    rpaulo 			pf(TH_ECE, "ECE");
    496        1.1       cgd 			printf(">");
    497        1.1       cgd 		}
    498        1.1       cgd 		break;
    499        1.1       cgd 	case TA_USER:
    500        1.1       cgd 		timer = req >> 8;
    501        1.1       cgd 		req &= 0xff;
    502        1.1       cgd 		printf("%s", prurequests[req]);
    503        1.1       cgd 		if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO)
    504        1.1       cgd 			printf("<%s>", tcptimers[timer]);
    505        1.1       cgd 		break;
    506        1.1       cgd 	}
    507        1.9    itojun 
    508        1.9    itojun skipact:
    509        1.1       cgd 	printf(" -> %s", tcpstates[tp->t_state]);
    510        1.1       cgd 	/* print out internal state of tp !?! */
    511        1.1       cgd 	printf("\n");
    512        1.1       cgd 	if (sflag) {
    513        1.5   thorpej 		printf("\trcv_nxt %x rcv_wnd %lx snd_una %x snd_nxt %x snd_max %x\n",
    514        1.1       cgd 		    tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt,
    515        1.1       cgd 		    tp->snd_max);
    516        1.5   thorpej 		printf("\tsnd_wl1 %x snd_wl2 %x snd_wnd %lx\n", tp->snd_wl1,
    517        1.1       cgd 		    tp->snd_wl2, tp->snd_wnd);
    518        1.1       cgd 	}
    519        1.1       cgd 	/* print out timers? */
    520        1.1       cgd 	if (tflag) {
    521       1.19     perry 		char *cp = "\t";
    522       1.19     perry 		int i;
    523       1.16   thorpej 		int hardticks;
    524       1.16   thorpej 
    525       1.21    rpaulo 		if (use_sysctl) {
    526       1.21    rpaulo 			size_t len = sizeof(hardticks);
    527        1.1       cgd 
    528       1.21    rpaulo 			if (sysctlbyname("kern.hardclock_ticks", &hardticks,
    529       1.21    rpaulo 			    &len, NULL, 0) == -1)
    530       1.21    rpaulo 				err(1, "kern.hardclock_ticks");
    531       1.21    rpaulo 		} else {
    532       1.21    rpaulo 			if (kvm_read(kd, nl[N_HARDCLOCK_TICKS].n_value,
    533       1.21    rpaulo 			    (char *)&hardticks,
    534       1.21    rpaulo 			    sizeof(hardticks)) != sizeof(hardticks))
    535       1.21    rpaulo 				errx(3, "hardclock_ticks: %s", kvm_geterr(kd));
    536       1.21    rpaulo 
    537       1.21    rpaulo 			for (i = 0; i < TCPT_NTIMERS; i++) {
    538       1.23  jmcneill 				ci = (callout_impl_t *)&tp->t_timer[i];
    539       1.23  jmcneill 				if ((ci->c_flags & CALLOUT_PENDING) == 0)
    540       1.21    rpaulo 					continue;
    541       1.21    rpaulo 				printf("%s%s=%d", cp, tcptimers[i],
    542       1.23  jmcneill 				    ci->c_time - hardticks);
    543       1.21    rpaulo 				if (i == TCPT_REXMT)
    544       1.21    rpaulo 					printf(" (t_rxtshft=%d)",
    545       1.21    rpaulo 					    tp->t_rxtshift);
    546       1.21    rpaulo 				cp = ", ";
    547       1.21    rpaulo 			}
    548       1.21    rpaulo 			if (*cp != '\t')
    549       1.21    rpaulo 				putchar('\n');
    550        1.1       cgd 		}
    551        1.1       cgd 	}
    552        1.1       cgd }
    553        1.1       cgd 
    554        1.5   thorpej int
    555       1.19     perry numeric(const void *v1, const void *v2)
    556        1.1       cgd {
    557        1.6   thorpej 	const caddr_t *c1 = v1;
    558        1.6   thorpej 	const caddr_t *c2 = v2;
    559        1.7   thorpej 	int rv;
    560        1.5   thorpej 
    561        1.7   thorpej 	if (*c1 < *c2)
    562        1.7   thorpej 		rv = -1;
    563        1.7   thorpej 	else if (*c1 > *c2)
    564        1.7   thorpej 		rv = 1;
    565        1.7   thorpej 	else
    566        1.7   thorpej 		rv = 0;
    567        1.7   thorpej 
    568        1.7   thorpej 	return (rv);
    569        1.1       cgd }
    570        1.1       cgd 
    571        1.5   thorpej void
    572       1.19     perry usage(void)
    573        1.1       cgd {
    574        1.1       cgd 
    575        1.5   thorpej 	(void) fprintf(stderr, "usage: %s [-afjst] [-p hex-address]"
    576       1.10       cgd 	    " [-N system] [-M core]\n", getprogname());
    577        1.5   thorpej 	exit(1);
    578        1.1       cgd }
    579