|
|
1.1 root 1: #include <stdio.h>
2: #include <sys/param.h>
3: #include <sys/stream.h>
4: #include <sys/inet/in.h>
5: #define KERNEL 1 /* get kernel definitions */
6: #include <sys/inet/tcp.h>
7: #include <sys/inet/socket.h>
8: #include <sys/inet/udp.h>
9: #include <sys/inet/ip_var.h>
10: #include <sys/inet/tcp_timer.h>
11: #define TCPSTATES 1
12: #include <sys/inet/tcp_fsm.h>
13: #include <sys/inet/tcp_var.h>
14: #include <sys/inet/tcpip.h>
15: #include <sys/inet/tcpdebug.h>
16: #include <sys/ethernet.h>
17:
18: static int strip = 0; /* true if we're stripping the high bit from kernel addrs */
19:
20: /* predeclared */
21: doseek();
22: void doseekoff();
23: void doread();
24:
25: main(argc, argv)
26: char *argv[];
27: {
28: char *xinu, *kmem;
29: char action = '\0';
30: char *operand;
31: int ai=1;
32:
33: xinu = "/unix";
34: kmem = "/dev/kmem";
35:
36: if(argc > 1 && argv[ai][0] == '-') {
37: action = argv[ai][1];
38: operand = &argv[ai++][2];
39: }
40: if (argc > ai+1)
41: xinu = argv[ai++];
42: if (argc > ai)
43: kmem = argv[ai];
44: kern_init(xinu, kmem);
45:
46: switch(action) {
47: case '\0':
48: case 'c':
49: tcps(0);
50: udps();
51: break;
52: case 'i':
53: interfaces();
54: break;
55: case 's':
56: statistics();
57: break;
58: case 'r':
59: routes(0);
60: break;
61: case 'R':
62: routes(1);
63: break;
64: case 'a':
65: arps();
66: break;
67: case 'C':
68: tcps(1);
69: break;
70: case 't':
71: if (*operand == '\0' || strcmp(operand, "tcp")==0)
72: debugtcp();
73: else if (strcmp(operand, "il")==0)
74: debugil();
75: else if (strcmp(operand, "qe")==0)
76: debugqe();
77: break;
78: default:
79: fprintf(stderr, "Usage: %s -icCrat [unix [vmcore]]\n", argv[0]);
80: break;
81: }
82: }
83:
84: /*
85: * truncate name to rightmost n chars
86: */
87: trunc(name, n)
88: char *name;
89: int n;
90: {
91: register int i=strlen(name);
92:
93: return ((i<=n) ? name : name+(i-n));
94: }
95:
96:
97: #include "nlist.h"
98: struct nlist nl[] = {
99: {"_ipif", 0},
100: #define NL_INET 0
101: {"_ipstat", 0},
102: #define NL_IPSTAT 1
103: {"_tcpstat", 0},
104: #define NL_TCPSTAT 2
105: {"_Ntcp", 0},
106: #define NL_NTCP 3
107: {"_tcpsocks", 0},
108: #define NL_TCP 4
109: {"_ip_routes", 0},
110: #define NL_ROUTE 5
111: {"_ip_arps", 0},
112: #define NL_ARP 6
113: {"_Ninet", 0},
114: #define NL_NINET 7
115: {"_Nip_route", 0},
116: #define NL_NROUTE 8
117: {"_Nip_arp", 0},
118: #define NL_NARP 9
119: {"_ip_default_route", 0},
120: #define NL_DR 10
121: {"_bugarr", 0},
122: #define NL_TCPDEB 11
123: {"_Nbugarr", 0},
124: #define NL_NBUGARR 12
125: {"_Nudp", 0},
126: #define NL_NUDP 13
127: {"_udpconn", 0},
128: #define NL_UDP 14
129: {"_ild", 0},
130: #define NL_ILDEB 15
131: {"_qed", 0},
132: #define NL_QEDEB 16
133: {0, 0}
134: };
135: int kern_fd;
136:
137: kern_init(xinu, kmem)
138: char *xinu, *kmem;
139: {
140: int i;
141: nlist(xinu, nl);
142: if((long)nl[0].n_value == 0){
143: fprintf(stderr, "nlist %s failed\n", xinu);
144: exit(1);
145: }
146: if(strcmp(kmem, "/dev/kmem") != 0){
147: for(i = 0; nl[i].n_name; i++){
148: nl[i].n_value &= 0xffffff;
149: }
150: strip = 1;
151: }
152: kern_fd = open(kmem, 0);
153: if(kern_fd < 0){
154: perror(kmem);
155: exit(1);
156: }
157: }
158:
159: interfaces()
160: {
161: extern char *xflags();
162: struct ipif ipif[128];
163: int i, ninet;
164:
165: if (doseek(NL_NINET) < 0) {
166: printf("Internet not compiled into this kernel\n");
167: return;
168: }
169: doread((char *)&ninet, sizeof ninet);
170: if (ninet > (sizeof(ipif)/sizeof(struct ipif)))
171: ninet = sizeof(ipif)/sizeof(struct ipif);
172: printf("%-4s %-12s %-12s %5s %6s %6s %6s %6s\n",
173: "Mtu", "Network", "Address", "Flags",
174: "Ipkts", "Ierrs", "Opkts", "Oerrs");
175: doseek(NL_INET);
176: doread((char *)ipif, ninet*sizeof(struct ipif));
177: for(i = 0; i < ninet; i++){
178: if((ipif[i].flags&IFF_UP) == 0)
179: continue;
180: printf("%-4d %-12s ", ipif[i].mtu,
181: trunc(in_host(ipif[i].that),12));
182: printf("%-12s %5s %6d %6d %6d %6d\n",
183: trunc(in_host(ipif[i].thishost),12),
184: xflags(ipif[i].flags, "UHA?", " "),
185: ipif[i].ipackets, ipif[i].ierrors,
186: ipif[i].opackets, ipif[i].oerrors);
187: }
188: }
189:
190: statistics()
191: {
192: struct ipstat stats;
193: struct tcpstat tcpstat;
194:
195: if (doseek(NL_IPSTAT) < 0) {
196: printf("Internet not compiled into this kernel\n");
197: return;
198: }
199: doread((char *)&stats, sizeof(stats));
200: printf("IP:\n");
201: printf("%6d bad sums\n", stats.ips_badsum);
202: printf("%6d short packets\n", stats.ips_tooshort);
203: printf("%6d short data\n", stats.ips_toosmall);
204: printf("%6d bad header lengths\n", stats.ips_badhlen);
205: printf("%6d real bad header lengths\n", stats.ips_badlen);
206: printf("%6d queue overflows\n", stats.ips_qfull);
207: printf("%6d output routing errors\n", stats.ips_route);
208: printf("%6d fragmented packets\n", stats.ips_fragout);
209: if (doseek(NL_TCPSTAT) < 0) {
210: printf("Tcp not compiled into this kernel\n");
211: return;
212: }
213: doread((char *)&tcpstat, sizeof(tcpstat));
214: printf("TCP:\n");
215: printf("%6d bad sums\n", tcpstat.tcps_badsum);
216: printf("%6d bad offsets\n", tcpstat.tcps_badoff);
217: printf("%6d header drops\n", tcpstat.tcps_hdrops);
218: printf("%6d bad segments\n", tcpstat.tcps_badsegs);
219: printf("%6d retransmit timeouts\n", tcpstat.tcps_timeouts[0]);
220: printf("%6d persist timeouts\n", tcpstat.tcps_timeouts[1]);
221: printf("%6d keep-alive timeouts\n", tcpstat.tcps_timeouts[2]);
222: printf("%6d quiet time timeouts\n", tcpstat.tcps_timeouts[3]);
223: printf("%6d duplicate packets received\n", tcpstat.tcps_duplicates);
224: printf("%6d possibly late packets received\n", tcpstat.tcps_delayed);
225: }
226:
227: tcps(flag)
228: {
229: int i, ntcp;
230: struct socket so;
231: struct tcpcb tcpcb;
232: extern char *xflags();
233: char b1[100], b2[100];
234: struct in_service *sp;
235: #define SS_INTERESTING (SS_RCVATMARK|SS_OPEN|SS_ACTIVE|SS_WAITING|SS_PLEASEOPEN)
236:
237: if (doseek(NL_NTCP) < 0) {
238: printf("Tcp not compiled into this kernel\n");
239: return;
240: }
241: doread((char *)&ntcp, sizeof ntcp);
242: printf("Proto Dev Wque Rque State %18s %18s %14s\n",
243: "Remote Addr", "Local Addr", "Cstate");
244: for(i = 0; i < ntcp; i++){
245: doseekoff(NL_TCP, sizeof(so)*i);
246: doread((char *)&so, sizeof(so));
247: if((so.so_state&SS_INTERESTING) == 0)
248: continue;
249: if(so.so_tcpcb){
250: if(strip)
251: so.so_tcpcb =
252: (struct tcpcb *)((int)(so.so_tcpcb)&0xffffff);
253: lseek(kern_fd, so.so_tcpcb, 0);
254: doread((char *)&tcpcb, sizeof(tcpcb));
255: } else {
256: tcpcb.t_state = 0;
257: }
258: sp = in_service(0, "tcp", so.so_fport);
259: sprintf(b1, "%11s.%s", trunc(in_host(so.so_faddr),11), sp->name);
260: sp = in_service(0, "tcp", so.so_lport);
261: sprintf(b2, "%11s.%s", trunc(in_host(so.so_laddr),11), sp->name);
262: if(!flag || tcpcb.t_state != TCPS_LISTEN)
263: printf(" tcp %02d %4d %4d %5s %18.18s %18.18s %14s\n",
264: so.so_dev,
265: so.so_wcount, so.so_rcount,
266: xflags(so.so_state, "OPRWA?", " "),
267: b1, b2,
268: tcpstates[tcpcb.t_state]);
269: #ifdef ALL
270: if(!flag || tcpcb.t_state != TCPS_LISTEN)
271: printf("template %x\n", tcpcb.t_template);
272: #endif
273: if(flag && tcpcb.t_state != TCPS_LISTEN){
274: printf(" Timers:\n");
275: printf("\tretransmit %d\n\tpersist %d\n\tkeepalive %d\n\t2msl %d\n",
276: tcpcb.t_timer[0], tcpcb.t_timer[1],
277: tcpcb.t_timer[2], tcpcb.t_timer[3]);
278: printf(" Send sequence variables:");
279: printf("\n\tunacked %d\n\tnext %d\n\turgent ptr %d",
280: tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
281: printf("\n\tinitial number %d\n\twindow %d\n\thighest sent %d\n",
282: tcpcb.iss, tcpcb.snd_wnd, tcpcb.snd_max);
283: printf(" Receive sequence variables:");
284: printf("\n\tnext %d\n\turgent ptr %d",
285: tcpcb.rcv_nxt, tcpcb.rcv_up);
286: printf("\n\tinitial number %d\n\twindow %d\n\tadvertised %d\n",
287: tcpcb.irs, tcpcb.rcv_wnd, tcpcb.rcv_adv);
288: printf(" Transmit timing:");
289: printf("\n\tinactive %d\n\tround trip %d\n\tseq # timed %d\n\tsmoothed round trip %f\n",
290: tcpcb.t_idle, tcpcb.t_rtt, tcpcb.t_rtseq,
291: tcpcb.t_srtt);
292: printf(" Status:");
293: printf("\n\tmax segment size %d", tcpcb.t_maxseg);
294: printf("\n\tforcing out byte %d", tcpcb.t_force);
295: printf("\n\tflags 0x%x\n", tcpcb.t_flags);
296: printf("\n");
297: }
298: }
299: }
300:
301: udps()
302: {
303: int i, nudp;
304: struct udp udp[132];
305: extern char *xflags();
306: char b1[100], b2[100];
307: struct in_service *sp;
308:
309: if (doseek(NL_NUDP) < 0) {
310: printf("Udp not compiled into this kernel\n");
311: return;
312: }
313: doread((char *)&nudp, sizeof nudp);
314: printf("\nProto Dev State %18s %18s\n",
315: "Remote Addr", "Local Addr");
316: doseek(NL_UDP);
317: doread((char *)udp, nudp*sizeof(struct udp));
318: for (i = 0; i < nudp; i++) {
319: if(udp[i].rq == 0)
320: continue;
321: sp = in_service(0, "udp", udp[i].sport);
322: sprintf(b1, "%s.%.6s", trunc(in_host(udp[i].src),11), sp->name);
323: sp = in_service(0, "udp", udp[i].dport);
324: sprintf(b2, "%s.%.6s", trunc(in_host(udp[i].dst),11), sp->name);
325: printf(" udp %02d %5s %18.18s %18.18s\n",
326: i, xflags(udp[i].flags, "ILC?", " "),
327: b2, b1);
328: }
329: }
330:
331: char *
332: xflags(fl, fs, buf)
333: char *fs, *buf;
334: {
335: int i, len;
336: char *os;
337:
338: os = buf;
339: len = strlen(fs);
340: for(i = 0; i < len; i++){
341: if(fl & (1<<i))
342: *buf++ = fs[i];
343: }
344: *buf++ = '\0';
345: return(os);
346: }
347:
348: routes(all)
349: int all;
350: {
351: struct ip_route r[256];
352: int i;
353: int nroute;
354:
355: doseek(NL_DR);
356: doread((char *)r, sizeof(struct ip_route));
357: if (r[0].gate != 0)
358: printf("Default route is %s\n\n", in_host(r[0].gate));
359: doseek(NL_NROUTE);
360: doread((char *)&nroute, sizeof nroute);
361: if (nroute > (sizeof(r)/sizeof(struct ip_route)))
362: nroute = sizeof(r)/sizeof(struct ip_route);
363: doseek(NL_ROUTE);
364: doread((char *)r, nroute*sizeof(struct ip_route));
365: printf("%-14s %-14s\n", "Destination", "Gateway");
366: for(i = 0; i < nroute; i++){
367: if(all || r[i].dst!=r[i].gate){
368: printf("%-14s ", in_host(r[i].dst));
369: printf("%-14s\n", in_host(r[i].gate));
370: }
371: }
372: }
373:
374: arps()
375: {
376: struct ip_arp a[256];
377: int i, j, narp;
378:
379: if (doseek(NL_NARP) < 0) {
380: printf("Arp not compiled into this kernel\n");
381: return;
382: }
383: doread((char *)&narp, sizeof narp);
384: if (narp > (sizeof(a)/sizeof(struct ip_arp)))
385: narp = sizeof(a)/sizeof(struct ip_arp);
386: doseek(NL_ARP);
387: doread((char *)a, narp*sizeof(struct ip_arp));
388: printf("%-11s Ether-Address\n", "Host");
389: for(i = 0; i < narp; i++){
390: if(a[i].inaddr){
391: printf("%-11s ", in_host(a[i].inaddr));
392: for(j = 0; j < 6; j++){
393: printf("%02x ", a[i].enaddr[j]);
394: }
395: printf("\n");
396: }
397: }
398: }
399:
400: #define NEXT(i) ((i+1)%SIZDEBUG)
401: #define PREV(i) ((i+SIZDEBUG-1)%SIZDEBUG)
402: #define HEADER\
403: "\ntime src dst seq bytes ack wind cksm urg flags\n"
404: #define FORMAT "%4d %c %8x.%-4d %8x.%-4d %8x %3x %8x %4x %04x %8x %s\n"
405:
406: debugtcp()
407: {
408: struct tcpdebug d[SIZDEBUG];
409: int i, lasti= 0;
410: time_t t, lastt = 0;
411: time_t base = 0;
412: int line = 0;
413: char *xflags();
414: char xbuf[9];
415:
416: for(;;) {
417: /* get array */
418: if (doseek(NL_TCPDEB) < 0) {
419: printf("Tcp debugging not compiled into this kernel\n");
420: return;
421: }
422: doread((char *)d, sizeof(d));
423:
424: /* see if we've overflowed the buffer (or first time around) */
425: if (d[lasti].stamp != lastt) {
426: if (lastt != 0)
427: printf("** missing messages **\n");
428: /* find last(highest) timestamped entry */
429: for (i = NEXT(lasti); i != lasti; i = NEXT(i)) {
430: if (d[i].stamp < lastt) {
431: if (base == 0)
432: base = d[i].stamp;
433: lasti = PREV(i);
434: lastt = 0; /* for start of next loop */
435: break;
436: }
437: lastt = d[i].stamp;
438: }
439: }
440:
441: /* print all new entries */
442: for (i = NEXT(lasti); i != lasti; i = NEXT(i)) {
443: if (d[i].stamp < lastt)
444: break;
445: if (d[i].stamp == 0)
446: continue;
447: if ((line++ % 22) == 0)
448: printf(HEADER);
449: printf(FORMAT, d[i].stamp-base, d[i].inout ? 'o' : 'i',
450: ntohl(d[i].hdr.ti_src), ntohs(d[i].hdr.ti_sport),
451: ntohl(d[i].hdr.ti_dst), ntohs(d[i].hdr.ti_dport),
452: ntohl(d[i].hdr.ti_seq),
453: ntohs(d[i].hdr.ti_len) - sizeof(struct tcphdr),
454: ntohl(d[i].hdr.ti_ack),
455: ntohs(d[i].hdr.ti_win),
456: ntohs(d[i].hdr.ti_sum),
457: ntohs(d[i].hdr.ti_urp),
458: xflags(d[i].hdr.ti_flags&0xff, "FSRPAU??", xbuf)
459: );
460: lastt = d[i].stamp;
461: lasti = i;
462: }
463: fflush(stdout);
464: sleep(1);
465: }
466: }
467:
468: #define QEDEBSIZE 64
469: #define QENEXT(i) ((i+1)%QEDEBSIZE)
470: #define QEPREV(i) ((i+QEDEBSIZE-1)%QEDEBSIZE)
471: #define QEHEADER\
472: "\n time src dst type\n"
473: #define QEFORMAT "%7d %c %02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x %4x\n"
474:
475: #define ILDEBSIZE 64
476: #define ILNEXT(i) ((i+1)%ILDEBSIZE)
477: #define ILPREV(i) ((i+ILDEBSIZE-1)%ILDEBSIZE)
478: #define ILHEADER\
479: "\n time dst arp type\n"
480: #define ILFORMAT "%7d %c %02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x %4x\n"
481:
482: debugil()
483: {
484: struct {
485: time_t time;
486: unsigned short code;
487: struct etherpup pup;
488: } d[ILDEBSIZE];
489: int i, lasti= 0;
490: time_t t, lastt = 0;
491: time_t base = 0;
492: int line = 0;
493: char *xflags();
494: char xbuf[9];
495:
496: for(;;) {
497: /* get array */
498: if (doseek(NL_ILDEB) < 0) {
499: printf("Interlan debugging not compiled into this kernel\n");
500: return;
501: }
502: doread((char *)d, sizeof(d));
503:
504: /* see if we've overflowed the buffer (or first time around) */
505: if (d[lasti].time != lastt) {
506: if (lastt != 0)
507: printf("** missing messages **\n");
508: /* find last(highest) timestamped entry */
509: for (i = ILNEXT(lasti); i != lasti; i = ILNEXT(i)) {
510: if (d[i].time < lastt) {
511: if (base == 0)
512: base = d[i].time;
513: lasti = ILPREV(i);
514: lastt = 0; /* for start of next loop */
515: break;
516: }
517: lastt = d[i].time;
518: }
519: }
520:
521: /* print all new entries */
522: for (i = ILNEXT(lasti); i != lasti; i = ILNEXT(i)) {
523: if (d[i].time < lastt)
524: break;
525: if (d[i].time == 0)
526: continue;
527: if ((line++ % 22) == 0)
528: printf(ILHEADER);
529: printf(ILFORMAT, d[i].time-base, d[i].code?'o':'i',
530: d[i].pup.dhost[0], d[i].pup.dhost[1],
531: d[i].pup.dhost[2], d[i].pup.dhost[3],
532: d[i].pup.dhost[4], d[i].pup.dhost[5],
533: d[i].pup.shost[0], d[i].pup.shost[1],
534: d[i].pup.shost[2], d[i].pup.shost[3],
535: d[i].pup.shost[4], d[i].pup.shost[5],
536: d[i].pup.type
537: );
538: lastt = d[i].time;
539: lasti = i;
540: }
541: fflush(stdout);
542: sleep(1);
543: }
544: }
545:
546: debugqe()
547: {
548: struct {
549: time_t time;
550: unsigned short code;
551: struct etherpup pup;
552: } d[QEDEBSIZE];
553: int i, lasti= 0;
554: time_t t, lastt = 0;
555: time_t base = 0;
556: int line = 0;
557: char *xflags();
558: char xbuf[9];
559:
560: for(;;) {
561: /* get array */
562: if (doseek(NL_QEDEB) < 0) {
563: printf("Interlan debugging not compqeed into this kernel\n");
564: return;
565: }
566: doread((char *)d, sizeof(d));
567:
568: /* see if we've overflowed the buffer (or first time around) */
569: if (d[lasti].time != lastt) {
570: if (lastt != 0)
571: printf("** missing messages **\n");
572: /* find last(highest) timestamped entry */
573: for (i = QENEXT(lasti); i != lasti; i = QENEXT(i)) {
574: if (d[i].time < lastt) {
575: if (base == 0)
576: base = d[i].time;
577: lasti = QEPREV(i);
578: lastt = 0; /* for start of next loop */
579: break;
580: }
581: lastt = d[i].time;
582: }
583: }
584:
585: /* print all new entries */
586: for (i = QENEXT(lasti); i != lasti; i = QENEXT(i)) {
587: if (d[i].time < lastt)
588: break;
589: if (d[i].time == 0)
590: continue;
591: if ((line++ % 22) == 0)
592: printf(QEHEADER);
593: printf(QEFORMAT, d[i].time-base, d[i].code?'o':'i',
594: d[i].pup.dhost[0], d[i].pup.dhost[1],
595: d[i].pup.dhost[2], d[i].pup.dhost[3],
596: d[i].pup.dhost[4], d[i].pup.dhost[5],
597: d[i].pup.shost[0], d[i].pup.shost[1],
598: d[i].pup.shost[2], d[i].pup.shost[3],
599: d[i].pup.shost[4], d[i].pup.shost[5],
600: d[i].pup.type
601: );
602: lastt = d[i].time;
603: lasti = i;
604: }
605: fflush(stdout);
606: sleep(1);
607: }
608: }
609:
610: doseek(nlitem)
611: unsigned int nlitem;
612: {
613: if (nl[nlitem].n_value == 0)
614: return -1;
615: if(lseek(kern_fd, (long)nl[nlitem].n_value, 0) == -1){
616: perror("seek");
617: exit(1);
618: }
619: return 0;
620: }
621:
622: void
623: doseekoff(nlitem, offset)
624: unsigned int nlitem;
625: unsigned int offset;
626: {
627: if(lseek(kern_fd, (long)(nl[nlitem].n_value+offset), 0) == -1){
628: perror("seek");
629: exit(1);
630: }
631: }
632:
633: void
634: doread(addr, size)
635: char *addr;
636: unsigned int size;
637: {
638: if(read(kern_fd, addr, size) < 0){
639: perror("read");
640: exit(1);
641: }
642: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.