1 /* 2 * Copyright (c) 1983, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)trpt.c 5.13 (Berkeley) 06/01/90"; 16 #endif /* not lint */ 17 18 #include <machine/pte.h> 19 20 #include <sys/param.h> 21 #include <sys/vmmac.h> 22 #include <sys/socket.h> 23 #include <sys/socketvar.h> 24 #define PRUREQUESTS 25 #include <sys/protosw.h> 26 #include <sys/file.h> 27 28 #include <net/route.h> 29 #include <net/if.h> 30 31 #include <netinet/in.h> 32 #include <netinet/in_systm.h> 33 #include <netinet/ip.h> 34 #include <netinet/in_pcb.h> 35 #include <netinet/ip_var.h> 36 #include <netinet/tcp.h> 37 #define TCPSTATES 38 #include <netinet/tcp_fsm.h> 39 #include <netinet/tcp_seq.h> 40 #define TCPTIMERS 41 #include <netinet/tcp_timer.h> 42 #include <netinet/tcp_var.h> 43 #include <netinet/tcpip.h> 44 #define TANAMES 45 #include <netinet/tcp_debug.h> 46 47 #include <arpa/inet.h> 48 49 #include <stdio.h> 50 #include <errno.h> 51 #include <nlist.h> 52 #include <paths.h> 53 54 struct nlist nl[] = { 55 #define N_TCP_DEBUG 0 56 { "_tcp_debug" }, 57 #define N_TCP_DEBX 1 58 { "_tcp_debx" }, 59 #define N_SYSMAP 2 60 { "_Sysmap" }, 61 #define N_SYSSIZE 3 62 { "_Syssize" }, 63 { "" }, 64 }; 65 66 static struct pte *Sysmap; 67 static caddr_t tcp_pcbs[TCP_NDEBUG]; 68 static n_time ntime; 69 static int aflag, kflag, memf, follow, sflag, tflag; 70 71 main(argc, argv) 72 int argc; 73 char **argv; 74 { 75 extern char *optarg; 76 extern int optind; 77 int ch, i, jflag, npcbs, numeric(); 78 char *system, *core, *malloc(); 79 off_t lseek(); 80 81 jflag = npcbs = 0; 82 while ((ch = getopt(argc, argv, "afjp:st")) != EOF) 83 switch((char)ch) { 84 case 'a': 85 ++aflag; 86 break; 87 case 'f': 88 ++follow; 89 setlinebuf(stdout); 90 break; 91 case 'j': 92 ++jflag; 93 break; 94 case 'p': 95 if (npcbs >= TCP_NDEBUG) { 96 fputs("trpt: too many pcb's specified\n", 97 stderr); 98 exit(1); 99 } 100 (void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]); 101 break; 102 case 's': 103 ++sflag; 104 break; 105 case 't': 106 ++tflag; 107 break; 108 case '?': 109 default: 110 (void)fprintf(stderr, 111 "usage: trpt [-afjst] [-p hex-address] [system [core]]\n"); 112 exit(1); 113 } 114 argc -= optind; 115 argv += optind; 116 117 core = _PATH_KMEM; 118 if (argc > 0) { 119 system = *argv; 120 argc--, argv++; 121 if (argc > 0) { 122 core = *argv; 123 argc--, argv++; 124 ++kflag; 125 } 126 } 127 else 128 system = _PATH_UNIX; 129 130 if (nlist(system, nl) < 0 || !nl[0].n_value) { 131 fprintf(stderr, "trpt: %s: no namelist\n", system); 132 exit(1); 133 } 134 if ((memf = open(core, O_RDONLY)) < 0) { 135 perror(core); 136 exit(2); 137 } 138 if (kflag) { 139 off_t off; 140 141 Sysmap = (struct pte *) 142 malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 143 if (!Sysmap) { 144 fputs("arp: can't get memory for Sysmap.\n", stderr); 145 exit(1); 146 } 147 off = nl[N_SYSMAP].n_value & ~KERNBASE; 148 (void)lseek(memf, off, L_SET); 149 (void)read(memf, (char *)Sysmap, 150 (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 151 } 152 (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); 153 if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != 154 sizeof(tcp_debx)) { 155 perror("trpt: tcp_debx"); 156 exit(3); 157 } 158 (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); 159 if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != 160 sizeof(tcp_debug)) { 161 perror("trpt: tcp_debug"); 162 exit(3); 163 } 164 /* 165 * If no control blocks have been specified, figure 166 * out how many distinct one we have and summarize 167 * them in tcp_pcbs for sorting the trace records 168 * below. 169 */ 170 if (!npcbs) { 171 for (i = 0; i < TCP_NDEBUG; i++) { 172 register struct tcp_debug *td = &tcp_debug[i]; 173 register int j; 174 175 if (td->td_tcb == 0) 176 continue; 177 for (j = 0; j < npcbs; j++) 178 if (tcp_pcbs[j] == td->td_tcb) 179 break; 180 if (j >= npcbs) 181 tcp_pcbs[npcbs++] = td->td_tcb; 182 } 183 if (!npcbs) 184 exit(0); 185 } 186 qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric); 187 if (jflag) { 188 for (i = 0;;) { 189 printf("%x", (int)tcp_pcbs[i]); 190 if (++i == npcbs) 191 break; 192 fputs(", ", stdout); 193 } 194 putchar('\n'); 195 } 196 else for (i = 0; i < npcbs; i++) { 197 printf("\n%x:\n", (int)tcp_pcbs[i]); 198 dotrace(tcp_pcbs[i]); 199 } 200 exit(0); 201 } 202 203 dotrace(tcpcb) 204 register caddr_t tcpcb; 205 { 206 register struct tcp_debug *td; 207 register int i; 208 int prev_debx = tcp_debx; 209 210 again: if (--tcp_debx < 0) 211 tcp_debx = TCP_NDEBUG - 1; 212 for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) { 213 td = &tcp_debug[i]; 214 if (tcpcb && td->td_tcb != tcpcb) 215 continue; 216 ntime = ntohl(td->td_time); 217 tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, 218 &td->td_ti, td->td_req); 219 if (i == tcp_debx) 220 goto done; 221 } 222 for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) { 223 td = &tcp_debug[i]; 224 if (tcpcb && td->td_tcb != tcpcb) 225 continue; 226 ntime = ntohl(td->td_time); 227 tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, 228 &td->td_ti, td->td_req); 229 } 230 done: if (follow) { 231 prev_debx = tcp_debx + 1; 232 if (prev_debx >= TCP_NDEBUG) 233 prev_debx = 0; 234 do { 235 sleep(1); 236 (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); 237 if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != 238 sizeof(tcp_debx)) { 239 perror("trpt: tcp_debx"); 240 exit(3); 241 } 242 } while (tcp_debx == prev_debx); 243 (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); 244 if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != 245 sizeof(tcp_debug)) { 246 perror("trpt: tcp_debug"); 247 exit(3); 248 } 249 goto again; 250 } 251 } 252 253 /* 254 * Tcp debug routines 255 */ 256 /*ARGSUSED*/ 257 tcp_trace(act, ostate, atp, tp, ti, req) 258 short act, ostate; 259 struct tcpcb *atp, *tp; 260 struct tcpiphdr *ti; 261 int req; 262 { 263 tcp_seq seq, ack; 264 int flags, len, win, timer; 265 266 printf("%03ld %s:%s ",(ntime/10) % 1000, tcpstates[ostate], 267 tanames[act]); 268 switch (act) { 269 case TA_INPUT: 270 case TA_OUTPUT: 271 case TA_DROP: 272 if (aflag) { 273 printf("(src=%s,%u, ", 274 inet_ntoa(ti->ti_src), ntohs(ti->ti_sport)); 275 printf("dst=%s,%u)", 276 inet_ntoa(ti->ti_dst), ntohs(ti->ti_dport)); 277 } 278 seq = ti->ti_seq; 279 ack = ti->ti_ack; 280 len = ti->ti_len; 281 win = ti->ti_win; 282 if (act == TA_OUTPUT) { 283 seq = ntohl(seq); 284 ack = ntohl(ack); 285 len = ntohs(len); 286 win = ntohs(win); 287 } 288 if (act == TA_OUTPUT) 289 len -= sizeof(struct tcphdr); 290 if (len) 291 printf("[%lx..%lx)", seq, seq + len); 292 else 293 printf("%lx", seq); 294 printf("@%lx", ack); 295 if (win) 296 printf("(win=%x)", win); 297 flags = ti->ti_flags; 298 if (flags) { 299 register char *cp = "<"; 300 #define pf(flag, string) { \ 301 if (ti->ti_flags&flag) { \ 302 (void)printf("%s%s", cp, string); \ 303 cp = ","; \ 304 } \ 305 } 306 pf(TH_SYN, "SYN"); 307 pf(TH_ACK, "ACK"); 308 pf(TH_FIN, "FIN"); 309 pf(TH_RST, "RST"); 310 pf(TH_PUSH, "PUSH"); 311 pf(TH_URG, "URG"); 312 printf(">"); 313 } 314 break; 315 case TA_USER: 316 timer = req >> 8; 317 req &= 0xff; 318 printf("%s", prurequests[req]); 319 if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO) 320 printf("<%s>", tcptimers[timer]); 321 break; 322 } 323 printf(" -> %s", tcpstates[tp->t_state]); 324 /* print out internal state of tp !?! */ 325 printf("\n"); 326 if (sflag) { 327 printf("\trcv_nxt %lx rcv_wnd %x snd_una %lx snd_nxt %lx snd_max %lx\n", 328 tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt, 329 tp->snd_max); 330 printf("\tsnd_wl1 %lx snd_wl2 %lx snd_wnd %x\n", tp->snd_wl1, 331 tp->snd_wl2, tp->snd_wnd); 332 } 333 /* print out timers? */ 334 if (tflag) { 335 register char *cp = "\t"; 336 register int i; 337 338 for (i = 0; i < TCPT_NTIMERS; i++) { 339 if (tp->t_timer[i] == 0) 340 continue; 341 printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]); 342 if (i == TCPT_REXMT) 343 printf(" (t_rxtshft=%d)", tp->t_rxtshift); 344 cp = ", "; 345 } 346 if (*cp != '\t') 347 putchar('\n'); 348 } 349 } 350 351 numeric(c1, c2) 352 caddr_t *c1, *c2; 353 { 354 return(*c1 - *c2); 355 } 356 357 klseek(fd, base, off) 358 int fd, off; 359 off_t base; 360 { 361 off_t lseek(); 362 363 if (kflag) { /* get kernel pte */ 364 base &= ~KERNBASE; 365 base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET); 366 } 367 (void)lseek(fd, base, off); 368 } 369