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