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