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