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