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