]> git.saurik.com Git - apple/network_cmds.git/blob - trpt.tproj/trpt.c
network_cmds-245.tar.gz
[apple/network_cmds.git] / trpt.tproj / trpt.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1983, 1988, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57 #ifndef lint
58 static char copyright[] =
59 "@(#) Copyright (c) 1983, 1988, 1993\n\
60 The Regents of the University of California. All rights reserved.\n";
61 #endif /* not lint */
62
63 #ifndef lint
64 static char sccsid[] = "@(#)trpt.c 8.1 (Berkeley) 6/6/93";
65 #endif /* not lint */
66
67 #include <sys/param.h>
68 #if BSD >= 199103
69 #define NEWVM
70 #endif
71 #ifndef NEWVM
72 #include <machine/pte.h>
73 #include <sys/vmmac.h>
74 #endif
75 #include <sys/socket.h>
76 #include <sys/socketvar.h>
77 #define PRUREQUESTS
78 #include <sys/protosw.h>
79 #include <sys/file.h>
80
81 #include <net/route.h>
82 #include <net/if.h>
83
84 #include <netinet/in.h>
85 #include <netinet/in_systm.h>
86 #include <netinet/ip.h>
87 #include <netinet/in_pcb.h>
88 #include <netinet/ip_var.h>
89 #include <netinet/tcp.h>
90 #define TCPSTATES
91 #include <netinet/tcp_fsm.h>
92 #include <netinet/tcp_seq.h>
93 #define TCPTIMERS
94 #include <netinet/tcp_timer.h>
95 #include <netinet/tcp_var.h>
96 #include <netinet/tcpip.h>
97 #define TANAMES
98 #include <netinet/tcp_debug.h>
99
100 #include <arpa/inet.h>
101
102 #include <stdio.h>
103 #include <errno.h>
104 #include <nlist.h>
105 #include <paths.h>
106
107 struct tcp_debug tcp_debug[TCP_NDEBUG];
108 int tcp_debx;
109
110 struct nlist nl[] = {
111 #define N_TCP_DEBUG 0
112 { "_tcp_debug" },
113 #define N_TCP_DEBX 1
114 { "_tcp_debx" },
115 #ifndef NEWVM
116 #define N_SYSMAP 2
117 { "_Sysmap" },
118 #define N_SYSSIZE 3
119 { "_Syssize" },
120 #endif
121 { "" },
122 };
123
124 #ifndef NEWVM
125 static struct pte *Sysmap;
126 #endif
127 static caddr_t tcp_pcbs[TCP_NDEBUG];
128 static n_time ntime;
129 static int aflag, kflag, memf, follow, sflag, tflag;
130
131 main(argc, argv)
132 int argc;
133 char **argv;
134 {
135 extern char *optarg;
136 extern int optind;
137 int ch, i, jflag, npcbs, numeric();
138 char *system, *core, *malloc();
139 off_t lseek();
140
141 jflag = npcbs = 0;
142 while ((ch = getopt(argc, argv, "afjp:st")) != EOF)
143 switch (ch) {
144 case 'a':
145 ++aflag;
146 break;
147 case 'f':
148 ++follow;
149 setlinebuf(stdout);
150 break;
151 case 'j':
152 ++jflag;
153 break;
154 case 'p':
155 if (npcbs >= TCP_NDEBUG) {
156 fputs("trpt: too many pcb's specified\n",
157 stderr);
158 exit(1);
159 }
160 (void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]);
161 break;
162 case 's':
163 ++sflag;
164 break;
165 case 't':
166 ++tflag;
167 break;
168 case '?':
169 default:
170 (void)fprintf(stderr,
171 "usage: trpt [-afjst] [-p hex-address] [system [core]]\n");
172 exit(1);
173 }
174 argc -= optind;
175 argv += optind;
176
177 core = _PATH_KMEM;
178 if (argc > 0) {
179 system = *argv;
180 argc--, argv++;
181 if (argc > 0) {
182 core = *argv;
183 argc--, argv++;
184 ++kflag;
185 }
186 /*
187 * Discard setgid privileges if not the running kernel so that
188 * bad guys can't print interesting stuff from kernel memory.
189 */
190 setgid(getgid());
191 }
192 else
193 system = _PATH_UNIX;
194
195 if (nlist(system, nl) < 0 || !nl[0].n_value) {
196 fprintf(stderr, "trpt: %s: no namelist\n", system);
197 exit(1);
198 }
199 if ((memf = open(core, O_RDONLY)) < 0) {
200 perror(core);
201 exit(2);
202 }
203 if (kflag) {
204 #ifdef NEWVM
205 fputs("trpt: can't do core files yet\n", stderr);
206 exit(1);
207 #else
208 off_t off;
209
210 Sysmap = (struct pte *)
211 malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
212 if (!Sysmap) {
213 fputs("trpt: can't get memory for Sysmap.\n", stderr);
214 exit(1);
215 }
216 off = nl[N_SYSMAP].n_value & ~KERNBASE;
217 (void)lseek(memf, off, L_SET);
218 (void)read(memf, (char *)Sysmap,
219 (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
220 #endif
221 }
222 (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET);
223 if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) !=
224 sizeof(tcp_debx)) {
225 perror("trpt: tcp_debx");
226 exit(3);
227 }
228 (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET);
229 if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) !=
230 sizeof(tcp_debug)) {
231 perror("trpt: tcp_debug");
232 exit(3);
233 }
234 /*
235 * If no control blocks have been specified, figure
236 * out how many distinct one we have and summarize
237 * them in tcp_pcbs for sorting the trace records
238 * below.
239 */
240 if (!npcbs) {
241 for (i = 0; i < TCP_NDEBUG; i++) {
242 register struct tcp_debug *td = &tcp_debug[i];
243 register int j;
244
245 if (td->td_tcb == 0)
246 continue;
247 for (j = 0; j < npcbs; j++)
248 if (tcp_pcbs[j] == td->td_tcb)
249 break;
250 if (j >= npcbs)
251 tcp_pcbs[npcbs++] = td->td_tcb;
252 }
253 if (!npcbs)
254 exit(0);
255 }
256 qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric);
257 if (jflag) {
258 for (i = 0;;) {
259 printf("%x", (int)tcp_pcbs[i]);
260 if (++i == npcbs)
261 break;
262 fputs(", ", stdout);
263 }
264 putchar('\n');
265 }
266 else for (i = 0; i < npcbs; i++) {
267 printf("\n%x:\n", (int)tcp_pcbs[i]);
268 dotrace(tcp_pcbs[i]);
269 }
270 exit(0);
271 }
272
273 dotrace(tcpcb)
274 register caddr_t tcpcb;
275 {
276 register struct tcp_debug *td;
277 register int i;
278 int prev_debx = tcp_debx;
279
280 again: if (--tcp_debx < 0)
281 tcp_debx = TCP_NDEBUG - 1;
282 for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) {
283 td = &tcp_debug[i];
284 if (tcpcb && td->td_tcb != tcpcb)
285 continue;
286 ntime = ntohl(td->td_time);
287 tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
288 &td->td_ti.ti_t, td->td_req);
289 if (i == tcp_debx)
290 goto done;
291 }
292 for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) {
293 td = &tcp_debug[i];
294 if (tcpcb && td->td_tcb != tcpcb)
295 continue;
296 ntime = ntohl(td->td_time);
297 tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
298 &td->td_ti.ti_t, td->td_req);
299 }
300 done: if (follow) {
301 prev_debx = tcp_debx + 1;
302 if (prev_debx >= TCP_NDEBUG)
303 prev_debx = 0;
304 do {
305 sleep(1);
306 (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET);
307 if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) !=
308 sizeof(tcp_debx)) {
309 perror("trpt: tcp_debx");
310 exit(3);
311 }
312 } while (tcp_debx == prev_debx);
313 (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET);
314 if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) !=
315 sizeof(tcp_debug)) {
316 perror("trpt: tcp_debug");
317 exit(3);
318 }
319 goto again;
320 }
321 }
322
323 /*
324 * Tcp debug routines
325 */
326 /*ARGSUSED*/
327 tcp_trace(act, ostate, atp, tp, ti, req)
328 short act, ostate;
329 struct tcpcb *atp, *tp;
330 struct tcpiphdr *ti;
331 int req;
332 {
333 tcp_seq seq, ack;
334 int flags, len, win, timer;
335
336 printf("%03ld %s:%s ",(ntime/10) % 1000, tcpstates[ostate],
337 tanames[act]);
338 switch (act) {
339 case TA_INPUT:
340 case TA_OUTPUT:
341 case TA_DROP:
342 if (aflag) {
343 printf("(src=%s,%u, ",
344 inet_ntoa(ti->ti_src), ntohs(ti->ti_sport));
345 printf("dst=%s,%u)",
346 inet_ntoa(ti->ti_dst), ntohs(ti->ti_dport));
347 }
348 seq = ti->ti_seq;
349 ack = ti->ti_ack;
350 len = ti->ti_len;
351 win = ti->ti_win;
352 if (act == TA_OUTPUT) {
353 seq = ntohl(seq);
354 ack = ntohl(ack);
355 len = ntohs(len);
356 win = ntohs(win);
357 }
358 if (act == TA_OUTPUT)
359 len -= sizeof(struct tcphdr);
360 if (len)
361 printf("[%lx..%lx)", seq, seq + len);
362 else
363 printf("%lx", seq);
364 printf("@%lx", ack);
365 if (win)
366 printf("(win=%x)", win);
367 flags = ti->ti_flags;
368 if (flags) {
369 register char *cp = "<";
370 #define pf(flag, string) { \
371 if (ti->ti_flags&flag) { \
372 (void)printf("%s%s", cp, string); \
373 cp = ","; \
374 } \
375 }
376 pf(TH_SYN, "SYN");
377 pf(TH_ACK, "ACK");
378 pf(TH_FIN, "FIN");
379 pf(TH_RST, "RST");
380 pf(TH_PUSH, "PUSH");
381 pf(TH_URG, "URG");
382 printf(">");
383 }
384 break;
385 case TA_USER:
386 timer = req >> 8;
387 req &= 0xff;
388 printf("%s", prurequests[req]);
389 if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO)
390 printf("<%s>", tcptimers[timer]);
391 break;
392 }
393 printf(" -> %s", tcpstates[tp->t_state]);
394 /* print out internal state of tp !?! */
395 printf("\n");
396 if (sflag) {
397 printf("\trcv_nxt %lx rcv_wnd %x snd_una %lx snd_nxt %lx snd_max %lx\n",
398 tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt,
399 tp->snd_max);
400 printf("\tsnd_wl1 %lx snd_wl2 %lx snd_wnd %x\n", tp->snd_wl1,
401 tp->snd_wl2, tp->snd_wnd);
402 }
403 /* print out timers? */
404 if (tflag) {
405 register char *cp = "\t";
406 register int i;
407
408 for (i = 0; i < TCPT_NTIMERS; i++) {
409 if (tp->t_timer[i] == 0)
410 continue;
411 printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]);
412 if (i == TCPT_REXMT)
413 printf(" (t_rxtshft=%d)", tp->t_rxtshift);
414 cp = ", ";
415 }
416 if (*cp != '\t')
417 putchar('\n');
418 }
419 }
420
421 numeric(c1, c2)
422 caddr_t *c1, *c2;
423 {
424 return(*c1 - *c2);
425 }
426
427 klseek(fd, base, off)
428 int fd, off;
429 off_t base;
430 {
431 off_t lseek();
432
433 #ifndef NEWVM
434 if (kflag) { /* get kernel pte */
435 base &= ~KERNBASE;
436 base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
437 }
438 #endif
439 (void)lseek(fd, base, off);
440 }