1 /* $OpenBSD: print-tcp.c,v 1.29 2014/02/05 21:12:19 florian 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/param.h> 25 #include <sys/time.h> 26 #include <sys/socket.h> 27 28 #include <netinet/in.h> 29 #include <netinet/in_systm.h> 30 #include <netinet/ip.h> 31 #include <netinet/ip_var.h> 32 #include <netinet/tcp.h> 33 #include <netinet/tcpip.h> 34 #include <net/if.h> 35 #include <net/pfvar.h> 36 37 #include <rpc/rpc.h> 38 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 44 #ifdef INET6 45 #include <netinet/ip6.h> 46 #endif 47 48 #include "interface.h" 49 #include "addrtoname.h" 50 #include "extract.h" 51 52 #include "nfs.h" 53 54 static void print_tcp_rst_data(register const u_char *sp, u_int length); 55 56 #define MAX_RST_DATA_LEN 30 57 58 /* Compatibility */ 59 #ifndef TCPOPT_WSCALE 60 #define TCPOPT_WSCALE 3 /* window scale factor (rfc1072) */ 61 #endif 62 #ifndef TCPOPT_SACKOK 63 #define TCPOPT_SACKOK 4 /* selective ack ok (rfc2018) */ 64 #endif 65 #ifndef TCPOPT_SACK 66 #define TCPOPT_SACK 5 /* selective ack (rfc2018) */ 67 #endif 68 #ifndef TCPOLEN_SACK 69 #define TCPOLEN_SACK 8 /* length of a SACK block */ 70 #endif 71 #ifndef TCPOPT_ECHO 72 #define TCPOPT_ECHO 6 /* echo (rfc1072) */ 73 #endif 74 #ifndef TCPOPT_ECHOREPLY 75 #define TCPOPT_ECHOREPLY 7 /* echo (rfc1072) */ 76 #endif 77 #ifndef TCPOPT_TIMESTAMP 78 #define TCPOPT_TIMESTAMP 8 /* timestamps (rfc1323) */ 79 #endif 80 #ifndef TCPOPT_CC 81 #define TCPOPT_CC 11 /* T/TCP CC options (rfc1644) */ 82 #endif 83 #ifndef TCPOPT_CCNEW 84 #define TCPOPT_CCNEW 12 /* T/TCP CC options (rfc1644) */ 85 #endif 86 #ifndef TCPOPT_CCECHO 87 #define TCPOPT_CCECHO 13 /* T/TCP CC options (rfc1644) */ 88 #endif 89 90 /* Definitions required for ECN 91 for use if the OS running tcpdump does not have ECN */ 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 #ifndef BGP_PORT 125 #define BGP_PORT 179 126 #endif 127 #define NETBIOS_SSN_PORT 139 128 129 static int tcp_cksum(const struct ip *ip, const struct tcphdr *tp, int len) 130 { 131 union phu { 132 struct phdr { 133 u_int32_t src; 134 u_int32_t dst; 135 u_char mbz; 136 u_char proto; 137 u_int16_t len; 138 } ph; 139 u_int16_t pa[6]; 140 } phu; 141 const u_int16_t *sp; 142 u_int32_t sum; 143 144 /* pseudo-header.. */ 145 phu.ph.len = htons((u_int16_t)len); 146 phu.ph.mbz = 0; 147 phu.ph.proto = IPPROTO_TCP; 148 memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); 149 memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); 150 151 sp = &phu.pa[0]; 152 sum = sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]; 153 154 return in_cksum((u_short *)tp, len, sum); 155 } 156 157 #ifdef INET6 158 static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp, 159 u_int len) 160 { 161 union { 162 struct { 163 struct in6_addr ph_src; 164 struct in6_addr ph_dst; 165 u_int32_t ph_len; 166 u_int8_t ph_zero[3]; 167 u_int8_t ph_nxt; 168 } ph; 169 u_int16_t pa[20]; 170 } phu; 171 size_t i; 172 u_int32_t sum = 0; 173 174 /* pseudo-header */ 175 memset(&phu, 0, sizeof(phu)); 176 phu.ph.ph_src = ip6->ip6_src; 177 phu.ph.ph_dst = ip6->ip6_dst; 178 phu.ph.ph_len = htonl(len); 179 phu.ph.ph_nxt = IPPROTO_TCP; 180 181 for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) 182 sum += phu.pa[i]; 183 184 return in_cksum((u_short *)tp, len, sum); 185 } 186 #endif 187 188 189 void 190 tcp_print(register const u_char *bp, register u_int length, 191 register const u_char *bp2) 192 { 193 register const struct tcphdr *tp; 194 register const struct ip *ip; 195 register u_char flags; 196 register int hlen; 197 register char ch; 198 register struct tcp_seq_hash *th = NULL; 199 register int rev = 0; 200 u_int16_t sport, dport, win, urp; 201 tcp_seq seq, ack; 202 #ifdef INET6 203 register 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 %d", 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 = (struct tcp_seq_hash *) 399 calloc(1, sizeof(*th)); 400 if (th->nxt == NULL) 401 error("tcp_print: calloc"); 402 } 403 th->addr = tha; 404 if (rev) 405 th->ack = seq, th->seq = ack - 1; 406 else 407 th->seq = seq, th->ack = ack - 1; 408 } else { 409 if (rev) 410 seq -= th->ack, ack -= th->seq; 411 else 412 seq -= th->seq, ack -= th->ack; 413 } 414 } 415 hlen = tp->th_off * 4; 416 if (hlen > length) { 417 (void)printf(" [bad hdr length]"); 418 return; 419 } 420 421 if (ip && ip->ip_v == 4 && vflag) { 422 int sum; 423 if (TTEST2(tp->th_sport, length)) { 424 sum = tcp_cksum(ip, tp, length); 425 if (sum != 0) 426 (void)printf(" [bad tcp cksum %x!]", sum); 427 else 428 (void)printf(" [tcp sum ok]"); 429 } 430 } 431 #ifdef INET6 432 if (ip6 && ip6->ip6_plen && vflag) { 433 int sum; 434 if (TTEST2(tp->th_sport, length)) { 435 sum = tcp6_cksum(ip6, tp, length); 436 if (sum != 0) 437 (void)printf(" [bad tcp cksum %x!]", sum); 438 else 439 (void)printf(" [tcp sum ok]"); 440 } 441 } 442 #endif 443 444 /* OS Fingerprint */ 445 if (oflag && (flags & (TH_SYN|TH_ACK)) == TH_SYN) { 446 struct pf_osfp_enlist *head = NULL; 447 struct pf_osfp_entry *fp; 448 unsigned long left; 449 left = (unsigned long)(snapend - (const u_char *)tp); 450 451 if (left >= hlen) 452 head = pf_osfp_fingerprint_hdr(ip, ip6, tp); 453 if (head) { 454 int prev = 0; 455 printf(" (src OS:"); 456 SLIST_FOREACH(fp, head, fp_entry) { 457 if (fp->fp_enflags & PF_OSFP_EXPANDED) 458 continue; 459 if (prev) 460 printf(","); 461 printf(" %s", fp->fp_class_nm); 462 if (fp->fp_version_nm[0]) 463 printf(" %s", fp->fp_version_nm); 464 if (fp->fp_subtype_nm[0]) 465 printf(" %s", fp->fp_subtype_nm); 466 prev = 1; 467 } 468 printf(")"); 469 } else { 470 if (left < hlen) 471 printf(" (src OS: short-pkt)"); 472 else 473 printf(" (src OS: unknown)"); 474 } 475 } 476 477 length -= hlen; 478 if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) 479 (void)printf(" %lu:%lu(%d)", (long) seq, (long) (seq + length), 480 length); 481 if (flags & TH_ACK) 482 (void)printf(" ack %u", ack); 483 484 (void)printf(" win %d", win); 485 486 if (flags & TH_URG) 487 (void)printf(" urg %d", urp); 488 /* 489 * Handle any options. 490 */ 491 if ((hlen -= sizeof(*tp)) > 0) { 492 register const u_char *cp; 493 register int i, opt, len, datalen; 494 495 cp = (const u_char *)tp + sizeof(*tp); 496 putchar(' '); 497 ch = '<'; 498 while (hlen > 0) { 499 putchar(ch); 500 TCHECK(*cp); 501 opt = *cp++; 502 if (ZEROLENOPT(opt)) 503 len = 1; 504 else { 505 TCHECK(*cp); 506 len = *cp++; /* total including type, len */ 507 if (len < 2 || len > hlen) 508 goto bad; 509 --hlen; /* account for length byte */ 510 } 511 --hlen; /* account for type byte */ 512 datalen = 0; 513 514 /* Bail if "l" bytes of data are not left or were not captured */ 515 #define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); } 516 517 switch (opt) { 518 519 case TCPOPT_MAXSEG: 520 (void)printf("mss"); 521 datalen = 2; 522 LENCHECK(datalen); 523 (void)printf(" %u", EXTRACT_16BITS(cp)); 524 525 break; 526 527 case TCPOPT_EOL: 528 (void)printf("eol"); 529 break; 530 531 case TCPOPT_NOP: 532 (void)printf("nop"); 533 break; 534 535 case TCPOPT_WSCALE: 536 (void)printf("wscale"); 537 datalen = 1; 538 LENCHECK(datalen); 539 (void)printf(" %u", *cp); 540 break; 541 542 case TCPOPT_SACKOK: 543 (void)printf("sackOK"); 544 if (len != 2) 545 (void)printf("[len %d]", len); 546 break; 547 548 case TCPOPT_SACK: 549 { 550 u_long s, e; 551 552 datalen = len - 2; 553 if ((datalen % TCPOLEN_SACK) != 0 || 554 !(flags & TH_ACK)) { 555 (void)printf("malformed sack "); 556 (void)printf("[len %d] ", datalen); 557 break; 558 } 559 printf("sack %d ", datalen/TCPOLEN_SACK); 560 for (i = 0; i < datalen; i += TCPOLEN_SACK) { 561 LENCHECK (i + TCPOLEN_SACK); 562 s = EXTRACT_32BITS(cp + i); 563 e = EXTRACT_32BITS(cp + i + 4); 564 if (!Sflag) { 565 if (rev) { 566 s -= th->seq; 567 e -= th->seq; 568 } else { 569 s -= th->ack; 570 e -= th->ack; 571 } 572 } 573 (void) printf("{%lu:%lu} ", s, e); 574 } 575 break; 576 } 577 case TCPOPT_ECHO: 578 (void)printf("echo"); 579 datalen = 4; 580 LENCHECK(datalen); 581 (void)printf(" %u", EXTRACT_32BITS(cp)); 582 break; 583 584 case TCPOPT_ECHOREPLY: 585 (void)printf("echoreply"); 586 datalen = 4; 587 LENCHECK(datalen); 588 (void)printf(" %u", EXTRACT_32BITS(cp)); 589 break; 590 591 case TCPOPT_TIMESTAMP: 592 (void)printf("timestamp"); 593 datalen = 8; 594 LENCHECK(4); 595 (void)printf(" %u", EXTRACT_32BITS(cp)); 596 LENCHECK(datalen); 597 (void)printf(" %u", EXTRACT_32BITS(cp + 4)); 598 break; 599 600 case TCPOPT_CC: 601 (void)printf("cc"); 602 datalen = 4; 603 LENCHECK(datalen); 604 (void)printf(" %u", EXTRACT_32BITS(cp)); 605 break; 606 607 case TCPOPT_CCNEW: 608 (void)printf("ccnew"); 609 datalen = 4; 610 LENCHECK(datalen); 611 (void)printf(" %u", EXTRACT_32BITS(cp)); 612 break; 613 614 case TCPOPT_CCECHO: 615 (void)printf("ccecho"); 616 datalen = 4; 617 LENCHECK(datalen); 618 (void)printf(" %u", EXTRACT_32BITS(cp)); 619 break; 620 621 case TCPOPT_SIGNATURE: 622 (void)printf("tcpmd5:"); 623 datalen = len - 2; 624 for (i = 0; i < datalen; ++i) { 625 LENCHECK(i+1); 626 (void)printf("%02x", cp[i]); 627 } 628 break; 629 630 default: 631 (void)printf("opt-%d:", opt); 632 datalen = len - 2; 633 for (i = 0; i < datalen; ++i) { 634 LENCHECK(i+1); 635 (void)printf("%02x", cp[i]); 636 } 637 break; 638 } 639 640 /* Account for data printed */ 641 cp += datalen; 642 hlen -= datalen; 643 644 /* Check specification against observed length */ 645 ++datalen; /* option octet */ 646 if (!ZEROLENOPT(opt)) 647 ++datalen; /* size octet */ 648 if (datalen != len) 649 (void)printf("[len %d]", len); 650 ch = ','; 651 if (opt == TCPOPT_EOL) 652 break; 653 } 654 putchar('>'); 655 } 656 657 if (length <= 0) 658 return; 659 660 /* 661 * Decode payload if necessary. 662 */ 663 bp += (tp->th_off * 4); 664 if (flags & TH_RST) { 665 if (vflag) 666 print_tcp_rst_data(bp, length); 667 } else { 668 if (sport == BGP_PORT || dport == BGP_PORT) 669 bgp_print(bp, length); 670 #if 0 671 else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT) 672 nbt_tcp_print(bp, length); 673 #endif 674 } 675 return; 676 bad: 677 fputs("[bad opt]", stdout); 678 if (ch != '\0') 679 putchar('>'); 680 return; 681 trunc: 682 fputs("[|tcp]", stdout); 683 if (ch != '\0') 684 putchar('>'); 685 } 686 687 688 /* 689 * RFC1122 says the following on data in RST segments: 690 * 691 * 4.2.2.12 RST Segment: RFC-793 Section 3.4 692 * 693 * A TCP SHOULD allow a received RST segment to include data. 694 * 695 * DISCUSSION 696 * It has been suggested that a RST segment could contain 697 * ASCII text that encoded and explained the cause of the 698 * RST. No standard has yet been established for such 699 * data. 700 * 701 */ 702 703 static void 704 print_tcp_rst_data(register const u_char *sp, u_int length) 705 { 706 int c; 707 708 if (TTEST2(*sp, length)) 709 printf(" [RST"); 710 else 711 printf(" [!RST"); 712 if (length > MAX_RST_DATA_LEN) { 713 length = MAX_RST_DATA_LEN; /* can use -X for longer */ 714 putchar('+'); /* indicate we truncate */ 715 } 716 putchar(' '); 717 while (length-- && sp < snapend) { 718 c = *sp++; 719 safeputchar(c); 720 } 721 putchar(']'); 722 } 723