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