]> The Tcpdump Group git mirrors - tcpdump/blob - print-tcp.c
Add an "ip.h" header, to declare the IP stuff needed by dissectors, and
[tcpdump] / print-tcp.c
1 /*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.74 2000-09-23 08:54:41 guy Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <sys/param.h>
32 #include <sys/time.h>
33
34 #include <rpc/rpc.h>
35
36 #include <netinet/in.h>
37 #include <netinet/in_systm.h>
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include <unistd.h>
44
45 #ifdef INET6
46 #include <netinet/ip6.h>
47 #endif
48
49 #include "interface.h"
50 #include "addrtoname.h"
51 #include "extract.h"
52
53 #include "tcp.h"
54
55 #include "ip.h"
56
57 static void print_tcp_rst_data(register const u_char *sp, u_int length);
58
59 #define MAX_RST_DATA_LEN 30
60
61 /* Compatibility */
62 #ifndef TCPOPT_WSCALE
63 #define TCPOPT_WSCALE 3 /* window scale factor (rfc1072) */
64 #endif
65 #ifndef TCPOPT_SACKOK
66 #define TCPOPT_SACKOK 4 /* selective ack ok (rfc1072) */
67 #endif
68 #ifndef TCPOPT_SACK
69 #define TCPOPT_SACK 5 /* selective ack (rfc1072) */
70 #endif
71 #ifndef TCPOPT_ECHO
72 #define TCPOPT_ECHO 6 /* echo (rfc1072) */
73 #endif
74 #ifndef TCPOPT_ECHOREPLY
75 #define TCPOPT_ECHOREPLY 7 /* echo (rfc1072) */
76 #endif
77 #ifndef TCPOPT_TIMESTAMP
78 #define TCPOPT_TIMESTAMP 8 /* timestamps (rfc1323) */
79 #endif
80 #ifndef TCPOPT_CC
81 #define TCPOPT_CC 11 /* T/TCP CC options (rfc1644) */
82 #endif
83 #ifndef TCPOPT_CCNEW
84 #define TCPOPT_CCNEW 12 /* T/TCP CC options (rfc1644) */
85 #endif
86 #ifndef TCPOPT_CCECHO
87 #define TCPOPT_CCECHO 13 /* T/TCP CC options (rfc1644) */
88 #endif
89
90 /*
91 * Definitions required for ECN
92 * for use if the OS running tcpdump does not have ECN
93 */
94 #ifndef TH_ECNECHO
95 #define TH_ECNECHO 0x40 /* ECN Echo in tcp header */
96 #endif
97 #ifndef TH_CWR
98 #define TH_CWR 0x80 /* ECN Cwnd Reduced in tcp header*/
99 #endif
100
101 struct tha {
102 #ifndef INET6
103 struct in_addr src;
104 struct in_addr dst;
105 #else
106 struct in6_addr src;
107 struct in6_addr dst;
108 #endif /*INET6*/
109 u_int port;
110 };
111
112 struct tcp_seq_hash {
113 struct tcp_seq_hash *nxt;
114 struct tha addr;
115 tcp_seq seq;
116 tcp_seq ack;
117 };
118
119 #define TSEQ_HASHSIZE 919
120
121 /* These tcp optinos do not have the size octet */
122 #define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP)
123
124 static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
125
126
127 #ifndef TELNET_PORT
128 #define TELNET_PORT 23
129 #endif
130 #ifndef BGP_PORT
131 #define BGP_PORT 179
132 #endif
133 #define NETBIOS_SSN_PORT 139
134 #ifndef NFS_PORT
135 #define NFS_PORT 2049
136 #endif
137
138 static int tcp_cksum(register const struct ip *ip,
139 register const struct tcphdr *tp,
140 register int len)
141 {
142 int i, tlen;
143 union phu {
144 struct phdr {
145 u_int32_t src;
146 u_int32_t dst;
147 u_char mbz;
148 u_char proto;
149 u_int16_t len;
150 } ph;
151 u_int16_t pa[6];
152 } phu;
153 register const u_int16_t *sp;
154 u_int32_t sum;
155 tlen = ntohs(ip->ip_len) - ((const char *)tp-(const char*)ip);
156
157 /* pseudo-header.. */
158 phu.ph.len = htons(tlen);
159 phu.ph.mbz = 0;
160 phu.ph.proto = IPPROTO_TCP;
161 memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
162 memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
163
164 sp = &phu.pa[0];
165 sum = sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5];
166
167 sp = (const u_int16_t *)tp;
168
169 for (i=0; i<(tlen&~1); i+= 2)
170 sum += *sp++;
171
172 if (tlen & 1) {
173 sum += htons( (*(const char *)sp) << 8);
174 }
175
176 while (sum > 0xffff)
177 sum = (sum & 0xffff) + (sum >> 16);
178 sum = ~sum & 0xffff;
179
180 return (sum);
181 }
182
183 #ifdef INET6
184 static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp,
185 int len)
186 {
187 int i, tlen;
188 register const u_int16_t *sp;
189 u_int32_t sum;
190 union {
191 struct {
192 struct in6_addr ph_src;
193 struct in6_addr ph_dst;
194 u_int32_t ph_len;
195 u_int8_t ph_zero[3];
196 u_int8_t ph_nxt;
197 } ph;
198 u_int16_t pa[20];
199 } phu;
200
201 tlen = ntohs(ip6->ip6_plen) + sizeof(struct ip6_hdr) -
202 ((const char *)tp - (const char*)ip6);
203
204 /* pseudo-header */
205 memset(&phu, 0, sizeof(phu));
206 phu.ph.ph_src = ip6->ip6_src;
207 phu.ph.ph_dst = ip6->ip6_dst;
208 phu.ph.ph_len = htonl(tlen);
209 phu.ph.ph_nxt = IPPROTO_TCP;
210
211 sum = 0;
212 for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
213 sum += phu.pa[i];
214
215 sp = (const u_int16_t *)tp;
216
217 for (i = 0; i < (tlen & ~1); i += 2)
218 sum += *sp++;
219
220 if (tlen & 1)
221 sum += htons((*(const char *)sp) << 8);
222
223 while (sum > 0xffff)
224 sum = (sum & 0xffff) + (sum >> 16);
225 sum = ~sum & 0xffff;
226
227 return (sum);
228 }
229 #endif
230
231 void
232 tcp_print(register const u_char *bp, register u_int length,
233 register const u_char *bp2)
234 {
235 register const struct tcphdr *tp;
236 register const struct ip *ip;
237 register u_char flags;
238 register int hlen;
239 register char ch;
240 u_int16_t sport, dport, win, urp;
241 u_int32_t seq, ack, thseq, thack;
242 int threv;
243 #ifdef INET6
244 register const struct ip6_hdr *ip6;
245 #endif
246
247 tp = (struct tcphdr *)bp;
248 ip = (struct ip *)bp2;
249 #ifdef INET6
250 if (ip->ip_v == 6)
251 ip6 = (struct ip6_hdr *)bp2;
252 else
253 ip6 = NULL;
254 #endif /*INET6*/
255 ch = '\0';
256 if (!TTEST(tp->th_dport)) {
257 (void)printf("%s > %s: [|tcp]",
258 ipaddr_string(&ip->ip_src),
259 ipaddr_string(&ip->ip_dst));
260 return;
261 }
262
263 sport = ntohs(tp->th_sport);
264 dport = ntohs(tp->th_dport);
265
266
267 hlen = tp->th_off * 4;
268
269 /*
270 * If data present and NFS port used, assume NFS.
271 * Pass offset of data plus 4 bytes for RPC TCP msg length
272 * to NFS print routines.
273 */
274 if (!qflag) {
275 if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend &&
276 dport == NFS_PORT) {
277 nfsreq_print((u_char *)tp + hlen + 4, length-hlen,
278 (u_char *)ip);
279 return;
280 } else if ((u_char *)tp + 4 + sizeof(struct rpc_msg)
281 <= snapend &&
282 sport == NFS_PORT) {
283 nfsreply_print((u_char *)tp + hlen + 4,length-hlen,
284 (u_char *)ip);
285 return;
286 }
287 }
288 #ifdef INET6
289 if (ip6) {
290 if (ip6->ip6_nxt == IPPROTO_TCP) {
291 (void)printf("%s.%s > %s.%s: ",
292 ip6addr_string(&ip6->ip6_src),
293 tcpport_string(sport),
294 ip6addr_string(&ip6->ip6_dst),
295 tcpport_string(dport));
296 } else {
297 (void)printf("%s > %s: ",
298 tcpport_string(sport), tcpport_string(dport));
299 }
300 } else
301 #endif /*INET6*/
302 {
303 if (ip->ip_p == IPPROTO_TCP) {
304 (void)printf("%s.%s > %s.%s: ",
305 ipaddr_string(&ip->ip_src),
306 tcpport_string(sport),
307 ipaddr_string(&ip->ip_dst),
308 tcpport_string(dport));
309 } else {
310 (void)printf("%s > %s: ",
311 tcpport_string(sport), tcpport_string(dport));
312 }
313 }
314
315 TCHECK(*tp);
316
317 seq = (u_int32_t)ntohl(tp->th_seq);
318 ack = (u_int32_t)ntohl(tp->th_ack);
319 win = ntohs(tp->th_win);
320 urp = ntohs(tp->th_urp);
321
322 if (qflag) {
323 (void)printf("tcp %d", length - tp->th_off * 4);
324 return;
325 }
326 if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH|
327 TH_ECNECHO|TH_CWR)) {
328 if (flags & TH_SYN)
329 putchar('S');
330 if (flags & TH_FIN)
331 putchar('F');
332 if (flags & TH_RST)
333 putchar('R');
334 if (flags & TH_PUSH)
335 putchar('P');
336 if (flags & TH_CWR)
337 putchar('W'); /* congestion _W_indow reduced (ECN) */
338 if (flags & TH_ECNECHO)
339 putchar('E'); /* ecn _E_cho sent (ECN) */
340 } else
341 putchar('.');
342
343 if (!Sflag && (flags & TH_ACK)) {
344 register struct tcp_seq_hash *th;
345 register int rev;
346 struct tha tha;
347 /*
348 * Find (or record) the initial sequence numbers for
349 * this conversation. (we pick an arbitrary
350 * collating order so there's only one entry for
351 * both directions).
352 */
353 #ifdef INET6
354 memset(&tha, 0, sizeof(tha));
355 rev = 0;
356 if (ip6) {
357 if (sport > dport) {
358 rev = 1;
359 } else if (sport == dport) {
360 int i;
361
362 for (i = 0; i < 4; i++) {
363 if (((u_int32_t *)(&ip6->ip6_src))[i] >
364 ((u_int32_t *)(&ip6->ip6_dst))[i]) {
365 rev = 1;
366 break;
367 }
368 }
369 }
370 if (rev) {
371 tha.src = ip6->ip6_dst;
372 tha.dst = ip6->ip6_src;
373 tha.port = dport << 16 | sport;
374 } else {
375 tha.dst = ip6->ip6_dst;
376 tha.src = ip6->ip6_src;
377 tha.port = sport << 16 | dport;
378 }
379 } else {
380 if (sport > dport ||
381 (sport == dport &&
382 ip->ip_src.s_addr > ip->ip_dst.s_addr)) {
383 rev = 1;
384 }
385 if (rev) {
386 *(struct in_addr *)&tha.src = ip->ip_dst;
387 *(struct in_addr *)&tha.dst = ip->ip_src;
388 tha.port = dport << 16 | sport;
389 } else {
390 *(struct in_addr *)&tha.dst = ip->ip_dst;
391 *(struct in_addr *)&tha.src = ip->ip_src;
392 tha.port = sport << 16 | dport;
393 }
394 }
395 #else
396 if (sport < dport ||
397 (sport == dport &&
398 ip->ip_src.s_addr < ip->ip_dst.s_addr)) {
399 tha.src = ip->ip_src, tha.dst = ip->ip_dst;
400 tha.port = sport << 16 | dport;
401 rev = 0;
402 } else {
403 tha.src = ip->ip_dst, tha.dst = ip->ip_src;
404 tha.port = dport << 16 | sport;
405 rev = 1;
406 }
407 #endif
408
409 threv = rev;
410 for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
411 th->nxt; th = th->nxt)
412 if (!memcmp((char *)&tha, (char *)&th->addr,
413 sizeof(th->addr)))
414 break;
415
416 if (!th->nxt || (flags & TH_SYN)) {
417 /* didn't find it or new conversation */
418 if (th->nxt == NULL) {
419 th->nxt = (struct tcp_seq_hash *)
420 calloc(1, sizeof(*th));
421 if (th->nxt == NULL)
422 error("tcp_print: calloc");
423 }
424 th->addr = tha;
425 if (rev)
426 th->ack = seq, th->seq = ack - 1;
427 else
428 th->seq = seq, th->ack = ack - 1;
429
430 } else {
431 if (rev)
432 seq -= th->ack, ack -= th->seq;
433 else
434 seq -= th->seq, ack -= th->ack;
435 }
436
437 thseq = th->seq;
438 thack = th->ack;
439 } else {
440 /*fool gcc*/
441 thseq = thack = threv = 0;
442 }
443 if (hlen > length) {
444 (void)printf(" [bad hdr length]");
445 return;
446 }
447
448 if (ip->ip_v == 4 && vflag) {
449 int sum;
450 if (TTEST2(tp->th_sport, length)) {
451 sum = tcp_cksum(ip, tp, length);
452 if (sum != 0)
453 (void)printf(" [bad tcp cksum %x!]", sum);
454 else
455 (void)printf(" [tcp sum ok]");
456 }
457 }
458 #ifdef INET6
459 if (ip->ip_v == 6 && ip6->ip6_plen && vflag) {
460 int sum;
461 if (TTEST2(tp->th_sport, length)) {
462 sum = tcp6_cksum(ip6, tp, length);
463 if (sum != 0)
464 (void)printf(" [bad tcp cksum %x!]", sum);
465 else
466 (void)printf(" [tcp sum ok]");
467 }
468 }
469 #endif
470
471 length -= hlen;
472 if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST))
473 (void)printf(" %u:%u(%d)", seq, seq + length, length);
474 if (flags & TH_ACK)
475 (void)printf(" ack %u", ack);
476
477 (void)printf(" win %d", win);
478
479 if (flags & TH_URG)
480 (void)printf(" urg %d", urp);
481 /*
482 * Handle any options.
483 */
484 if ((hlen -= sizeof(*tp)) > 0) {
485 register const u_char *cp;
486 register int i, opt, len, datalen;
487
488 cp = (const u_char *)tp + sizeof(*tp);
489 putchar(' ');
490 ch = '<';
491 while (hlen > 0) {
492 putchar(ch);
493 TCHECK(*cp);
494 opt = *cp++;
495 if (ZEROLENOPT(opt))
496 len = 1;
497 else {
498 TCHECK(*cp);
499 len = *cp++; /* total including type, len */
500 if (len < 2 || len > hlen)
501 goto bad;
502 --hlen; /* account for length byte */
503 }
504 --hlen; /* account for type byte */
505 datalen = 0;
506
507 /* Bail if "l" bytes of data are not left or were not captured */
508 #define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); }
509
510 switch (opt) {
511
512 case TCPOPT_MAXSEG:
513 (void)printf("mss");
514 datalen = 2;
515 LENCHECK(datalen);
516 (void)printf(" %u", EXTRACT_16BITS(cp));
517
518 break;
519
520 case TCPOPT_EOL:
521 (void)printf("eol");
522 break;
523
524 case TCPOPT_NOP:
525 (void)printf("nop");
526 break;
527
528 case TCPOPT_WSCALE:
529 (void)printf("wscale");
530 datalen = 1;
531 LENCHECK(datalen);
532 (void)printf(" %u", *cp);
533 break;
534
535 case TCPOPT_SACKOK:
536 (void)printf("sackOK");
537 break;
538
539 case TCPOPT_SACK:
540 (void)printf("sack");
541 datalen = len - 2;
542 if (datalen % 8 != 0) {
543 (void)printf(" malformed sack ");
544 } else {
545 u_int32_t s, e;
546
547 (void)printf(" sack %d ", datalen / 8);
548 for (i = 0; i < datalen; i += 8) {
549 LENCHECK(i + 4);
550 s = EXTRACT_32BITS(cp + i);
551 LENCHECK(i + 8);
552 e = EXTRACT_32BITS(cp + i + 4);
553 if (threv) {
554 s -= thseq;
555 e -= thseq;
556 } else {
557 s -= thack;
558 e -= thack;
559 }
560 (void)printf("{%u:%u}", s, e);
561 }
562 (void)printf(" ");
563 }
564 break;
565
566 case TCPOPT_ECHO:
567 (void)printf("echo");
568 datalen = 4;
569 LENCHECK(datalen);
570 (void)printf(" %u", EXTRACT_32BITS(cp));
571 break;
572
573 case TCPOPT_ECHOREPLY:
574 (void)printf("echoreply");
575 datalen = 4;
576 LENCHECK(datalen);
577 (void)printf(" %u", EXTRACT_32BITS(cp));
578 break;
579
580 case TCPOPT_TIMESTAMP:
581 (void)printf("timestamp");
582 datalen = 8;
583 LENCHECK(4);
584 (void)printf(" %u", EXTRACT_32BITS(cp));
585 LENCHECK(datalen);
586 (void)printf(" %u", EXTRACT_32BITS(cp + 4));
587 break;
588
589 case TCPOPT_CC:
590 (void)printf("cc");
591 datalen = 4;
592 LENCHECK(datalen);
593 (void)printf(" %u", EXTRACT_32BITS(cp));
594 break;
595
596 case TCPOPT_CCNEW:
597 (void)printf("ccnew");
598 datalen = 4;
599 LENCHECK(datalen);
600 (void)printf(" %u", EXTRACT_32BITS(cp));
601 break;
602
603 case TCPOPT_CCECHO:
604 (void)printf("ccecho");
605 datalen = 4;
606 LENCHECK(datalen);
607 (void)printf(" %u", EXTRACT_32BITS(cp));
608 break;
609
610 default:
611 (void)printf("opt-%d:", opt);
612 datalen = len - 2;
613 for (i = 0; i < datalen; ++i) {
614 LENCHECK(i);
615 (void)printf("%02x", cp[i]);
616 }
617 break;
618 }
619
620 /* Account for data printed */
621 cp += datalen;
622 hlen -= datalen;
623
624 /* Check specification against observed length */
625 ++datalen; /* option octet */
626 if (!ZEROLENOPT(opt))
627 ++datalen; /* size octet */
628 if (datalen != len)
629 (void)printf("[len %d]", len);
630 ch = ',';
631 if (opt == TCPOPT_EOL)
632 break;
633 }
634 putchar('>');
635 }
636
637 if (length <= 0)
638 return;
639
640 /*
641 * Decode payload if necessary.
642 */
643 bp += (tp->th_off * 4);
644 if (flags & TH_RST) {
645 if (vflag)
646 print_tcp_rst_data(bp, length);
647 } else {
648 if (sport == TELNET_PORT || dport == TELNET_PORT) {
649 if (!qflag && vflag)
650 telnet_print(bp, length);
651 } else if (sport == BGP_PORT || dport == BGP_PORT)
652 bgp_print(bp, length);
653 else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT)
654 nbt_tcp_print(bp, length);
655 }
656 return;
657 bad:
658 fputs("[bad opt]", stdout);
659 if (ch != '\0')
660 putchar('>');
661 return;
662 trunc:
663 fputs("[|tcp]", stdout);
664 if (ch != '\0')
665 putchar('>');
666 }
667
668 /*
669 * RFC1122 says the following on data in RST segments:
670 *
671 * 4.2.2.12 RST Segment: RFC-793 Section 3.4
672 *
673 * A TCP SHOULD allow a received RST segment to include data.
674 *
675 * DISCUSSION
676 * It has been suggested that a RST segment could contain
677 * ASCII text that encoded and explained the cause of the
678 * RST. No standard has yet been established for such
679 * data.
680 *
681 */
682
683 static void
684 print_tcp_rst_data(register const u_char *sp, u_int length)
685 {
686 int c;
687
688 if (TTEST2(*sp, length))
689 printf(" [RST");
690 else
691 printf(" [!RST");
692 if (length > MAX_RST_DATA_LEN) {
693 length = MAX_RST_DATA_LEN; /* can use -X for longer */
694 putchar('+'); /* indicate we truncate */
695 }
696 putchar(' ');
697 while (length-- && sp <= snapend) {
698 c = *sp++;
699 if (isprint(c))
700 putchar(c);
701 else
702 putchar('.');
703 }
704 putchar(']');
705 }