xref: /freebsd/contrib/tcpdump/print-tcp.c (revision 3193579b66fd7067f898dbc54bdea81a0e6f9bd0)
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.95 2001/12/10 08:21:24 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 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <unistd.h>
43 
44 #include "interface.h"
45 #include "addrtoname.h"
46 #include "extract.h"
47 
48 #include "tcp.h"
49 
50 #include "ip.h"
51 #ifdef INET6
52 #include "ip6.h"
53 #endif
54 
55 #include "nameser.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 
62 struct tha {
63 #ifndef INET6
64 	struct in_addr src;
65 	struct in_addr dst;
66 #else
67 	struct in6_addr src;
68 	struct in6_addr dst;
69 #endif /*INET6*/
70 	u_int port;
71 };
72 
73 struct tcp_seq_hash {
74 	struct tcp_seq_hash *nxt;
75 	struct tha addr;
76 	tcp_seq seq;
77 	tcp_seq ack;
78 };
79 
80 #define TSEQ_HASHSIZE 919
81 
82 /* These tcp optinos do not have the size octet */
83 #define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP)
84 
85 static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
86 
87 
88 #ifndef TELNET_PORT
89 #define TELNET_PORT	23
90 #endif
91 #ifndef BGP_PORT
92 #define BGP_PORT	179
93 #endif
94 #define NETBIOS_SSN_PORT 139
95 #ifndef PPTP_PORT
96 #define PPTP_PORT	1723
97 #endif
98 #define BEEP_PORT        10288
99 #ifndef NFS_PORT
100 #define NFS_PORT	2049
101 #endif
102 #define MSDP_PORT	639
103 
104 static int tcp_cksum(register const struct ip *ip,
105 		     register const struct tcphdr *tp,
106 		     register int len)
107 {
108 	union phu {
109 		struct phdr {
110 			u_int32_t src;
111 			u_int32_t dst;
112 			u_char mbz;
113 			u_char proto;
114 			u_int16_t len;
115 		} ph;
116 		u_int16_t pa[6];
117 	} phu;
118 	const u_int16_t *sp;
119 
120 	/* pseudo-header.. */
121 	phu.ph.len = htons(len);	/* XXX */
122 	phu.ph.mbz = 0;
123 	phu.ph.proto = IPPROTO_TCP;
124 	memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
125 	memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
126 
127 	sp = &phu.pa[0];
128 	return in_cksum((u_short *)tp, len,
129 			sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);
130 }
131 
132 #ifdef INET6
133 static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp,
134 	int len)
135 {
136 	int i, tlen;
137 	register const u_int16_t *sp;
138 	u_int32_t sum;
139 	union {
140 		struct {
141 			struct in6_addr ph_src;
142 			struct in6_addr ph_dst;
143 			u_int32_t	ph_len;
144 			u_int8_t	ph_zero[3];
145 			u_int8_t	ph_nxt;
146 		} ph;
147 		u_int16_t pa[20];
148 	} phu;
149 
150 	tlen = ntohs(ip6->ip6_plen) + sizeof(struct ip6_hdr) -
151 	    ((const char *)tp - (const char*)ip6);
152 
153 	/* pseudo-header */
154 	memset(&phu, 0, sizeof(phu));
155 	phu.ph.ph_src = ip6->ip6_src;
156 	phu.ph.ph_dst = ip6->ip6_dst;
157 	phu.ph.ph_len = htonl(tlen);
158 	phu.ph.ph_nxt = IPPROTO_TCP;
159 
160 	sum = 0;
161 	for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
162 		sum += phu.pa[i];
163 
164 	sp = (const u_int16_t *)tp;
165 
166 	for (i = 0; i < (tlen & ~1); i += 2)
167 		sum += *sp++;
168 
169 	if (tlen & 1)
170 		sum += htons((*(const u_int8_t *)sp) << 8);
171 
172 	while (sum > 0xffff)
173 		sum = (sum & 0xffff) + (sum >> 16);
174 	sum = ~sum & 0xffff;
175 
176 	return (sum);
177 }
178 #endif
179 
180 void
181 tcp_print(register const u_char *bp, register u_int length,
182 	  register const u_char *bp2, int fragmented)
183 {
184 	register const struct tcphdr *tp;
185 	register const struct ip *ip;
186 	register u_char flags;
187 	register int hlen;
188 	register char ch;
189 	u_int16_t sport, dport, win, urp;
190 	u_int32_t seq, ack, thseq, thack;
191 	int threv;
192 #ifdef INET6
193 	register const struct ip6_hdr *ip6;
194 #endif
195 
196 	tp = (struct tcphdr *)bp;
197 	ip = (struct ip *)bp2;
198 #ifdef INET6
199 	if (IP_V(ip) == 6)
200 		ip6 = (struct ip6_hdr *)bp2;
201 	else
202 		ip6 = NULL;
203 #endif /*INET6*/
204 	ch = '\0';
205 	if (!TTEST(tp->th_dport)) {
206 		(void)printf("%s > %s: [|tcp]",
207 			ipaddr_string(&ip->ip_src),
208 			ipaddr_string(&ip->ip_dst));
209 		return;
210 	}
211 
212 	sport = ntohs(tp->th_sport);
213 	dport = ntohs(tp->th_dport);
214 
215 	hlen = TH_OFF(tp) * 4;
216 
217 	/*
218 	 * If data present and NFS port used, assume NFS.
219 	 * Pass offset of data plus 4 bytes for RPC TCP msg length
220 	 * to NFS print routines.
221 	 */
222 	if (!qflag) {
223 		if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend &&
224 		    dport == NFS_PORT) {
225 			nfsreq_print((u_char *)tp + hlen + 4, length - hlen,
226 				     (u_char *)ip);
227 			return;
228 		} else if ((u_char *)tp + 4 + sizeof(struct rpc_msg)
229 			   <= snapend &&
230 			   sport == NFS_PORT) {
231 			nfsreply_print((u_char *)tp + hlen + 4, length - hlen,
232 				       (u_char *)ip);
233 			return;
234 		}
235 	}
236 #ifdef INET6
237 	if (ip6) {
238 		if (ip6->ip6_nxt == IPPROTO_TCP) {
239 			(void)printf("%s.%s > %s.%s: ",
240 				ip6addr_string(&ip6->ip6_src),
241 				tcpport_string(sport),
242 				ip6addr_string(&ip6->ip6_dst),
243 				tcpport_string(dport));
244 		} else {
245 			(void)printf("%s > %s: ",
246 				tcpport_string(sport), tcpport_string(dport));
247 		}
248 	} else
249 #endif /*INET6*/
250 	{
251 		if (ip->ip_p == IPPROTO_TCP) {
252 			(void)printf("%s.%s > %s.%s: ",
253 				ipaddr_string(&ip->ip_src),
254 				tcpport_string(sport),
255 				ipaddr_string(&ip->ip_dst),
256 				tcpport_string(dport));
257 		} else {
258 			(void)printf("%s > %s: ",
259 				tcpport_string(sport), tcpport_string(dport));
260 		}
261 	}
262 
263 	TCHECK(*tp);
264 
265 	seq = (u_int32_t)ntohl(tp->th_seq);
266 	ack = (u_int32_t)ntohl(tp->th_ack);
267 	win = ntohs(tp->th_win);
268 	urp = ntohs(tp->th_urp);
269 
270 	if (qflag) {
271 		(void)printf("tcp %d", length - TH_OFF(tp) * 4);
272 		return;
273 	}
274 	if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH|
275 				      TH_ECNECHO|TH_CWR)) {
276 		if (flags & TH_SYN)
277 			putchar('S');
278 		if (flags & TH_FIN)
279 			putchar('F');
280 		if (flags & TH_RST)
281 			putchar('R');
282 		if (flags & TH_PUSH)
283 			putchar('P');
284 		if (flags & TH_CWR)
285 			putchar('W');	/* congestion _W_indow reduced (ECN) */
286 		if (flags & TH_ECNECHO)
287 			putchar('E');	/* ecn _E_cho sent (ECN) */
288 	} else
289 		putchar('.');
290 
291 	if (!Sflag && (flags & TH_ACK)) {
292 		register struct tcp_seq_hash *th;
293 		register int rev;
294 		struct tha tha;
295 		/*
296 		 * Find (or record) the initial sequence numbers for
297 		 * this conversation.  (we pick an arbitrary
298 		 * collating order so there's only one entry for
299 		 * both directions).
300 		 */
301 #ifdef INET6
302 		memset(&tha, 0, sizeof(tha));
303 		rev = 0;
304 		if (ip6) {
305 			if (sport > dport)
306 				rev = 1;
307 			else if (sport == dport) {
308 				int i;
309 
310 				for (i = 0; i < 4; i++) {
311 					if (((u_int32_t *)(&ip6->ip6_src))[i] >
312 					    ((u_int32_t *)(&ip6->ip6_dst))[i]) {
313 						rev = 1;
314 						break;
315 					}
316 				}
317 			}
318 			if (rev) {
319 				tha.src = ip6->ip6_dst;
320 				tha.dst = ip6->ip6_src;
321 				tha.port = dport << 16 | sport;
322 			} else {
323 				tha.dst = ip6->ip6_dst;
324 				tha.src = ip6->ip6_src;
325 				tha.port = sport << 16 | dport;
326 			}
327 		} else {
328 			if (sport > dport ||
329 			    (sport == dport &&
330 			     ip->ip_src.s_addr > ip->ip_dst.s_addr)) {
331 				rev = 1;
332 			}
333 			if (rev) {
334 				*(struct in_addr *)&tha.src = ip->ip_dst;
335 				*(struct in_addr *)&tha.dst = ip->ip_src;
336 				tha.port = dport << 16 | sport;
337 			} else {
338 				*(struct in_addr *)&tha.dst = ip->ip_dst;
339 				*(struct in_addr *)&tha.src = ip->ip_src;
340 				tha.port = sport << 16 | dport;
341 			}
342 		}
343 #else
344 		if (sport < dport ||
345 		    (sport == dport &&
346 		     ip->ip_src.s_addr < ip->ip_dst.s_addr)) {
347 			tha.src = ip->ip_src, tha.dst = ip->ip_dst;
348 			tha.port = sport << 16 | dport;
349 			rev = 0;
350 		} else {
351 			tha.src = ip->ip_dst, tha.dst = ip->ip_src;
352 			tha.port = dport << 16 | sport;
353 			rev = 1;
354 		}
355 #endif
356 
357 		threv = rev;
358 		for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
359 		     th->nxt; th = th->nxt)
360 			if (!memcmp((char *)&tha, (char *)&th->addr,
361 				  sizeof(th->addr)))
362 				break;
363 
364 		if (!th->nxt || (flags & TH_SYN)) {
365 			/* didn't find it or new conversation */
366 			if (th->nxt == NULL) {
367 				th->nxt = (struct tcp_seq_hash *)
368 					calloc(1, sizeof(*th));
369 				if (th->nxt == NULL)
370 					error("tcp_print: calloc");
371 			}
372 			th->addr = tha;
373 			if (rev)
374 				th->ack = seq, th->seq = ack - 1;
375 			else
376 				th->seq = seq, th->ack = ack - 1;
377 		} else {
378 			if (rev)
379 				seq -= th->ack, ack -= th->seq;
380 			else
381 				seq -= th->seq, ack -= th->ack;
382 		}
383 
384 		thseq = th->seq;
385 		thack = th->ack;
386 	} else {
387 		/*fool gcc*/
388 		thseq = thack = threv = 0;
389 	}
390 	if (hlen > length) {
391 		(void)printf(" [bad hdr length]");
392 		return;
393 	}
394 
395 	if (IP_V(ip) == 4 && vflag && !fragmented) {
396 		int sum;
397 		if (TTEST2(tp->th_sport, length)) {
398 			sum = tcp_cksum(ip, tp, length);
399 			if (sum != 0)
400 				(void)printf(" [bad tcp cksum %x!]", sum);
401 			else
402 				(void)printf(" [tcp sum ok]");
403 		}
404 	}
405 #ifdef INET6
406 	if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !fragmented) {
407 		int sum;
408 		if (TTEST2(tp->th_sport, length)) {
409 			sum = tcp6_cksum(ip6, tp, length);
410 			if (sum != 0)
411 				(void)printf(" [bad tcp cksum %x!]", sum);
412 			else
413 				(void)printf(" [tcp sum ok]");
414 		}
415 	}
416 #endif
417 
418 	length -= hlen;
419 	if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST))
420 		(void)printf(" %u:%u(%u)", seq, seq + length, length);
421 	if (flags & TH_ACK)
422 		(void)printf(" ack %u", ack);
423 
424 	(void)printf(" win %d", win);
425 
426 	if (flags & TH_URG)
427 		(void)printf(" urg %d", urp);
428 	/*
429 	 * Handle any options.
430 	 */
431 	if ((hlen -= sizeof(*tp)) > 0) {
432 		register const u_char *cp;
433 		register int i, opt, len, datalen;
434 
435 		cp = (const u_char *)tp + sizeof(*tp);
436 		putchar(' ');
437 		ch = '<';
438 		while (hlen > 0) {
439 			putchar(ch);
440 			TCHECK(*cp);
441 			opt = *cp++;
442 			if (ZEROLENOPT(opt))
443 				len = 1;
444 			else {
445 				TCHECK(*cp);
446 				len = *cp++;	/* total including type, len */
447 				if (len < 2 || len > hlen)
448 					goto bad;
449 				--hlen;		/* account for length byte */
450 			}
451 			--hlen;			/* account for type byte */
452 			datalen = 0;
453 
454 /* Bail if "l" bytes of data are not left or were not captured  */
455 #define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); }
456 
457 			switch (opt) {
458 
459 			case TCPOPT_MAXSEG:
460 				(void)printf("mss");
461 				datalen = 2;
462 				LENCHECK(datalen);
463 				(void)printf(" %u", EXTRACT_16BITS(cp));
464 
465 				break;
466 
467 			case TCPOPT_EOL:
468 				(void)printf("eol");
469 				break;
470 
471 			case TCPOPT_NOP:
472 				(void)printf("nop");
473 				break;
474 
475 			case TCPOPT_WSCALE:
476 				(void)printf("wscale");
477 				datalen = 1;
478 				LENCHECK(datalen);
479 				(void)printf(" %u", *cp);
480 				break;
481 
482 			case TCPOPT_SACKOK:
483 				(void)printf("sackOK");
484 				break;
485 
486 			case TCPOPT_SACK:
487 				(void)printf("sack");
488 				datalen = len - 2;
489 				if (datalen % 8 != 0) {
490 					(void)printf(" malformed sack ");
491 				} else {
492 					u_int32_t s, e;
493 
494 					(void)printf(" sack %d ", datalen / 8);
495 					for (i = 0; i < datalen; i += 8) {
496 						LENCHECK(i + 4);
497 						s = EXTRACT_32BITS(cp + i);
498 						LENCHECK(i + 8);
499 						e = EXTRACT_32BITS(cp + i + 4);
500 						if (threv) {
501 							s -= thseq;
502 							e -= thseq;
503 						} else {
504 							s -= thack;
505 							e -= thack;
506 						}
507 						(void)printf("{%u:%u}", s, e);
508 					}
509 					(void)printf(" ");
510 				}
511 				break;
512 
513 			case TCPOPT_ECHO:
514 				(void)printf("echo");
515 				datalen = 4;
516 				LENCHECK(datalen);
517 				(void)printf(" %u", EXTRACT_32BITS(cp));
518 				break;
519 
520 			case TCPOPT_ECHOREPLY:
521 				(void)printf("echoreply");
522 				datalen = 4;
523 				LENCHECK(datalen);
524 				(void)printf(" %u", EXTRACT_32BITS(cp));
525 				break;
526 
527 			case TCPOPT_TIMESTAMP:
528 				(void)printf("timestamp");
529 				datalen = 8;
530 				LENCHECK(4);
531 				(void)printf(" %u", EXTRACT_32BITS(cp));
532 				LENCHECK(datalen);
533 				(void)printf(" %u", EXTRACT_32BITS(cp + 4));
534 				break;
535 
536 			case TCPOPT_CC:
537 				(void)printf("cc");
538 				datalen = 4;
539 				LENCHECK(datalen);
540 				(void)printf(" %u", EXTRACT_32BITS(cp));
541 				break;
542 
543 			case TCPOPT_CCNEW:
544 				(void)printf("ccnew");
545 				datalen = 4;
546 				LENCHECK(datalen);
547 				(void)printf(" %u", EXTRACT_32BITS(cp));
548 				break;
549 
550 			case TCPOPT_CCECHO:
551 				(void)printf("ccecho");
552 				datalen = 4;
553 				LENCHECK(datalen);
554 				(void)printf(" %u", EXTRACT_32BITS(cp));
555 				break;
556 
557 			default:
558 				(void)printf("opt-%d:", opt);
559 				datalen = len - 2;
560 				for (i = 0; i < datalen; ++i) {
561 					LENCHECK(i);
562 					(void)printf("%02x", cp[i]);
563 				}
564 				break;
565 			}
566 
567 			/* Account for data printed */
568 			cp += datalen;
569 			hlen -= datalen;
570 
571 			/* Check specification against observed length */
572 			++datalen;			/* option octet */
573 			if (!ZEROLENOPT(opt))
574 				++datalen;		/* size octet */
575 			if (datalen != len)
576 				(void)printf("[len %d]", len);
577 			ch = ',';
578 			if (opt == TCPOPT_EOL)
579 				break;
580 		}
581 		putchar('>');
582 	}
583 
584 	if (length <= 0)
585 		return;
586 
587 	/*
588 	 * Decode payload if necessary.
589 	 */
590 	bp += TH_OFF(tp) * 4;
591 	if (flags & TH_RST) {
592 		if (vflag)
593 			print_tcp_rst_data(bp, length);
594 	} else {
595 		if (sport == TELNET_PORT || dport == TELNET_PORT) {
596 			if (!qflag && vflag)
597 				telnet_print(bp, length);
598 		} else if (sport == BGP_PORT || dport == BGP_PORT)
599 			bgp_print(bp, length);
600 		else if (sport == PPTP_PORT || dport == PPTP_PORT)
601 			pptp_print(bp, length);
602 #ifdef TCPDUMP_DO_SMB
603 		else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT)
604 			nbt_tcp_print(bp, length);
605 #endif
606 		else if (sport == BEEP_PORT || dport == BEEP_PORT)
607 			beep_print(bp, length);
608 		else if (length > 2 &&
609 		    (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT)) {
610 			/*
611 			 * TCP DNS query has 2byte length at the head.
612 			 * XXX packet could be unaligned, it can go strange
613 			 */
614 			ns_print(bp + 2, length - 2);
615 		} else if (sport == MSDP_PORT || dport == MSDP_PORT) {
616 			msdp_print(bp, length);
617 		}
618 	}
619 	return;
620 bad:
621 	fputs("[bad opt]", stdout);
622 	if (ch != '\0')
623 		putchar('>');
624 	return;
625 trunc:
626 	fputs("[|tcp]", stdout);
627 	if (ch != '\0')
628 		putchar('>');
629 }
630 
631 /*
632  * RFC1122 says the following on data in RST segments:
633  *
634  *         4.2.2.12  RST Segment: RFC-793 Section 3.4
635  *
636  *            A TCP SHOULD allow a received RST segment to include data.
637  *
638  *            DISCUSSION
639  *                 It has been suggested that a RST segment could contain
640  *                 ASCII text that encoded and explained the cause of the
641  *                 RST.  No standard has yet been established for such
642  *                 data.
643  *
644  */
645 
646 static void
647 print_tcp_rst_data(register const u_char *sp, u_int length)
648 {
649 	int c;
650 
651 	if (TTEST2(*sp, length))
652 		printf(" [RST");
653 	else
654 		printf(" [!RST");
655 	if (length > MAX_RST_DATA_LEN) {
656 		length = MAX_RST_DATA_LEN;	/* can use -X for longer */
657 		putchar('+');			/* indicate we truncate */
658 	}
659 	putchar(' ');
660 	while (length-- && sp <= snapend) {
661 		c = *sp++;
662 		safeputchar(c);
663 	}
664 	putchar(']');
665 }
666