print-tcp.c revision 190207
138451Smsmith/* $NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky Exp $ */ 238451Smsmith 338451Smsmith/* 438451Smsmith * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 538451Smsmith * The Regents of the University of California. All rights reserved. 638451Smsmith * 738451Smsmith * Copyright (c) 1999-2004 The tcpdump.org project 838451Smsmith * 938451Smsmith * Redistribution and use in source and binary forms, with or without 1038451Smsmith * modification, are permitted provided that: (1) source code distributions 1138451Smsmith * retain the above copyright notice and this paragraph in its entirety, (2) 1238451Smsmith * distributions including binary code include the above copyright notice and 1338451Smsmith * this paragraph in its entirety in the documentation or other materials 1438451Smsmith * provided with the distribution, and (3) all advertising materials mentioning 1538451Smsmith * features or use of this software display the following acknowledgement: 1638451Smsmith * ``This product includes software developed by the University of California, 1738451Smsmith * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1838451Smsmith * the University nor the names of its contributors may be used to endorse 1938451Smsmith * or promote products derived from this software without specific prior 2038451Smsmith * written permission. 2138451Smsmith * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 2238451Smsmith * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 2338451Smsmith * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2438451Smsmith */ 2538451Smsmith 2650476Speter#ifndef lint 2738451Smsmithstatic const char rcsid[] _U_ = 2838451Smsmith"@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.130.2.3 2007-12-22 03:08:45 guy Exp $ (LBL)"; 2938451Smsmith #else 3038451Smsmith__RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $"); 3138451Smsmith#endif 3238451Smsmith 3338451Smsmith#ifdef HAVE_CONFIG_H 3438451Smsmith#include "config.h" 3538451Smsmith#endif 3638451Smsmith 3738451Smsmith#include <tcpdump-stdinc.h> 3838451Smsmith 3938451Smsmith#include <stdio.h> 4038451Smsmith#include <stdlib.h> 4138451Smsmith#include <string.h> 4238451Smsmith 4338451Smsmith#include "interface.h" 4438451Smsmith#include "addrtoname.h" 4538451Smsmith#include "extract.h" 4638451Smsmith 4738451Smsmith#include "tcp.h" 4838451Smsmith 4938451Smsmith#include "ip.h" 5038451Smsmith#ifdef INET6 5138451Smsmith#include "ip6.h" 5238451Smsmith#endif 5338451Smsmith#include "ipproto.h" 5438451Smsmith#include "rpc_auth.h" 5538451Smsmith#include "rpc_msg.h" 5638451Smsmith 5738451Smsmith#include "nameser.h" 5838451Smsmith 5938451Smsmith#ifdef HAVE_LIBCRYPTO 6038451Smsmith#include <openssl/md5.h> 6138451Smsmith 6238451Smsmith#define SIGNATURE_VALID 0 6338451Smsmith#define SIGNATURE_INVALID 1 6438451Smsmith#define CANT_CHECK_SIGNATURE 2 6538451Smsmith 6638451Smsmithstatic int tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp, 6738451Smsmith const u_char *data, int length, const u_char *rcvsig); 6859766Sjlemon#endif 6964185Sjhb 7038451Smsmithstatic void print_tcp_rst_data(register const u_char *sp, u_int length); 7139665Smsmith 7239665Smsmith#define MAX_RST_DATA_LEN 30 7339665Smsmith 7438451Smsmith 7538451Smsmithstruct tha { 7638451Smsmith#ifndef INET6 7738451Smsmith struct in_addr src; 7838451Smsmith struct in_addr dst; 7955206Speter#else 8038451Smsmith struct in6_addr src; 8155206Speter struct in6_addr dst; 8238451Smsmith#endif /*INET6*/ 8338451Smsmith u_int port; 8438451Smsmith}; 8538451Smsmith 8638451Smsmithstruct tcp_seq_hash { 8738451Smsmith struct tcp_seq_hash *nxt; 8838451Smsmith struct tha addr; 8938451Smsmith tcp_seq seq; 9038451Smsmith tcp_seq ack; 9138451Smsmith}; 9238451Smsmith 9338451Smsmith#define TSEQ_HASHSIZE 919 9438451Smsmith 9538451Smsmith/* These tcp optinos do not have the size octet */ 9638451Smsmith#define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP) 9738451Smsmith 9838451Smsmithstatic struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE]; 9938451Smsmith 10038451Smsmithstruct tok tcp_flag_values[] = { 10138451Smsmith { TH_FIN, "F" }, 10238451Smsmith { TH_SYN, "S" }, 10338451Smsmith { TH_RST, "R" }, 10438451Smsmith { TH_PUSH, "P" }, 10539468Smsmith { TH_ACK, "." }, 10639468Smsmith { TH_URG, "U" }, 10738451Smsmith { TH_ECNECHO, "E" }, 10838451Smsmith { TH_CWR, "W" }, 10938451Smsmith { 0, NULL } 11038451Smsmith}; 11138451Smsmith 11238451Smsmithstruct tok tcp_option_values[] = { 11338451Smsmith { TCPOPT_EOL, "eol" }, 11459766Sjlemon { TCPOPT_NOP, "nop" }, 11538451Smsmith { TCPOPT_MAXSEG, "mss" }, 11638451Smsmith { TCPOPT_WSCALE, "wscale" }, 11738451Smsmith { TCPOPT_SACKOK, "sackOK" }, 11838451Smsmith { TCPOPT_SACK, "sack" }, 11938451Smsmith { TCPOPT_ECHO, "echo" }, 12038451Smsmith { TCPOPT_ECHOREPLY, "echoreply" }, 12138451Smsmith { TCPOPT_TIMESTAMP, "TS" }, 12238451Smsmith { TCPOPT_CC, "cc" }, 12338451Smsmith { TCPOPT_CCNEW, "ccnew" }, 12438451Smsmith { TCPOPT_CCECHO, "" }, 12583610Ssobomax { TCPOPT_SIGNATURE, "md5" }, 12638451Smsmith { TCPOPT_AUTH, "enhanced auth" }, 12759766Sjlemon { 0, NULL } 12892494Ssobomax}; 12938451Smsmith 13038451Smsmithstatic int tcp_cksum(register const struct ip *ip, 13138451Smsmith register const struct tcphdr *tp, 13238451Smsmith register u_int len) 13338451Smsmith{ 13438451Smsmith union phu { 13538451Smsmith struct phdr { 13638451Smsmith u_int32_t src; 13738451Smsmith u_int32_t dst; 13838451Smsmith u_char mbz; 13939468Smsmith u_char proto; 14038451Smsmith u_int16_t len; 14138451Smsmith } ph; 14264185Sjhb u_int16_t pa[6]; 14364185Sjhb } phu; 14438451Smsmith const u_int16_t *sp; 14538451Smsmith 14638451Smsmith /* pseudo-header.. */ 14740774Smsmith phu.ph.len = htons((u_int16_t)len); 14864185Sjhb phu.ph.mbz = 0; 14938451Smsmith phu.ph.proto = IPPROTO_TCP; 15038451Smsmith memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); 15159766Sjlemon if (IP_HL(ip) == 5) 15259766Sjlemon memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); 15359766Sjlemon else 15459766Sjlemon phu.ph.dst = ip_finddst(ip); 15559766Sjlemon 15638451Smsmith sp = &phu.pa[0]; 15738451Smsmith return in_cksum((u_short *)tp, len, 15838451Smsmith sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]); 15938451Smsmith} 16038451Smsmith 16138451Smsmith#ifdef INET6 16238451Smsmithstatic int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp, 16338451Smsmith u_int len) 16465470Smsmith{ 16565470Smsmith size_t i; 16665470Smsmith u_int32_t sum = 0; 16765470Smsmith union { 16865470Smsmith struct { 16938451Smsmith struct in6_addr ph_src; 17038451Smsmith struct in6_addr ph_dst; 17138451Smsmith u_int32_t ph_len; 17238451Smsmith u_int8_t ph_zero[3]; 17338451Smsmith u_int8_t ph_nxt; 17438451Smsmith } ph; 17538451Smsmith u_int16_t pa[20]; 17638451Smsmith } phu; 17738451Smsmith 17838451Smsmith /* pseudo-header */ 17938451Smsmith memset(&phu, 0, sizeof(phu)); 18055181Speter phu.ph.ph_src = ip6->ip6_src; 18138451Smsmith phu.ph.ph_dst = ip6->ip6_dst; 18276579Sdcs phu.ph.ph_len = htonl(len); 18376579Sdcs phu.ph.ph_nxt = IPPROTO_TCP; 18476579Sdcs 18576579Sdcs for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) 18676579Sdcs sum += phu.pa[i]; 18776579Sdcs 18876579Sdcs return in_cksum((u_short *)tp, len, sum); 18976579Sdcs} 19076579Sdcs#endif 19176579Sdcs 19276579Sdcsvoid 19376579Sdcstcp_print(register const u_char *bp, register u_int length, 19476579Sdcs register const u_char *bp2, int fragmented) 19576579Sdcs{ 19676579Sdcs register const struct tcphdr *tp; 19776579Sdcs register const struct ip *ip; 19876579Sdcs register u_char flags; 19976579Sdcs register u_int hlen; 20076579Sdcs register char ch; 20176579Sdcs u_int16_t sport, dport, win, urp; 20276579Sdcs u_int32_t seq, ack, thseq, thack; 20376579Sdcs int threv; 20476579Sdcs#ifdef INET6 20576579Sdcs register const struct ip6_hdr *ip6; 20676579Sdcs#endif 20776579Sdcs 20876579Sdcs tp = (struct tcphdr *)bp; 20976579Sdcs ip = (struct ip *)bp2; 21076579Sdcs#ifdef INET6 21176579Sdcs if (IP_V(ip) == 6) 21276579Sdcs ip6 = (struct ip6_hdr *)bp2; 21376579Sdcs else 21476579Sdcs ip6 = NULL; 21576579Sdcs#endif /*INET6*/ 21676579Sdcs ch = '\0'; 21751169Sdfr if (!TTEST(tp->th_dport)) { 21851169Sdfr (void)printf("%s > %s: [|tcp]", 21951169Sdfr ipaddr_string(&ip->ip_src), 22051169Sdfr ipaddr_string(&ip->ip_dst)); 22151169Sdfr return; 22251169Sdfr } 22351169Sdfr 22451169Sdfr sport = EXTRACT_16BITS(&tp->th_sport); 22551169Sdfr dport = EXTRACT_16BITS(&tp->th_dport); 22651169Sdfr 22739665Smsmith hlen = TH_OFF(tp) * 4; 22839665Smsmith 22939665Smsmith /* 23038451Smsmith * If data present, header length valid, and NFS port used, 23139665Smsmith * assume NFS. 23239665Smsmith * Pass offset of data plus 4 bytes for RPC TCP msg length 23339665Smsmith * to NFS print routines. 23439665Smsmith */ 23539665Smsmith if (!qflag && hlen >= sizeof(*tp) && hlen <= length && 23639665Smsmith (length - hlen) >= 4) { 23739665Smsmith u_char *fraglenp; 23839665Smsmith u_int32_t fraglen; 23940520Sdfr register struct sunrpc_msg *rp; 24040520Sdfr enum sunrpc_msg_type direction; 24140520Sdfr 24239665Smsmith fraglenp = (u_char *)tp + hlen; 24338451Smsmith if (TTEST2(*fraglenp, 4)) { 24438451Smsmith fraglen = EXTRACT_32BITS(fraglenp) & 0x7FFFFFFF; 24538451Smsmith if (fraglen > (length - hlen) - 4) 24638451Smsmith fraglen = (length - hlen) - 4; 24738451Smsmith rp = (struct sunrpc_msg *)(fraglenp + 4); 24838451Smsmith if (TTEST(rp->rm_direction)) { 24938451Smsmith direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); 25040805Smsmith if (dport == NFS_PORT && 25138451Smsmith direction == SUNRPC_CALL) { 25238451Smsmith nfsreq_print((u_char *)rp, fraglen, 25338451Smsmith (u_char *)ip); 25438451Smsmith return; 25538451Smsmith } 25638451Smsmith if (sport == NFS_PORT && 25738451Smsmith direction == SUNRPC_REPLY) { 25838451Smsmith nfsreply_print((u_char *)rp, fraglen, 25938451Smsmith (u_char *)ip); 26087632Sjhb return; 26138451Smsmith } 26238451Smsmith } 26338451Smsmith } 26438451Smsmith } 26538451Smsmith#ifdef INET6 26659766Sjlemon if (ip6) { 26738451Smsmith if (ip6->ip6_nxt == IPPROTO_TCP) { 26838451Smsmith (void)printf("%s.%s > %s.%s: ", 26938451Smsmith ip6addr_string(&ip6->ip6_src), 27038451Smsmith tcpport_string(sport), 27138451Smsmith ip6addr_string(&ip6->ip6_dst), 27238451Smsmith tcpport_string(dport)); 27338451Smsmith } else { 27442511Smsmith (void)printf("%s > %s: ", 27538451Smsmith tcpport_string(sport), tcpport_string(dport)); 27638451Smsmith } 27738451Smsmith } else 27838451Smsmith#endif /*INET6*/ 27938451Smsmith { 28038451Smsmith if (ip->ip_p == IPPROTO_TCP) { 28139468Smsmith (void)printf("%s.%s > %s.%s: ", 28238451Smsmith ipaddr_string(&ip->ip_src), 28340891Smsmith tcpport_string(sport), 28440891Smsmith ipaddr_string(&ip->ip_dst), 28540891Smsmith tcpport_string(dport)); 28640891Smsmith } else { 28738451Smsmith (void)printf("%s > %s: ", 28838451Smsmith tcpport_string(sport), tcpport_string(dport)); 28938451Smsmith } 29038451Smsmith } 29138451Smsmith 29238451Smsmith if (hlen < sizeof(*tp)) { 29338451Smsmith (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]", 29438451Smsmith length - hlen, hlen, (unsigned long)sizeof(*tp)); 29538451Smsmith return; 29638451Smsmith } 29738451Smsmith 29838451Smsmith TCHECK(*tp); 29938451Smsmith 30038451Smsmith seq = EXTRACT_32BITS(&tp->th_seq); 30138451Smsmith ack = EXTRACT_32BITS(&tp->th_ack); 30238451Smsmith win = EXTRACT_16BITS(&tp->th_win); 30338451Smsmith urp = EXTRACT_16BITS(&tp->th_urp); 30438451Smsmith 30538451Smsmith if (qflag) { 30638451Smsmith (void)printf("tcp %d", length - hlen); 30738451Smsmith if (hlen > length) { 30838451Smsmith (void)printf(" [bad hdr length %u - too long, > %u]", 30964185Sjhb hlen, length); 31064185Sjhb } 31164185Sjhb return; 31238451Smsmith } 31364185Sjhb 31464185Sjhb flags = tp->th_flags; 31538451Smsmith printf("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags)); 31638451Smsmith 31738451Smsmith if (!Sflag && (flags & TH_ACK)) { 31838451Smsmith register struct tcp_seq_hash *th; 31938451Smsmith const void *src, *dst; 32038451Smsmith register int rev; 32138451Smsmith struct tha tha; 32238451Smsmith /* 32338451Smsmith * Find (or record) the initial sequence numbers for 32438451Smsmith * this conversation. (we pick an arbitrary 32538451Smsmith * collating order so there's only one entry for 32638451Smsmith * both directions). 32738451Smsmith */ 32838451Smsmith#ifdef INET6 32938451Smsmith memset(&tha, 0, sizeof(tha)); 33038451Smsmith rev = 0; 33138451Smsmith if (ip6) { 33238451Smsmith src = &ip6->ip6_src; 33338451Smsmith dst = &ip6->ip6_dst; 33438451Smsmith if (sport > dport) 33538451Smsmith rev = 1; 33638451Smsmith else if (sport == dport) { 33738451Smsmith if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0) 33838451Smsmith rev = 1; 33938451Smsmith } 34038451Smsmith if (rev) { 34138451Smsmith memcpy(&tha.src, dst, sizeof ip6->ip6_dst); 34238451Smsmith memcpy(&tha.dst, src, sizeof ip6->ip6_src); 34338451Smsmith tha.port = dport << 16 | sport; 34438451Smsmith } else { 34597776Ssobomax memcpy(&tha.dst, dst, sizeof ip6->ip6_dst); 34638451Smsmith memcpy(&tha.src, src, sizeof ip6->ip6_src); 34738451Smsmith tha.port = sport << 16 | dport; 34838451Smsmith } 34938451Smsmith } else { 35038451Smsmith src = &ip->ip_src; 35138451Smsmith dst = &ip->ip_dst; 35238451Smsmith if (sport > dport) 35339468Smsmith rev = 1; 35438451Smsmith else if (sport == dport) { 35555137Speter if (memcmp(src, dst, sizeof ip->ip_dst) > 0) 35655137Speter rev = 1; 35738451Smsmith } 35838451Smsmith if (rev) { 35959766Sjlemon memcpy(&tha.src, dst, sizeof ip->ip_dst); 36038451Smsmith memcpy(&tha.dst, src, sizeof ip->ip_src); 36159766Sjlemon tha.port = dport << 16 | sport; 36238451Smsmith } else { 36338451Smsmith memcpy(&tha.dst, dst, sizeof ip->ip_dst); 36438451Smsmith memcpy(&tha.src, src, sizeof ip->ip_src); 36538451Smsmith tha.port = sport << 16 | dport; 36638451Smsmith } 36738451Smsmith } 36838451Smsmith#else 36939672Sdfr rev = 0; 37038451Smsmith src = &ip->ip_src; 37138506Sbde dst = &ip->ip_dst; 37238451Smsmith if (sport > dport) 37338451Smsmith rev = 1; 37438451Smsmith else if (sport == dport) { 37590868Smike if (memcmp(src, dst, sizeof ip->ip_dst) > 0) 37690868Smike rev = 1; 37790868Smike } 37891959Smike if (rev) { 37991959Smike memcpy(&tha.src, dst, sizeof ip->ip_dst); 38091959Smike memcpy(&tha.dst, src, sizeof ip->ip_src); 38191959Smike tha.port = dport << 16 | sport; 38291959Smike } else { 38391959Smike memcpy(&tha.dst, dst, sizeof ip->ip_dst); 38491959Smike memcpy(&tha.src, src, sizeof ip->ip_src); 38591959Smike tha.port = sport << 16 | dport; 38691959Smike } 38791959Smike#endif 38890868Smike 38990868Smike threv = rev; 39090868Smike for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; 39190868Smike th->nxt; th = th->nxt) 39291959Smike if (memcmp((char *)&tha, (char *)&th->addr, 39390868Smike sizeof(th->addr)) == 0) 39439672Sdfr break; 39539672Sdfr 39639672Sdfr if (!th->nxt || (flags & TH_SYN)) { 39739672Sdfr /* didn't find it or new conversation */ 39839672Sdfr if (th->nxt == NULL) { 39939672Sdfr th->nxt = (struct tcp_seq_hash *) 40039672Sdfr calloc(1, sizeof(*th)); 40139672Sdfr if (th->nxt == NULL) 40239672Sdfr error("tcp_print: calloc"); 40339672Sdfr } 40439672Sdfr th->addr = tha; 40539672Sdfr if (rev) 40639672Sdfr th->ack = seq, th->seq = ack - 1; 40739672Sdfr else 40839672Sdfr th->seq = seq, th->ack = ack - 1; 40939672Sdfr } else { 41039672Sdfr if (rev) 41139672Sdfr seq -= th->ack, ack -= th->seq; 41239672Sdfr else 41339672Sdfr seq -= th->seq, ack -= th->ack; 41439672Sdfr } 41539672Sdfr 41639672Sdfr thseq = th->seq; 417 thack = th->ack; 418 } else { 419 /*fool gcc*/ 420 thseq = thack = threv = 0; 421 } 422 if (hlen > length) { 423 (void)printf(" [bad hdr length %u - too long, > %u]", 424 hlen, length); 425 return; 426 } 427 428 if (IP_V(ip) == 4 && vflag && !Kflag && !fragmented) { 429 u_int16_t sum, tcp_sum; 430 if (TTEST2(tp->th_sport, length)) { 431 sum = tcp_cksum(ip, tp, length); 432 433 (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); 434 if (sum != 0) { 435 tcp_sum = EXTRACT_16BITS(&tp->th_sum); 436 (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum)); 437 } else 438 (void)printf(" (correct)"); 439 } 440 } 441#ifdef INET6 442 if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !Kflag && !fragmented) { 443 u_int16_t sum,tcp_sum; 444 if (TTEST2(tp->th_sport, length)) { 445 sum = tcp6_cksum(ip6, tp, length); 446 (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); 447 if (sum != 0) { 448 tcp_sum = EXTRACT_16BITS(&tp->th_sum); 449 (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum)); 450 } else 451 (void)printf(" (correct)"); 452 453 } 454 } 455#endif 456 457 length -= hlen; 458 if (vflag > 1 || flags & (TH_SYN | TH_FIN | TH_RST)) { 459 (void)printf(", seq %u", seq); 460 461 if (length > 0) { 462 (void)printf(":%u", seq + length); 463 } 464 } 465 466 if (flags & TH_ACK) { 467 (void)printf(", ack %u", ack); 468 } 469 470 (void)printf(", win %d", win); 471 472 if (flags & TH_URG) 473 (void)printf(", urg %d", urp); 474 /* 475 * Handle any options. 476 */ 477 if (hlen > sizeof(*tp)) { 478 register const u_char *cp; 479 register u_int i, opt, datalen; 480 register u_int len; 481 482 hlen -= sizeof(*tp); 483 cp = (const u_char *)tp + sizeof(*tp); 484 printf(", options ["); 485 while (hlen > 0) { 486 if (ch != '\0') 487 putchar(ch); 488 TCHECK(*cp); 489 opt = *cp++; 490 if (ZEROLENOPT(opt)) 491 len = 1; 492 else { 493 TCHECK(*cp); 494 len = *cp++; /* total including type, len */ 495 if (len < 2 || len > hlen) 496 goto bad; 497 --hlen; /* account for length byte */ 498 } 499 --hlen; /* account for type byte */ 500 datalen = 0; 501 502/* Bail if "l" bytes of data are not left or were not captured */ 503#define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); } 504 505 506 printf("%s", tok2str(tcp_option_values, "Unknown Option %u", opt)); 507 508 switch (opt) { 509 510 case TCPOPT_MAXSEG: 511 datalen = 2; 512 LENCHECK(datalen); 513 (void)printf(" %u", EXTRACT_16BITS(cp)); 514 break; 515 516 case TCPOPT_WSCALE: 517 datalen = 1; 518 LENCHECK(datalen); 519 (void)printf(" %u", *cp); 520 break; 521 522 case TCPOPT_SACK: 523 datalen = len - 2; 524 if (datalen % 8 != 0) { 525 (void)printf("malformed sack"); 526 } else { 527 u_int32_t s, e; 528 529 (void)printf(" %d ", datalen / 8); 530 for (i = 0; i < datalen; i += 8) { 531 LENCHECK(i + 4); 532 s = EXTRACT_32BITS(cp + i); 533 LENCHECK(i + 8); 534 e = EXTRACT_32BITS(cp + i + 4); 535 if (threv) { 536 s -= thseq; 537 e -= thseq; 538 } else { 539 s -= thack; 540 e -= thack; 541 } 542 (void)printf("{%u:%u}", s, e); 543 } 544 } 545 break; 546 547 case TCPOPT_CC: 548 case TCPOPT_CCNEW: 549 case TCPOPT_CCECHO: 550 case TCPOPT_ECHO: 551 case TCPOPT_ECHOREPLY: 552 553 /* 554 * those options share their semantics. 555 * fall through 556 */ 557 datalen = 4; 558 LENCHECK(datalen); 559 (void)printf(" %u", EXTRACT_32BITS(cp)); 560 break; 561 562 case TCPOPT_TIMESTAMP: 563 datalen = 8; 564 LENCHECK(datalen); 565 (void)printf(" val %u ecr %u", 566 EXTRACT_32BITS(cp), 567 EXTRACT_32BITS(cp + 4)); 568 break; 569 570 case TCPOPT_SIGNATURE: 571 datalen = TCP_SIGLEN; 572 LENCHECK(datalen); 573#ifdef HAVE_LIBCRYPTO 574 switch (tcp_verify_signature(ip, tp, 575 bp + TH_OFF(tp) * 4, length, cp)) { 576 577 case SIGNATURE_VALID: 578 (void)printf("valid"); 579 break; 580 581 case SIGNATURE_INVALID: 582 (void)printf("invalid"); 583 break; 584 585 case CANT_CHECK_SIGNATURE: 586 (void)printf("can't check - "); 587 for (i = 0; i < TCP_SIGLEN; ++i) 588 (void)printf("%02x", cp[i]); 589 break; 590 } 591#else 592 for (i = 0; i < TCP_SIGLEN; ++i) 593 (void)printf("%02x", cp[i]); 594#endif 595 break; 596 597 case TCPOPT_AUTH: 598 (void)printf("keyid %d", *cp++); 599 datalen = len - 3; 600 for (i = 0; i < datalen; ++i) { 601 LENCHECK(i); 602 (void)printf("%02x", cp[i]); 603 } 604 break; 605 606 607 case TCPOPT_EOL: 608 case TCPOPT_NOP: 609 case TCPOPT_SACKOK: 610 /* 611 * Nothing interesting. 612 * fall through 613 */ 614 break; 615 616 default: 617 datalen = len - 2; 618 for (i = 0; i < datalen; ++i) { 619 LENCHECK(i); 620 (void)printf("%02x", cp[i]); 621 } 622 break; 623 } 624 625 /* Account for data printed */ 626 cp += datalen; 627 hlen -= datalen; 628 629 /* Check specification against observed length */ 630 ++datalen; /* option octet */ 631 if (!ZEROLENOPT(opt)) 632 ++datalen; /* size octet */ 633 if (datalen != len) 634 (void)printf("[len %d]", len); 635 ch = ','; 636 if (opt == TCPOPT_EOL) 637 break; 638 } 639 putchar(']'); 640 } 641 642 /* 643 * Print length field before crawling down the stack. 644 */ 645 printf(", length %u", length); 646 647 if (length <= 0) 648 return; 649 650 /* 651 * Decode payload if necessary. 652 */ 653 bp += TH_OFF(tp) * 4; 654 if ((flags & TH_RST) && vflag) { 655 print_tcp_rst_data(bp, length); 656 return; 657 } 658 659 if (sport == TELNET_PORT || dport == TELNET_PORT) { 660 if (!qflag && vflag) 661 telnet_print(bp, length); 662 } else if (sport == BGP_PORT || dport == BGP_PORT) 663 bgp_print(bp, length); 664 else if (sport == PPTP_PORT || dport == PPTP_PORT) 665 pptp_print(bp); 666#ifdef TCPDUMP_DO_SMB 667 else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT) 668 nbt_tcp_print(bp, length); 669 else if (sport == SMB_PORT || dport == SMB_PORT) 670 smb_tcp_print(bp, length); 671#endif 672 else if (sport == BEEP_PORT || dport == BEEP_PORT) 673 beep_print(bp, length); 674 else if (length > 2 && 675 (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT || 676 sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) { 677 /* 678 * TCP DNS query has 2byte length at the head. 679 * XXX packet could be unaligned, it can go strange 680 */ 681 ns_print(bp + 2, length - 2, 0); 682 } else if (sport == MSDP_PORT || dport == MSDP_PORT) { 683 msdp_print(bp, length); 684 } 685 else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) { 686 ldp_print(bp, length); 687 } 688 689 return; 690 bad: 691 fputs("[bad opt]", stdout); 692 if (ch != '\0') 693 putchar('>'); 694 return; 695 trunc: 696 fputs("[|tcp]", stdout); 697 if (ch != '\0') 698 putchar('>'); 699} 700 701/* 702 * RFC1122 says the following on data in RST segments: 703 * 704 * 4.2.2.12 RST Segment: RFC-793 Section 3.4 705 * 706 * A TCP SHOULD allow a received RST segment to include data. 707 * 708 * DISCUSSION 709 * It has been suggested that a RST segment could contain 710 * ASCII text that encoded and explained the cause of the 711 * RST. No standard has yet been established for such 712 * data. 713 * 714 */ 715 716static void 717print_tcp_rst_data(register const u_char *sp, u_int length) 718{ 719 int c; 720 721 if (TTEST2(*sp, length)) 722 printf(" [RST"); 723 else 724 printf(" [!RST"); 725 if (length > MAX_RST_DATA_LEN) { 726 length = MAX_RST_DATA_LEN; /* can use -X for longer */ 727 putchar('+'); /* indicate we truncate */ 728 } 729 putchar(' '); 730 while (length-- && sp <= snapend) { 731 c = *sp++; 732 safeputchar(c); 733 } 734 putchar(']'); 735} 736 737#ifdef HAVE_LIBCRYPTO 738static int 739tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp, 740 const u_char *data, int length, const u_char *rcvsig) 741{ 742 struct tcphdr tp1; 743 u_char sig[TCP_SIGLEN]; 744 char zero_proto = 0; 745 MD5_CTX ctx; 746 u_int16_t savecsum, tlen; 747#ifdef INET6 748 struct ip6_hdr *ip6; 749 u_int32_t len32; 750 u_int8_t nxt; 751#endif 752 753 tp1 = *tp; 754 755 if (tcpmd5secret == NULL) 756 return (CANT_CHECK_SIGNATURE); 757 758 MD5_Init(&ctx); 759 /* 760 * Step 1: Update MD5 hash with IP pseudo-header. 761 */ 762 if (IP_V(ip) == 4) { 763 MD5_Update(&ctx, (char *)&ip->ip_src, sizeof(ip->ip_src)); 764 MD5_Update(&ctx, (char *)&ip->ip_dst, sizeof(ip->ip_dst)); 765 MD5_Update(&ctx, (char *)&zero_proto, sizeof(zero_proto)); 766 MD5_Update(&ctx, (char *)&ip->ip_p, sizeof(ip->ip_p)); 767 tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4; 768 tlen = htons(tlen); 769 MD5_Update(&ctx, (char *)&tlen, sizeof(tlen)); 770#ifdef INET6 771 } else if (IP_V(ip) == 6) { 772 ip6 = (struct ip6_hdr *)ip; 773 MD5_Update(&ctx, (char *)&ip6->ip6_src, sizeof(ip6->ip6_src)); 774 MD5_Update(&ctx, (char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst)); 775 len32 = htonl(ntohs(ip6->ip6_plen)); 776 MD5_Update(&ctx, (char *)&len32, sizeof(len32)); 777 nxt = 0; 778 MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); 779 MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); 780 MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); 781 nxt = IPPROTO_TCP; 782 MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); 783#endif 784 } else 785 return (CANT_CHECK_SIGNATURE); 786 787 /* 788 * Step 2: Update MD5 hash with TCP header, excluding options. 789 * The TCP checksum must be set to zero. 790 */ 791 savecsum = tp1.th_sum; 792 tp1.th_sum = 0; 793 MD5_Update(&ctx, (char *)&tp1, sizeof(struct tcphdr)); 794 tp1.th_sum = savecsum; 795 /* 796 * Step 3: Update MD5 hash with TCP segment data, if present. 797 */ 798 if (length > 0) 799 MD5_Update(&ctx, data, length); 800 /* 801 * Step 4: Update MD5 hash with shared secret. 802 */ 803 MD5_Update(&ctx, tcpmd5secret, strlen(tcpmd5secret)); 804 MD5_Final(sig, &ctx); 805 806 if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0) 807 return (SIGNATURE_VALID); 808 else 809 return (SIGNATURE_INVALID); 810} 811#endif /* HAVE_LIBCRYPTO */ 812 813/* 814 * Local Variables: 815 * c-style: whitesmith 816 * c-basic-offset: 8 817 * End: 818 */ 819