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