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