1 /* $OpenBSD: print-tcp.c,v 1.28 2010/01/12 06:10:33 naddy 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, 301 (u_char *)ip); 302 return; 303 } else if ((u_char *)tp + 4 + 304 sizeof(struct rpc_msg) <= snapend && sport == NFS_PORT) { 305 nfsreply_print((u_char *)tp + hlen + 4, len, 306 (u_char *)ip); 307 return; 308 } 309 } 310 if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH| 311 TH_ECNECHO|TH_CWR)) { 312 if (flags & TH_SYN) 313 putchar('S'); 314 if (flags & TH_FIN) 315 putchar('F'); 316 if (flags & TH_RST) 317 putchar('R'); 318 if (flags & TH_PUSH) 319 putchar('P'); 320 if (flags & TH_CWR) 321 putchar('W'); /* congestion _W_indow reduced (ECN) */ 322 if (flags & TH_ECNECHO) 323 putchar('E'); /* ecn _E_cho sent (ECN) */ 324 } else 325 putchar('.'); 326 327 if (!Sflag && (flags & TH_ACK)) { 328 struct tha tha; 329 /* 330 * Find (or record) the initial sequence numbers for 331 * this conversation. (we pick an arbitrary 332 * collating order so there's only one entry for 333 * both directions). 334 */ 335 #ifdef INET6 336 bzero(&tha, sizeof(tha)); 337 rev = 0; 338 if (ip6) { 339 if (sport > dport) { 340 rev = 1; 341 } else if (sport == dport) { 342 int i; 343 344 for (i = 0; i < 4; i++) { 345 if (((u_int32_t *)(&ip6->ip6_src))[i] > 346 ((u_int32_t *)(&ip6->ip6_dst))[i]) { 347 rev = 1; 348 break; 349 } 350 } 351 } 352 if (rev) { 353 tha.src = ip6->ip6_dst; 354 tha.dst = ip6->ip6_src; 355 tha.port = dport << 16 | sport; 356 } else { 357 tha.dst = ip6->ip6_dst; 358 tha.src = ip6->ip6_src; 359 tha.port = sport << 16 | dport; 360 } 361 } else { 362 if (sport > dport || 363 (sport == dport && 364 ip->ip_src.s_addr > ip->ip_dst.s_addr)) { 365 rev = 1; 366 } 367 if (rev) { 368 *(struct in_addr *)&tha.src = ip->ip_dst; 369 *(struct in_addr *)&tha.dst = ip->ip_src; 370 tha.port = dport << 16 | sport; 371 } else { 372 *(struct in_addr *)&tha.dst = ip->ip_dst; 373 *(struct in_addr *)&tha.src = ip->ip_src; 374 tha.port = sport << 16 | dport; 375 } 376 } 377 #else 378 if (sport < dport || 379 (sport == dport && 380 ip->ip_src.s_addr < ip->ip_dst.s_addr)) { 381 tha.src = ip->ip_src, tha.dst = ip->ip_dst; 382 tha.port = sport << 16 | dport; 383 rev = 0; 384 } else { 385 tha.src = ip->ip_dst, tha.dst = ip->ip_src; 386 tha.port = dport << 16 | sport; 387 rev = 1; 388 } 389 #endif 390 391 for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; 392 th->nxt; th = th->nxt) 393 if (!memcmp((char *)&tha, (char *)&th->addr, 394 sizeof(th->addr))) 395 break; 396 397 if (!th->nxt || flags & TH_SYN) { 398 /* didn't find it or new conversation */ 399 if (th->nxt == NULL) { 400 th->nxt = (struct tcp_seq_hash *) 401 calloc(1, sizeof(*th)); 402 if (th->nxt == NULL) 403 error("tcp_print: calloc"); 404 } 405 th->addr = tha; 406 if (rev) 407 th->ack = seq, th->seq = ack - 1; 408 else 409 th->seq = seq, th->ack = ack - 1; 410 } else { 411 if (rev) 412 seq -= th->ack, ack -= th->seq; 413 else 414 seq -= th->seq, ack -= th->ack; 415 } 416 } 417 hlen = tp->th_off * 4; 418 if (hlen > length) { 419 (void)printf(" [bad hdr length]"); 420 return; 421 } 422 423 if (ip && ip->ip_v == 4 && vflag) { 424 int sum; 425 if (TTEST2(tp->th_sport, length)) { 426 sum = tcp_cksum(ip, tp, length); 427 if (sum != 0) 428 (void)printf(" [bad tcp cksum %x!]", sum); 429 else 430 (void)printf(" [tcp sum ok]"); 431 } 432 } 433 #ifdef INET6 434 if (ip6 && ip6->ip6_plen && vflag) { 435 int sum; 436 if (TTEST2(tp->th_sport, length)) { 437 sum = tcp6_cksum(ip6, tp, length); 438 if (sum != 0) 439 (void)printf(" [bad tcp cksum %x!]", sum); 440 else 441 (void)printf(" [tcp sum ok]"); 442 } 443 } 444 #endif 445 446 /* OS Fingerprint */ 447 if (oflag && (flags & (TH_SYN|TH_ACK)) == TH_SYN) { 448 struct pf_osfp_enlist *head = NULL; 449 struct pf_osfp_entry *fp; 450 unsigned long left; 451 left = (unsigned long)(snapend - (const u_char *)tp); 452 453 if (left >= hlen) 454 head = pf_osfp_fingerprint_hdr(ip, ip6, tp); 455 if (head) { 456 int prev = 0; 457 printf(" (src OS:"); 458 SLIST_FOREACH(fp, head, fp_entry) { 459 if (fp->fp_enflags & PF_OSFP_EXPANDED) 460 continue; 461 if (prev) 462 printf(","); 463 printf(" %s", fp->fp_class_nm); 464 if (fp->fp_version_nm[0]) 465 printf(" %s", fp->fp_version_nm); 466 if (fp->fp_subtype_nm[0]) 467 printf(" %s", fp->fp_subtype_nm); 468 prev = 1; 469 } 470 printf(")"); 471 } else { 472 if (left < hlen) 473 printf(" (src OS: short-pkt)"); 474 else 475 printf(" (src OS: unknown)"); 476 } 477 } 478 479 length -= hlen; 480 if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) 481 (void)printf(" %lu:%lu(%d)", (long) seq, (long) (seq + length), 482 length); 483 if (flags & TH_ACK) 484 (void)printf(" ack %u", ack); 485 486 (void)printf(" win %d", win); 487 488 if (flags & TH_URG) 489 (void)printf(" urg %d", urp); 490 /* 491 * Handle any options. 492 */ 493 if ((hlen -= sizeof(*tp)) > 0) { 494 register const u_char *cp; 495 register 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 #if 0 673 else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT) 674 nbt_tcp_print(bp, length); 675 #endif 676 } 677 return; 678 bad: 679 fputs("[bad opt]", stdout); 680 if (ch != '\0') 681 putchar('>'); 682 return; 683 trunc: 684 fputs("[|tcp]", stdout); 685 if (ch != '\0') 686 putchar('>'); 687 } 688 689 690 /* 691 * RFC1122 says the following on data in RST segments: 692 * 693 * 4.2.2.12 RST Segment: RFC-793 Section 3.4 694 * 695 * A TCP SHOULD allow a received RST segment to include data. 696 * 697 * DISCUSSION 698 * It has been suggested that a RST segment could contain 699 * ASCII text that encoded and explained the cause of the 700 * RST. No standard has yet been established for such 701 * data. 702 * 703 */ 704 705 static void 706 print_tcp_rst_data(register const u_char *sp, u_int length) 707 { 708 int c; 709 710 if (TTEST2(*sp, length)) 711 printf(" [RST"); 712 else 713 printf(" [!RST"); 714 if (length > MAX_RST_DATA_LEN) { 715 length = MAX_RST_DATA_LEN; /* can use -X for longer */ 716 putchar('+'); /* indicate we truncate */ 717 } 718 putchar(' '); 719 while (length-- && sp < snapend) { 720 c = *sp++; 721 safeputchar(c); 722 } 723 putchar(']'); 724 } 725