1 /* NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky 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 * Copyright (c) 1999-2004 The tcpdump.org project 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that: (1) source code distributions 11 * retain the above copyright notice and this paragraph in its entirety, (2) 12 * distributions including binary code include the above copyright notice and 13 * this paragraph in its entirety in the documentation or other materials 14 * provided with the distribution, and (3) all advertising materials mentioning 15 * features or use of this software display the following acknowledgement: 16 * ``This product includes software developed by the University of California, 17 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 18 * the University nor the names of its contributors may be used to endorse 19 * or promote products derived from this software without specific prior 20 * written permission. 21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 22 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 24 */ 25 26 #include <sys/cdefs.h> 27 #ifndef lint 28 __RCSID("$NetBSD: print-tcp.c,v 1.7 2017/01/24 23:29:14 christos Exp $"); 29 #endif 30 31 #ifdef HAVE_CONFIG_H 32 #include "config.h" 33 #endif 34 35 #include <netdissect-stdinc.h> 36 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include "netdissect.h" 41 #include "addrtoname.h" 42 #include "extract.h" 43 44 #include "tcp.h" 45 46 #include "ip.h" 47 #include "ip6.h" 48 #include "ipproto.h" 49 #include "rpc_auth.h" 50 #include "rpc_msg.h" 51 52 #ifdef HAVE_LIBCRYPTO 53 #include <openssl/md5.h> 54 #include "signature.h" 55 56 static int tcp_verify_signature(netdissect_options *ndo, 57 const struct ip *ip, const struct tcphdr *tp, 58 const u_char *data, int length, const u_char *rcvsig); 59 #endif 60 61 static void print_tcp_rst_data(netdissect_options *, register const u_char *sp, u_int length); 62 static void print_tcp_fastopen_option(netdissect_options *ndo, register const u_char *cp, 63 u_int datalen, int exp); 64 65 #define MAX_RST_DATA_LEN 30 66 67 68 struct tha { 69 struct in_addr src; 70 struct in_addr dst; 71 u_int port; 72 }; 73 74 struct tcp_seq_hash { 75 struct tcp_seq_hash *nxt; 76 struct tha addr; 77 tcp_seq seq; 78 tcp_seq ack; 79 }; 80 81 struct tha6 { 82 struct in6_addr src; 83 struct in6_addr dst; 84 u_int port; 85 }; 86 87 struct tcp_seq_hash6 { 88 struct tcp_seq_hash6 *nxt; 89 struct tha6 addr; 90 tcp_seq seq; 91 tcp_seq ack; 92 }; 93 94 #define TSEQ_HASHSIZE 919 95 96 /* These tcp optinos do not have the size octet */ 97 #define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP) 98 99 static struct tcp_seq_hash tcp_seq_hash4[TSEQ_HASHSIZE]; 100 static struct tcp_seq_hash6 tcp_seq_hash6[TSEQ_HASHSIZE]; 101 102 static const struct tok tcp_flag_values[] = { 103 { TH_FIN, "F" }, 104 { TH_SYN, "S" }, 105 { TH_RST, "R" }, 106 { TH_PUSH, "P" }, 107 { TH_ACK, "." }, 108 { TH_URG, "U" }, 109 { TH_ECNECHO, "E" }, 110 { TH_CWR, "W" }, 111 { 0, NULL } 112 }; 113 114 static const struct tok tcp_option_values[] = { 115 { TCPOPT_EOL, "eol" }, 116 { TCPOPT_NOP, "nop" }, 117 { TCPOPT_MAXSEG, "mss" }, 118 { TCPOPT_WSCALE, "wscale" }, 119 { TCPOPT_SACKOK, "sackOK" }, 120 { TCPOPT_SACK, "sack" }, 121 { TCPOPT_ECHO, "echo" }, 122 { TCPOPT_ECHOREPLY, "echoreply" }, 123 { TCPOPT_TIMESTAMP, "TS" }, 124 { TCPOPT_CC, "cc" }, 125 { TCPOPT_CCNEW, "ccnew" }, 126 { TCPOPT_CCECHO, "" }, 127 { TCPOPT_SIGNATURE, "md5" }, 128 { TCPOPT_AUTH, "enhanced auth" }, 129 { TCPOPT_UTO, "uto" }, 130 { TCPOPT_MPTCP, "mptcp" }, 131 { TCPOPT_FASTOPEN, "tfo" }, 132 { TCPOPT_EXPERIMENT2, "exp" }, 133 { 0, NULL } 134 }; 135 136 static int 137 tcp_cksum(netdissect_options *ndo, 138 register const struct ip *ip, 139 register const struct tcphdr *tp, 140 register u_int len) 141 { 142 return nextproto4_cksum(ndo, ip, (const uint8_t *)tp, len, len, 143 IPPROTO_TCP); 144 } 145 146 static int 147 tcp6_cksum(netdissect_options *ndo, 148 register const struct ip6_hdr *ip6, 149 register const struct tcphdr *tp, 150 register u_int len) 151 { 152 return nextproto6_cksum(ndo, ip6, (const uint8_t *)tp, len, len, 153 IPPROTO_TCP); 154 } 155 156 void 157 tcp_print(netdissect_options *ndo, 158 register const u_char *bp, register u_int length, 159 register const u_char *bp2, int fragmented) 160 { 161 register const struct tcphdr *tp; 162 register const struct ip *ip; 163 register u_char flags; 164 register u_int hlen; 165 register char ch; 166 uint16_t sport, dport, win, urp; 167 uint32_t seq, ack, thseq, thack; 168 u_int utoval; 169 uint16_t magic; 170 register int rev; 171 register const struct ip6_hdr *ip6; 172 173 tp = (const struct tcphdr *)bp; 174 ip = (const struct ip *)bp2; 175 if (IP_V(ip) == 6) 176 ip6 = (const struct ip6_hdr *)bp2; 177 else 178 ip6 = NULL; 179 ch = '\0'; 180 if (!ND_TTEST(tp->th_dport)) { 181 ND_PRINT((ndo, "%s > %s: [|tcp]", 182 ipaddr_string(ndo, &ip->ip_src), 183 ipaddr_string(ndo, &ip->ip_dst))); 184 return; 185 } 186 187 sport = EXTRACT_16BITS(&tp->th_sport); 188 dport = EXTRACT_16BITS(&tp->th_dport); 189 190 hlen = TH_OFF(tp) * 4; 191 192 if (ip6) { 193 if (ip6->ip6_nxt == IPPROTO_TCP) { 194 ND_PRINT((ndo, "%s.%s > %s.%s: ", 195 ip6addr_string(ndo, &ip6->ip6_src), 196 tcpport_string(ndo, sport), 197 ip6addr_string(ndo, &ip6->ip6_dst), 198 tcpport_string(ndo, dport))); 199 } else { 200 ND_PRINT((ndo, "%s > %s: ", 201 tcpport_string(ndo, sport), tcpport_string(ndo, dport))); 202 } 203 } else { 204 if (ip->ip_p == IPPROTO_TCP) { 205 ND_PRINT((ndo, "%s.%s > %s.%s: ", 206 ipaddr_string(ndo, &ip->ip_src), 207 tcpport_string(ndo, sport), 208 ipaddr_string(ndo, &ip->ip_dst), 209 tcpport_string(ndo, dport))); 210 } else { 211 ND_PRINT((ndo, "%s > %s: ", 212 tcpport_string(ndo, sport), tcpport_string(ndo, dport))); 213 } 214 } 215 216 if (hlen < sizeof(*tp)) { 217 ND_PRINT((ndo, " tcp %d [bad hdr length %u - too short, < %lu]", 218 length - hlen, hlen, (unsigned long)sizeof(*tp))); 219 return; 220 } 221 222 ND_TCHECK(*tp); 223 224 seq = EXTRACT_32BITS(&tp->th_seq); 225 ack = EXTRACT_32BITS(&tp->th_ack); 226 win = EXTRACT_16BITS(&tp->th_win); 227 urp = EXTRACT_16BITS(&tp->th_urp); 228 229 if (ndo->ndo_qflag) { 230 ND_PRINT((ndo, "tcp %d", length - hlen)); 231 if (hlen > length) { 232 ND_PRINT((ndo, " [bad hdr length %u - too long, > %u]", 233 hlen, length)); 234 } 235 return; 236 } 237 238 flags = tp->th_flags; 239 ND_PRINT((ndo, "Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags))); 240 241 if (!ndo->ndo_Sflag && (flags & TH_ACK)) { 242 /* 243 * Find (or record) the initial sequence numbers for 244 * this conversation. (we pick an arbitrary 245 * collating order so there's only one entry for 246 * both directions). 247 */ 248 rev = 0; 249 if (ip6) { 250 register struct tcp_seq_hash6 *th; 251 struct tcp_seq_hash6 *tcp_seq_hash; 252 const struct in6_addr *src, *dst; 253 struct tha6 tha; 254 255 tcp_seq_hash = tcp_seq_hash6; 256 src = &ip6->ip6_src; 257 dst = &ip6->ip6_dst; 258 if (sport > dport) 259 rev = 1; 260 else if (sport == dport) { 261 if (UNALIGNED_MEMCMP(src, dst, sizeof ip6->ip6_dst) > 0) 262 rev = 1; 263 } 264 if (rev) { 265 UNALIGNED_MEMCPY(&tha.src, dst, sizeof ip6->ip6_dst); 266 UNALIGNED_MEMCPY(&tha.dst, src, sizeof ip6->ip6_src); 267 tha.port = dport << 16 | sport; 268 } else { 269 UNALIGNED_MEMCPY(&tha.dst, dst, sizeof ip6->ip6_dst); 270 UNALIGNED_MEMCPY(&tha.src, src, sizeof ip6->ip6_src); 271 tha.port = sport << 16 | dport; 272 } 273 274 for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; 275 th->nxt; th = th->nxt) 276 if (memcmp((char *)&tha, (char *)&th->addr, 277 sizeof(th->addr)) == 0) 278 break; 279 280 if (!th->nxt || (flags & TH_SYN)) { 281 /* didn't find it or new conversation */ 282 if (th->nxt == NULL) { 283 th->nxt = (struct tcp_seq_hash6 *) 284 calloc(1, sizeof(*th)); 285 if (th->nxt == NULL) 286 (*ndo->ndo_error)(ndo, 287 "tcp_print: calloc"); 288 } 289 th->addr = tha; 290 if (rev) 291 th->ack = seq, th->seq = ack - 1; 292 else 293 th->seq = seq, th->ack = ack - 1; 294 } else { 295 if (rev) 296 seq -= th->ack, ack -= th->seq; 297 else 298 seq -= th->seq, ack -= th->ack; 299 } 300 301 thseq = th->seq; 302 thack = th->ack; 303 } else { 304 register struct tcp_seq_hash *th; 305 struct tcp_seq_hash *tcp_seq_hash; 306 struct tha tha; 307 308 tcp_seq_hash = tcp_seq_hash4; 309 if (sport > dport) 310 rev = 1; 311 else if (sport == dport) { 312 if (UNALIGNED_MEMCMP(&ip->ip_src, &ip->ip_dst, sizeof ip->ip_dst) > 0) 313 rev = 1; 314 } 315 if (rev) { 316 UNALIGNED_MEMCPY(&tha.src, &ip->ip_dst, sizeof ip->ip_dst); 317 UNALIGNED_MEMCPY(&tha.dst, &ip->ip_src, sizeof ip->ip_src); 318 tha.port = dport << 16 | sport; 319 } else { 320 UNALIGNED_MEMCPY(&tha.dst, &ip->ip_dst, sizeof ip->ip_dst); 321 UNALIGNED_MEMCPY(&tha.src, &ip->ip_src, sizeof ip->ip_src); 322 tha.port = sport << 16 | dport; 323 } 324 325 for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; 326 th->nxt; th = th->nxt) 327 if (memcmp((char *)&tha, (char *)&th->addr, 328 sizeof(th->addr)) == 0) 329 break; 330 331 if (!th->nxt || (flags & TH_SYN)) { 332 /* didn't find it or new conversation */ 333 if (th->nxt == NULL) { 334 th->nxt = (struct tcp_seq_hash *) 335 calloc(1, sizeof(*th)); 336 if (th->nxt == NULL) 337 (*ndo->ndo_error)(ndo, 338 "tcp_print: calloc"); 339 } 340 th->addr = tha; 341 if (rev) 342 th->ack = seq, th->seq = ack - 1; 343 else 344 th->seq = seq, th->ack = ack - 1; 345 } else { 346 if (rev) 347 seq -= th->ack, ack -= th->seq; 348 else 349 seq -= th->seq, ack -= th->ack; 350 } 351 352 thseq = th->seq; 353 thack = th->ack; 354 } 355 } else { 356 /*fool gcc*/ 357 thseq = thack = rev = 0; 358 } 359 if (hlen > length) { 360 ND_PRINT((ndo, " [bad hdr length %u - too long, > %u]", 361 hlen, length)); 362 return; 363 } 364 365 if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) { 366 /* Check the checksum, if possible. */ 367 uint16_t sum, tcp_sum; 368 369 if (IP_V(ip) == 4) { 370 if (ND_TTEST2(tp->th_sport, length)) { 371 sum = tcp_cksum(ndo, ip, tp, length); 372 tcp_sum = EXTRACT_16BITS(&tp->th_sum); 373 374 ND_PRINT((ndo, ", cksum 0x%04x", tcp_sum)); 375 if (sum != 0) 376 ND_PRINT((ndo, " (incorrect -> 0x%04x)", 377 in_cksum_shouldbe(tcp_sum, sum))); 378 else 379 ND_PRINT((ndo, " (correct)")); 380 } 381 } else if (IP_V(ip) == 6 && ip6->ip6_plen) { 382 if (ND_TTEST2(tp->th_sport, length)) { 383 sum = tcp6_cksum(ndo, ip6, tp, length); 384 tcp_sum = EXTRACT_16BITS(&tp->th_sum); 385 386 ND_PRINT((ndo, ", cksum 0x%04x", tcp_sum)); 387 if (sum != 0) 388 ND_PRINT((ndo, " (incorrect -> 0x%04x)", 389 in_cksum_shouldbe(tcp_sum, sum))); 390 else 391 ND_PRINT((ndo, " (correct)")); 392 393 } 394 } 395 } 396 397 length -= hlen; 398 if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { 399 ND_PRINT((ndo, ", seq %u", seq)); 400 401 if (length > 0) { 402 ND_PRINT((ndo, ":%u", seq + length)); 403 } 404 } 405 406 if (flags & TH_ACK) { 407 ND_PRINT((ndo, ", ack %u", ack)); 408 } 409 410 ND_PRINT((ndo, ", win %d", win)); 411 412 if (flags & TH_URG) 413 ND_PRINT((ndo, ", urg %d", urp)); 414 /* 415 * Handle any options. 416 */ 417 if (hlen > sizeof(*tp)) { 418 register const u_char *cp; 419 register u_int i, opt, datalen; 420 register u_int len; 421 422 hlen -= sizeof(*tp); 423 cp = (const u_char *)tp + sizeof(*tp); 424 ND_PRINT((ndo, ", options [")); 425 while (hlen > 0) { 426 if (ch != '\0') 427 ND_PRINT((ndo, "%c", ch)); 428 ND_TCHECK(*cp); 429 opt = *cp++; 430 if (ZEROLENOPT(opt)) 431 len = 1; 432 else { 433 ND_TCHECK(*cp); 434 len = *cp++; /* total including type, len */ 435 if (len < 2 || len > hlen) 436 goto bad; 437 --hlen; /* account for length byte */ 438 } 439 --hlen; /* account for type byte */ 440 datalen = 0; 441 442 /* Bail if "l" bytes of data are not left or were not captured */ 443 #define LENCHECK(l) { if ((l) > hlen) goto bad; ND_TCHECK2(*cp, l); } 444 445 446 ND_PRINT((ndo, "%s", tok2str(tcp_option_values, "unknown-%u", opt))); 447 448 switch (opt) { 449 450 case TCPOPT_MAXSEG: 451 datalen = 2; 452 LENCHECK(datalen); 453 ND_PRINT((ndo, " %u", EXTRACT_16BITS(cp))); 454 break; 455 456 case TCPOPT_WSCALE: 457 datalen = 1; 458 LENCHECK(datalen); 459 ND_PRINT((ndo, " %u", *cp)); 460 break; 461 462 case TCPOPT_SACK: 463 datalen = len - 2; 464 if (datalen % 8 != 0) { 465 ND_PRINT((ndo, "invalid sack")); 466 } else { 467 uint32_t s, e; 468 469 ND_PRINT((ndo, " %d ", datalen / 8)); 470 for (i = 0; i < datalen; i += 8) { 471 LENCHECK(i + 4); 472 s = EXTRACT_32BITS(cp + i); 473 LENCHECK(i + 8); 474 e = EXTRACT_32BITS(cp + i + 4); 475 if (rev) { 476 s -= thseq; 477 e -= thseq; 478 } else { 479 s -= thack; 480 e -= thack; 481 } 482 ND_PRINT((ndo, "{%u:%u}", s, e)); 483 } 484 } 485 break; 486 487 case TCPOPT_CC: 488 case TCPOPT_CCNEW: 489 case TCPOPT_CCECHO: 490 case TCPOPT_ECHO: 491 case TCPOPT_ECHOREPLY: 492 493 /* 494 * those options share their semantics. 495 * fall through 496 */ 497 datalen = 4; 498 LENCHECK(datalen); 499 ND_PRINT((ndo, " %u", EXTRACT_32BITS(cp))); 500 break; 501 502 case TCPOPT_TIMESTAMP: 503 datalen = 8; 504 LENCHECK(datalen); 505 ND_PRINT((ndo, " val %u ecr %u", 506 EXTRACT_32BITS(cp), 507 EXTRACT_32BITS(cp + 4))); 508 break; 509 510 case TCPOPT_SIGNATURE: 511 datalen = TCP_SIGLEN; 512 LENCHECK(datalen); 513 #ifdef HAVE_LIBCRYPTO 514 switch (tcp_verify_signature(ndo, ip, tp, 515 bp + TH_OFF(tp) * 4, length, cp)) { 516 517 case SIGNATURE_VALID: 518 ND_PRINT((ndo, "valid")); 519 break; 520 521 case SIGNATURE_INVALID: 522 ND_PRINT((ndo, "invalid")); 523 break; 524 525 case CANT_CHECK_SIGNATURE: 526 ND_PRINT((ndo, "can't check - ")); 527 for (i = 0; i < TCP_SIGLEN; ++i) 528 ND_PRINT((ndo, "%02x", cp[i])); 529 break; 530 } 531 #else 532 for (i = 0; i < TCP_SIGLEN; ++i) 533 ND_PRINT((ndo, "%02x", cp[i])); 534 #endif 535 break; 536 537 case TCPOPT_AUTH: 538 ND_PRINT((ndo, "keyid %d", *cp++)); 539 datalen = len - 3; 540 for (i = 0; i < datalen; ++i) { 541 LENCHECK(i); 542 ND_PRINT((ndo, "%02x", cp[i])); 543 } 544 break; 545 546 547 case TCPOPT_EOL: 548 case TCPOPT_NOP: 549 case TCPOPT_SACKOK: 550 /* 551 * Nothing interesting. 552 * fall through 553 */ 554 break; 555 556 case TCPOPT_UTO: 557 datalen = 2; 558 LENCHECK(datalen); 559 utoval = EXTRACT_16BITS(cp); 560 ND_PRINT((ndo, "0x%x", utoval)); 561 if (utoval & 0x0001) 562 utoval = (utoval >> 1) * 60; 563 else 564 utoval >>= 1; 565 ND_PRINT((ndo, " %u", utoval)); 566 break; 567 568 case TCPOPT_MPTCP: 569 datalen = len - 2; 570 LENCHECK(datalen); 571 if (!mptcp_print(ndo, cp-2, len, flags)) 572 goto bad; 573 break; 574 575 case TCPOPT_FASTOPEN: 576 datalen = len - 2; 577 LENCHECK(datalen); 578 print_tcp_fastopen_option(ndo, cp, datalen, FALSE); 579 break; 580 581 case TCPOPT_EXPERIMENT2: 582 datalen = len - 2; 583 LENCHECK(datalen); 584 if (datalen < 2) 585 goto bad; 586 /* RFC6994 */ 587 magic = EXTRACT_16BITS(cp); 588 ND_PRINT((ndo, "-")); 589 590 switch(magic) { 591 592 case 0xf989: /* TCP Fast Open RFC 7413 */ 593 print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE); 594 break; 595 596 default: 597 /* Unknown magic number */ 598 ND_PRINT((ndo, "%04x", magic)); 599 break; 600 } 601 break; 602 603 default: 604 datalen = len - 2; 605 if (datalen) 606 ND_PRINT((ndo, " 0x")); 607 for (i = 0; i < datalen; ++i) { 608 LENCHECK(i); 609 ND_PRINT((ndo, "%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 ND_PRINT((ndo, "[len %d]", len)); 624 ch = ','; 625 if (opt == TCPOPT_EOL) 626 break; 627 } 628 ND_PRINT((ndo, "]")); 629 } 630 631 /* 632 * Print length field before crawling down the stack. 633 */ 634 ND_PRINT((ndo, ", length %u", length)); 635 636 if (length <= 0) 637 return; 638 639 /* 640 * Decode payload if necessary. 641 */ 642 bp += TH_OFF(tp) * 4; 643 if ((flags & TH_RST) && ndo->ndo_vflag) { 644 print_tcp_rst_data(ndo, bp, length); 645 return; 646 } 647 648 if (ndo->ndo_packettype) { 649 switch (ndo->ndo_packettype) { 650 case PT_ZMTP1: 651 zmtp1_print(ndo, bp, length); 652 break; 653 case PT_RESP: 654 resp_print(ndo, bp, length); 655 break; 656 } 657 return; 658 } 659 660 if (IS_SRC_OR_DST_PORT(TELNET_PORT)) { 661 telnet_print(ndo, bp, length); 662 } else if (IS_SRC_OR_DST_PORT(SMTP_PORT)) { 663 ND_PRINT((ndo, ": ")); 664 smtp_print(ndo, bp, length); 665 } else if (IS_SRC_OR_DST_PORT(BGP_PORT)) 666 bgp_print(ndo, bp, length); 667 else if (IS_SRC_OR_DST_PORT(PPTP_PORT)) 668 pptp_print(ndo, bp); 669 else if (IS_SRC_OR_DST_PORT(REDIS_PORT)) 670 resp_print(ndo, bp, length); 671 #ifdef ENABLE_SMB 672 else if (IS_SRC_OR_DST_PORT(NETBIOS_SSN_PORT)) 673 nbt_tcp_print(ndo, bp, length); 674 else if (IS_SRC_OR_DST_PORT(SMB_PORT)) 675 smb_tcp_print(ndo, bp, length); 676 #endif 677 else if (IS_SRC_OR_DST_PORT(BEEP_PORT)) 678 beep_print(ndo, bp, length); 679 else if (IS_SRC_OR_DST_PORT(OPENFLOW_PORT_OLD) || IS_SRC_OR_DST_PORT(OPENFLOW_PORT_IANA)) 680 openflow_print(ndo, bp, length); 681 else if (IS_SRC_OR_DST_PORT(FTP_PORT)) { 682 ND_PRINT((ndo, ": ")); 683 ftp_print(ndo, bp, length); 684 } else if (IS_SRC_OR_DST_PORT(HTTP_PORT) || IS_SRC_OR_DST_PORT(HTTP_PORT_ALT)) { 685 ND_PRINT((ndo, ": ")); 686 http_print(ndo, bp, length); 687 } else if (IS_SRC_OR_DST_PORT(RTSP_PORT) || IS_SRC_OR_DST_PORT(RTSP_PORT_ALT)) { 688 ND_PRINT((ndo, ": ")); 689 rtsp_print(ndo, bp, length); 690 } else if (length > 2 && 691 (IS_SRC_OR_DST_PORT(NAMESERVER_PORT))) { 692 /* 693 * TCP DNS query has 2byte length at the head. 694 * XXX packet could be unaligned, it can go strange 695 */ 696 ns_print(ndo, bp + 2, length - 2, 0); 697 } else if (IS_SRC_OR_DST_PORT(MSDP_PORT)) { 698 msdp_print(ndo, bp, length); 699 } else if (IS_SRC_OR_DST_PORT(RPKI_RTR_PORT)) { 700 rpki_rtr_print(ndo, bp, length); 701 } 702 else if (length > 0 && (IS_SRC_OR_DST_PORT(LDP_PORT))) { 703 ldp_print(ndo, bp, length); 704 } 705 else if ((IS_SRC_OR_DST_PORT(NFS_PORT)) && 706 length >= 4 && ND_TTEST2(*bp, 4)) { 707 /* 708 * If data present, header length valid, and NFS port used, 709 * assume NFS. 710 * Pass offset of data plus 4 bytes for RPC TCP msg length 711 * to NFS print routines. 712 */ 713 uint32_t fraglen; 714 register const struct sunrpc_msg *rp; 715 enum sunrpc_msg_type direction; 716 717 fraglen = EXTRACT_32BITS(bp) & 0x7FFFFFFF; 718 if (fraglen > (length) - 4) 719 fraglen = (length) - 4; 720 rp = (const struct sunrpc_msg *)(bp + 4); 721 if (ND_TTEST(rp->rm_direction)) { 722 direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); 723 if (dport == NFS_PORT && direction == SUNRPC_CALL) { 724 ND_PRINT((ndo, ": NFS request xid %u ", EXTRACT_32BITS(&rp->rm_xid))); 725 nfsreq_print_noaddr(ndo, (const u_char *)rp, fraglen, (const u_char *)ip); 726 return; 727 } 728 if (sport == NFS_PORT && direction == SUNRPC_REPLY) { 729 ND_PRINT((ndo, ": NFS reply xid %u ", EXTRACT_32BITS(&rp->rm_xid))); 730 nfsreply_print_noaddr(ndo, (const u_char *)rp, fraglen, (const u_char *)ip); 731 return; 732 } 733 } 734 } 735 736 return; 737 bad: 738 ND_PRINT((ndo, "[bad opt]")); 739 if (ch != '\0') 740 ND_PRINT((ndo, ">")); 741 return; 742 trunc: 743 ND_PRINT((ndo, "[|tcp]")); 744 if (ch != '\0') 745 ND_PRINT((ndo, ">")); 746 } 747 748 /* 749 * RFC1122 says the following on data in RST segments: 750 * 751 * 4.2.2.12 RST Segment: RFC-793 Section 3.4 752 * 753 * A TCP SHOULD allow a received RST segment to include data. 754 * 755 * DISCUSSION 756 * It has been suggested that a RST segment could contain 757 * ASCII text that encoded and explained the cause of the 758 * RST. No standard has yet been established for such 759 * data. 760 * 761 */ 762 763 static void 764 print_tcp_rst_data(netdissect_options *ndo, 765 register const u_char *sp, u_int length) 766 { 767 int c; 768 769 ND_PRINT((ndo, ND_TTEST2(*sp, length) ? " [RST" : " [!RST")); 770 if (length > MAX_RST_DATA_LEN) { 771 length = MAX_RST_DATA_LEN; /* can use -X for longer */ 772 ND_PRINT((ndo, "+")); /* indicate we truncate */ 773 } 774 ND_PRINT((ndo, " ")); 775 while (length-- && sp < ndo->ndo_snapend) { 776 c = *sp++; 777 safeputchar(ndo, c); 778 } 779 ND_PRINT((ndo, "]")); 780 } 781 782 static void 783 print_tcp_fastopen_option(netdissect_options *ndo, register const u_char *cp, 784 u_int datalen, int exp) 785 { 786 u_int i; 787 788 if (exp) 789 ND_PRINT((ndo, "tfo")); 790 791 if (datalen == 0) { 792 /* Fast Open Cookie Request */ 793 ND_PRINT((ndo, " cookiereq")); 794 } else { 795 /* Fast Open Cookie */ 796 if (datalen % 2 != 0 || datalen < 4 || datalen > 16) { 797 ND_PRINT((ndo, " invalid")); 798 } else { 799 ND_PRINT((ndo, " cookie ")); 800 for (i = 0; i < datalen; ++i) 801 ND_PRINT((ndo, "%02x", cp[i])); 802 } 803 } 804 } 805 806 #ifdef HAVE_LIBCRYPTO 807 USES_APPLE_DEPRECATED_API 808 static int 809 tcp_verify_signature(netdissect_options *ndo, 810 const struct ip *ip, const struct tcphdr *tp, 811 const u_char *data, int length, const u_char *rcvsig) 812 { 813 struct tcphdr tp1; 814 u_char sig[TCP_SIGLEN]; 815 char zero_proto = 0; 816 MD5_CTX ctx; 817 uint16_t savecsum, tlen; 818 const struct ip6_hdr *ip6; 819 uint32_t len32; 820 uint8_t nxt; 821 822 if (data + length > ndo->ndo_snapend) { 823 ND_PRINT((ndo, "snaplen too short, ")); 824 return (CANT_CHECK_SIGNATURE); 825 } 826 827 tp1 = *tp; 828 829 if (ndo->ndo_sigsecret == NULL) { 830 ND_PRINT((ndo, "shared secret not supplied with -M, ")); 831 return (CANT_CHECK_SIGNATURE); 832 } 833 834 MD5_Init(&ctx); 835 /* 836 * Step 1: Update MD5 hash with IP pseudo-header. 837 */ 838 if (IP_V(ip) == 4) { 839 MD5_Update(&ctx, (const char *)&ip->ip_src, sizeof(ip->ip_src)); 840 MD5_Update(&ctx, (const char *)&ip->ip_dst, sizeof(ip->ip_dst)); 841 MD5_Update(&ctx, (const char *)&zero_proto, sizeof(zero_proto)); 842 MD5_Update(&ctx, (const char *)&ip->ip_p, sizeof(ip->ip_p)); 843 tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4; 844 tlen = htons(tlen); 845 MD5_Update(&ctx, (const char *)&tlen, sizeof(tlen)); 846 } else if (IP_V(ip) == 6) { 847 ip6 = (const struct ip6_hdr *)ip; 848 MD5_Update(&ctx, (const char *)&ip6->ip6_src, sizeof(ip6->ip6_src)); 849 MD5_Update(&ctx, (const char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst)); 850 len32 = htonl(EXTRACT_16BITS(&ip6->ip6_plen)); 851 MD5_Update(&ctx, (const char *)&len32, sizeof(len32)); 852 nxt = 0; 853 MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); 854 MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); 855 MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); 856 nxt = IPPROTO_TCP; 857 MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); 858 } else { 859 ND_PRINT((ndo, "IP version not 4 or 6, ")); 860 return (CANT_CHECK_SIGNATURE); 861 } 862 863 /* 864 * Step 2: Update MD5 hash with TCP header, excluding options. 865 * The TCP checksum must be set to zero. 866 */ 867 savecsum = tp1.th_sum; 868 tp1.th_sum = 0; 869 MD5_Update(&ctx, (const char *)&tp1, sizeof(struct tcphdr)); 870 tp1.th_sum = savecsum; 871 /* 872 * Step 3: Update MD5 hash with TCP segment data, if present. 873 */ 874 if (length > 0) 875 MD5_Update(&ctx, data, length); 876 /* 877 * Step 4: Update MD5 hash with shared secret. 878 */ 879 MD5_Update(&ctx, ndo->ndo_sigsecret, strlen(ndo->ndo_sigsecret)); 880 MD5_Final(sig, &ctx); 881 882 if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0) 883 return (SIGNATURE_VALID); 884 else 885 return (SIGNATURE_INVALID); 886 } 887 USES_APPLE_RST 888 #endif /* HAVE_LIBCRYPTO */ 889 890 /* 891 * Local Variables: 892 * c-style: whitesmith 893 * c-basic-offset: 8 894 * End: 895 */ 896