14edb46e9SPaul Traina /* 24644f044SBill Fenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 34edb46e9SPaul Traina * The Regents of the University of California. All rights reserved. 44edb46e9SPaul Traina * 51de50e9fSSam Leffler * Copyright (c) 1999-2004 The tcpdump.org project 61de50e9fSSam Leffler * 74edb46e9SPaul Traina * Redistribution and use in source and binary forms, with or without 84edb46e9SPaul Traina * modification, are permitted provided that: (1) source code distributions 94edb46e9SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 104edb46e9SPaul Traina * distributions including binary code include the above copyright notice and 114edb46e9SPaul Traina * this paragraph in its entirety in the documentation or other materials 124edb46e9SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 134edb46e9SPaul Traina * features or use of this software display the following acknowledgement: 144edb46e9SPaul Traina * ``This product includes software developed by the University of California, 154edb46e9SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 164edb46e9SPaul Traina * the University nor the names of its contributors may be used to endorse 174edb46e9SPaul Traina * or promote products derived from this software without specific prior 184edb46e9SPaul Traina * written permission. 194edb46e9SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 204edb46e9SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 214edb46e9SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 224edb46e9SPaul Traina */ 234edb46e9SPaul Traina 244edb46e9SPaul Traina #ifndef lint 255b0fe478SBruce M Simpson static const char rcsid[] _U_ = 261de50e9fSSam Leffler "@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.120 2005/04/06 18:53:56 mcr Exp $ (LBL)"; 27b0453382SBill Fenner #endif 28b0453382SBill Fenner 29b0453382SBill Fenner #ifdef HAVE_CONFIG_H 30b0453382SBill Fenner #include "config.h" 314edb46e9SPaul Traina #endif 324edb46e9SPaul Traina 335b0fe478SBruce M Simpson #include <tcpdump-stdinc.h> 344edb46e9SPaul Traina 354edb46e9SPaul Traina #include <stdio.h> 364edb46e9SPaul Traina #include <stdlib.h> 374edb46e9SPaul Traina #include <string.h> 384edb46e9SPaul Traina 394edb46e9SPaul Traina #include "interface.h" 404edb46e9SPaul Traina #include "addrtoname.h" 414edb46e9SPaul Traina #include "extract.h" 424edb46e9SPaul Traina 43685295f4SBill Fenner #include "tcp.h" 44685295f4SBill Fenner 45685295f4SBill Fenner #include "ip.h" 46685295f4SBill Fenner #ifdef INET6 47685295f4SBill Fenner #include "ip6.h" 48685295f4SBill Fenner #endif 495b0fe478SBruce M Simpson #include "ipproto.h" 501de50e9fSSam Leffler #include "rpc_auth.h" 511de50e9fSSam Leffler #include "rpc_msg.h" 52685295f4SBill Fenner 53a90e161bSBill Fenner #include "nameser.h" 54a90e161bSBill Fenner 551de50e9fSSam Leffler #ifdef HAVE_LIBCRYPTO 561de50e9fSSam Leffler #include <openssl/md5.h> 571de50e9fSSam Leffler 581de50e9fSSam Leffler #define SIGNATURE_VALID 0 591de50e9fSSam Leffler #define SIGNATURE_INVALID 1 601de50e9fSSam Leffler #define CANT_CHECK_SIGNATURE 2 611de50e9fSSam Leffler 621de50e9fSSam Leffler static int tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp, 631de50e9fSSam Leffler const u_char *data, int length, const u_char *rcvsig); 641de50e9fSSam Leffler #endif 651de50e9fSSam Leffler 66685295f4SBill Fenner static void print_tcp_rst_data(register const u_char *sp, u_int length); 67685295f4SBill Fenner 68685295f4SBill Fenner #define MAX_RST_DATA_LEN 30 69685295f4SBill Fenner 70685295f4SBill Fenner 714edb46e9SPaul Traina struct tha { 72b0453382SBill Fenner #ifndef INET6 734edb46e9SPaul Traina struct in_addr src; 744edb46e9SPaul Traina struct in_addr dst; 75b0453382SBill Fenner #else 76b0453382SBill Fenner struct in6_addr src; 77b0453382SBill Fenner struct in6_addr dst; 78b0453382SBill Fenner #endif /*INET6*/ 794edb46e9SPaul Traina u_int port; 804edb46e9SPaul Traina }; 814edb46e9SPaul Traina 824edb46e9SPaul Traina struct tcp_seq_hash { 834edb46e9SPaul Traina struct tcp_seq_hash *nxt; 844edb46e9SPaul Traina struct tha addr; 854edb46e9SPaul Traina tcp_seq seq; 864edb46e9SPaul Traina tcp_seq ack; 874edb46e9SPaul Traina }; 884edb46e9SPaul Traina 894edb46e9SPaul Traina #define TSEQ_HASHSIZE 919 904edb46e9SPaul Traina 914edb46e9SPaul Traina /* These tcp optinos do not have the size octet */ 924edb46e9SPaul Traina #define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP) 934edb46e9SPaul Traina 944edb46e9SPaul Traina static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE]; 954edb46e9SPaul Traina 964edb46e9SPaul Traina 97b0453382SBill Fenner #ifndef TELNET_PORT 98b0453382SBill Fenner #define TELNET_PORT 23 99b0453382SBill Fenner #endif 100b0453382SBill Fenner #ifndef BGP_PORT 101b0453382SBill Fenner #define BGP_PORT 179 102b0453382SBill Fenner #endif 103b0453382SBill Fenner #define NETBIOS_SSN_PORT 139 104a90e161bSBill Fenner #ifndef PPTP_PORT 105a90e161bSBill Fenner #define PPTP_PORT 1723 106a90e161bSBill Fenner #endif 107a90e161bSBill Fenner #define BEEP_PORT 10288 108685295f4SBill Fenner #ifndef NFS_PORT 109685295f4SBill Fenner #define NFS_PORT 2049 110685295f4SBill Fenner #endif 111a90e161bSBill Fenner #define MSDP_PORT 639 1125b0fe478SBruce M Simpson #define LDP_PORT 646 113685295f4SBill Fenner 114685295f4SBill Fenner static int tcp_cksum(register const struct ip *ip, 115685295f4SBill Fenner register const struct tcphdr *tp, 1165b0fe478SBruce M Simpson register u_int len) 117685295f4SBill Fenner { 118685295f4SBill Fenner union phu { 119685295f4SBill Fenner struct phdr { 120685295f4SBill Fenner u_int32_t src; 121685295f4SBill Fenner u_int32_t dst; 122685295f4SBill Fenner u_char mbz; 123685295f4SBill Fenner u_char proto; 124685295f4SBill Fenner u_int16_t len; 125685295f4SBill Fenner } ph; 126685295f4SBill Fenner u_int16_t pa[6]; 127685295f4SBill Fenner } phu; 128a90e161bSBill Fenner const u_int16_t *sp; 129685295f4SBill Fenner 130685295f4SBill Fenner /* pseudo-header.. */ 1315b0fe478SBruce M Simpson phu.ph.len = htons((u_int16_t)len); 132685295f4SBill Fenner phu.ph.mbz = 0; 133685295f4SBill Fenner phu.ph.proto = IPPROTO_TCP; 134685295f4SBill Fenner memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); 1355b0fe478SBruce M Simpson if (IP_HL(ip) == 5) 136685295f4SBill Fenner memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); 1375b0fe478SBruce M Simpson else 1385b0fe478SBruce M Simpson phu.ph.dst = ip_finddst(ip); 139685295f4SBill Fenner 140685295f4SBill Fenner sp = &phu.pa[0]; 141a90e161bSBill Fenner return in_cksum((u_short *)tp, len, 142a90e161bSBill Fenner sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]); 143685295f4SBill Fenner } 144685295f4SBill Fenner 145685295f4SBill Fenner #ifdef INET6 146685295f4SBill Fenner static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp, 1475b0fe478SBruce M Simpson u_int len) 148685295f4SBill Fenner { 1495b0fe478SBruce M Simpson size_t i; 150685295f4SBill Fenner register const u_int16_t *sp; 151685295f4SBill Fenner u_int32_t sum; 152685295f4SBill Fenner union { 153685295f4SBill Fenner struct { 154685295f4SBill Fenner struct in6_addr ph_src; 155685295f4SBill Fenner struct in6_addr ph_dst; 156685295f4SBill Fenner u_int32_t ph_len; 157685295f4SBill Fenner u_int8_t ph_zero[3]; 158685295f4SBill Fenner u_int8_t ph_nxt; 159685295f4SBill Fenner } ph; 160685295f4SBill Fenner u_int16_t pa[20]; 161685295f4SBill Fenner } phu; 162685295f4SBill Fenner 163685295f4SBill Fenner /* pseudo-header */ 164685295f4SBill Fenner memset(&phu, 0, sizeof(phu)); 165685295f4SBill Fenner phu.ph.ph_src = ip6->ip6_src; 166685295f4SBill Fenner phu.ph.ph_dst = ip6->ip6_dst; 1675b0fe478SBruce M Simpson phu.ph.ph_len = htonl(len); 168685295f4SBill Fenner phu.ph.ph_nxt = IPPROTO_TCP; 169685295f4SBill Fenner 170685295f4SBill Fenner sum = 0; 171685295f4SBill Fenner for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) 172685295f4SBill Fenner sum += phu.pa[i]; 173685295f4SBill Fenner 174685295f4SBill Fenner sp = (const u_int16_t *)tp; 175685295f4SBill Fenner 1765b0fe478SBruce M Simpson for (i = 0; i < (len & ~1); i += 2) 177685295f4SBill Fenner sum += *sp++; 178685295f4SBill Fenner 1795b0fe478SBruce M Simpson if (len & 1) 180685295f4SBill Fenner sum += htons((*(const u_int8_t *)sp) << 8); 181685295f4SBill Fenner 182685295f4SBill Fenner while (sum > 0xffff) 183685295f4SBill Fenner sum = (sum & 0xffff) + (sum >> 16); 184685295f4SBill Fenner sum = ~sum & 0xffff; 185685295f4SBill Fenner 186685295f4SBill Fenner return (sum); 187685295f4SBill Fenner } 188685295f4SBill Fenner #endif 189b0453382SBill Fenner 1904edb46e9SPaul Traina void 1914edb46e9SPaul Traina tcp_print(register const u_char *bp, register u_int length, 192685295f4SBill Fenner register const u_char *bp2, int fragmented) 1934edb46e9SPaul Traina { 1944edb46e9SPaul Traina register const struct tcphdr *tp; 1954edb46e9SPaul Traina register const struct ip *ip; 1964edb46e9SPaul Traina register u_char flags; 1975b0fe478SBruce M Simpson register u_int hlen; 1984edb46e9SPaul Traina register char ch; 199685295f4SBill Fenner u_int16_t sport, dport, win, urp; 200b0453382SBill Fenner u_int32_t seq, ack, thseq, thack; 201b0453382SBill Fenner int threv; 202b0453382SBill Fenner #ifdef INET6 203b0453382SBill Fenner register const struct ip6_hdr *ip6; 204b0453382SBill Fenner #endif 2054edb46e9SPaul Traina 2064edb46e9SPaul Traina tp = (struct tcphdr *)bp; 2074edb46e9SPaul Traina ip = (struct ip *)bp2; 208b0453382SBill Fenner #ifdef INET6 209685295f4SBill Fenner if (IP_V(ip) == 6) 210b0453382SBill Fenner ip6 = (struct ip6_hdr *)bp2; 211b0453382SBill Fenner else 212b0453382SBill Fenner ip6 = NULL; 213b0453382SBill Fenner #endif /*INET6*/ 2144edb46e9SPaul Traina ch = '\0'; 215b0453382SBill Fenner if (!TTEST(tp->th_dport)) { 216b0453382SBill Fenner (void)printf("%s > %s: [|tcp]", 217b0453382SBill Fenner ipaddr_string(&ip->ip_src), 218b0453382SBill Fenner ipaddr_string(&ip->ip_dst)); 2194edb46e9SPaul Traina return; 2204edb46e9SPaul Traina } 2214edb46e9SPaul Traina 2225b0fe478SBruce M Simpson sport = EXTRACT_16BITS(&tp->th_sport); 2235b0fe478SBruce M Simpson dport = EXTRACT_16BITS(&tp->th_dport); 224b0453382SBill Fenner 225685295f4SBill Fenner hlen = TH_OFF(tp) * 4; 226685295f4SBill Fenner 227685295f4SBill Fenner /* 2281de50e9fSSam Leffler * If data present, header length valid, and NFS port used, 2291de50e9fSSam Leffler * assume NFS. 230685295f4SBill Fenner * Pass offset of data plus 4 bytes for RPC TCP msg length 231685295f4SBill Fenner * to NFS print routines. 232685295f4SBill Fenner */ 2331de50e9fSSam Leffler if (!qflag && hlen >= sizeof(*tp) && hlen <= length) { 2341de50e9fSSam Leffler if ((u_char *)tp + 4 + sizeof(struct sunrpc_msg) <= snapend && 235685295f4SBill Fenner dport == NFS_PORT) { 236685295f4SBill Fenner nfsreq_print((u_char *)tp + hlen + 4, length - hlen, 237685295f4SBill Fenner (u_char *)ip); 238685295f4SBill Fenner return; 2391de50e9fSSam Leffler } else if ((u_char *)tp + 4 + sizeof(struct sunrpc_msg) 240685295f4SBill Fenner <= snapend && 241685295f4SBill Fenner sport == NFS_PORT) { 242685295f4SBill Fenner nfsreply_print((u_char *)tp + hlen + 4, length - hlen, 243685295f4SBill Fenner (u_char *)ip); 244685295f4SBill Fenner return; 245685295f4SBill Fenner } 246685295f4SBill Fenner } 247b0453382SBill Fenner #ifdef INET6 248b0453382SBill Fenner if (ip6) { 249b0453382SBill Fenner if (ip6->ip6_nxt == IPPROTO_TCP) { 250b0453382SBill Fenner (void)printf("%s.%s > %s.%s: ", 251b0453382SBill Fenner ip6addr_string(&ip6->ip6_src), 252b0453382SBill Fenner tcpport_string(sport), 253b0453382SBill Fenner ip6addr_string(&ip6->ip6_dst), 254b0453382SBill Fenner tcpport_string(dport)); 255b0453382SBill Fenner } else { 256b0453382SBill Fenner (void)printf("%s > %s: ", 257b0453382SBill Fenner tcpport_string(sport), tcpport_string(dport)); 258b0453382SBill Fenner } 259b0453382SBill Fenner } else 260b0453382SBill Fenner #endif /*INET6*/ 261b0453382SBill Fenner { 262b0453382SBill Fenner if (ip->ip_p == IPPROTO_TCP) { 263b0453382SBill Fenner (void)printf("%s.%s > %s.%s: ", 264b0453382SBill Fenner ipaddr_string(&ip->ip_src), 265b0453382SBill Fenner tcpport_string(sport), 266b0453382SBill Fenner ipaddr_string(&ip->ip_dst), 267b0453382SBill Fenner tcpport_string(dport)); 268b0453382SBill Fenner } else { 269b0453382SBill Fenner (void)printf("%s > %s: ", 270b0453382SBill Fenner tcpport_string(sport), tcpport_string(dport)); 271b0453382SBill Fenner } 272b0453382SBill Fenner } 273b0453382SBill Fenner 2741de50e9fSSam Leffler if (hlen < sizeof(*tp)) { 2751de50e9fSSam Leffler (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]", 2761de50e9fSSam Leffler length - hlen, hlen, (unsigned long)sizeof(*tp)); 2771de50e9fSSam Leffler return; 2781de50e9fSSam Leffler } 2791de50e9fSSam Leffler 280b0453382SBill Fenner TCHECK(*tp); 281b0453382SBill Fenner 2825b0fe478SBruce M Simpson seq = EXTRACT_32BITS(&tp->th_seq); 2835b0fe478SBruce M Simpson ack = EXTRACT_32BITS(&tp->th_ack); 2845b0fe478SBruce M Simpson win = EXTRACT_16BITS(&tp->th_win); 2855b0fe478SBruce M Simpson urp = EXTRACT_16BITS(&tp->th_urp); 2864edb46e9SPaul Traina 2874edb46e9SPaul Traina if (qflag) { 2881de50e9fSSam Leffler (void)printf("tcp %d", length - hlen); 2891de50e9fSSam Leffler if (hlen > length) { 2901de50e9fSSam Leffler (void)printf(" [bad hdr length %u - too long, > %u]", 2911de50e9fSSam Leffler hlen, length); 2921de50e9fSSam Leffler } 2934edb46e9SPaul Traina return; 2944edb46e9SPaul Traina } 295685295f4SBill Fenner if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH| 296685295f4SBill Fenner TH_ECNECHO|TH_CWR)) { 2974edb46e9SPaul Traina if (flags & TH_SYN) 2984edb46e9SPaul Traina putchar('S'); 2994edb46e9SPaul Traina if (flags & TH_FIN) 3004edb46e9SPaul Traina putchar('F'); 3014edb46e9SPaul Traina if (flags & TH_RST) 3024edb46e9SPaul Traina putchar('R'); 3034edb46e9SPaul Traina if (flags & TH_PUSH) 3044edb46e9SPaul Traina putchar('P'); 305685295f4SBill Fenner if (flags & TH_CWR) 306685295f4SBill Fenner putchar('W'); /* congestion _W_indow reduced (ECN) */ 307685295f4SBill Fenner if (flags & TH_ECNECHO) 308685295f4SBill Fenner putchar('E'); /* ecn _E_cho sent (ECN) */ 3094edb46e9SPaul Traina } else 3104edb46e9SPaul Traina putchar('.'); 3114edb46e9SPaul Traina 3124edb46e9SPaul Traina if (!Sflag && (flags & TH_ACK)) { 3134edb46e9SPaul Traina register struct tcp_seq_hash *th; 3145b0fe478SBruce M Simpson const void *src, *dst; 3154edb46e9SPaul Traina register int rev; 3164edb46e9SPaul Traina struct tha tha; 3174edb46e9SPaul Traina /* 3184edb46e9SPaul Traina * Find (or record) the initial sequence numbers for 3194edb46e9SPaul Traina * this conversation. (we pick an arbitrary 3204edb46e9SPaul Traina * collating order so there's only one entry for 3214edb46e9SPaul Traina * both directions). 3224edb46e9SPaul Traina */ 323b0453382SBill Fenner #ifdef INET6 324685295f4SBill Fenner memset(&tha, 0, sizeof(tha)); 325b0453382SBill Fenner rev = 0; 326b0453382SBill Fenner if (ip6) { 3275b0fe478SBruce M Simpson src = &ip6->ip6_src; 3285b0fe478SBruce M Simpson dst = &ip6->ip6_dst; 329a90e161bSBill Fenner if (sport > dport) 330b0453382SBill Fenner rev = 1; 331a90e161bSBill Fenner else if (sport == dport) { 3325b0fe478SBruce M Simpson if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0) 333b0453382SBill Fenner rev = 1; 334b0453382SBill Fenner } 335b0453382SBill Fenner if (rev) { 3365b0fe478SBruce M Simpson memcpy(&tha.src, dst, sizeof ip6->ip6_dst); 3375b0fe478SBruce M Simpson memcpy(&tha.dst, src, sizeof ip6->ip6_src); 338b0453382SBill Fenner tha.port = dport << 16 | sport; 339b0453382SBill Fenner } else { 3405b0fe478SBruce M Simpson memcpy(&tha.dst, dst, sizeof ip6->ip6_dst); 3415b0fe478SBruce M Simpson memcpy(&tha.src, src, sizeof ip6->ip6_src); 342b0453382SBill Fenner tha.port = sport << 16 | dport; 343b0453382SBill Fenner } 344b0453382SBill Fenner } else { 3455b0fe478SBruce M Simpson src = &ip->ip_src; 3465b0fe478SBruce M Simpson dst = &ip->ip_dst; 3475b0fe478SBruce M Simpson if (sport > dport) 3485b0fe478SBruce M Simpson rev = 1; 3495b0fe478SBruce M Simpson else if (sport == dport) { 3505b0fe478SBruce M Simpson if (memcmp(src, dst, sizeof ip->ip_dst) > 0) 351b0453382SBill Fenner rev = 1; 352b0453382SBill Fenner } 353b0453382SBill Fenner if (rev) { 3545b0fe478SBruce M Simpson memcpy(&tha.src, dst, sizeof ip->ip_dst); 3555b0fe478SBruce M Simpson memcpy(&tha.dst, src, sizeof ip->ip_src); 356b0453382SBill Fenner tha.port = dport << 16 | sport; 357b0453382SBill Fenner } else { 3585b0fe478SBruce M Simpson memcpy(&tha.dst, dst, sizeof ip->ip_dst); 3595b0fe478SBruce M Simpson memcpy(&tha.src, src, sizeof ip->ip_src); 360b0453382SBill Fenner tha.port = sport << 16 | dport; 361b0453382SBill Fenner } 362b0453382SBill Fenner } 363b0453382SBill Fenner #else 3644edb46e9SPaul Traina rev = 0; 3655b0fe478SBruce M Simpson src = &ip->ip_src; 3665b0fe478SBruce M Simpson dst = &ip->ip_dst; 3675b0fe478SBruce M Simpson if (sport > dport) 3684edb46e9SPaul Traina rev = 1; 3695b0fe478SBruce M Simpson else if (sport == dport) { 3705b0fe478SBruce M Simpson if (memcmp(src, dst, sizeof ip->ip_dst) > 0) 3715b0fe478SBruce M Simpson rev = 1; 3725b0fe478SBruce M Simpson } 3735b0fe478SBruce M Simpson if (rev) { 3745b0fe478SBruce M Simpson memcpy(&tha.src, dst, sizeof ip->ip_dst); 3755b0fe478SBruce M Simpson memcpy(&tha.dst, src, sizeof ip->ip_src); 3765b0fe478SBruce M Simpson tha.port = dport << 16 | sport; 3775b0fe478SBruce M Simpson } else { 3785b0fe478SBruce M Simpson memcpy(&tha.dst, dst, sizeof ip->ip_dst); 3795b0fe478SBruce M Simpson memcpy(&tha.src, src, sizeof ip->ip_src); 3805b0fe478SBruce M Simpson tha.port = sport << 16 | dport; 3814edb46e9SPaul Traina } 382b0453382SBill Fenner #endif 3834edb46e9SPaul Traina 384b0453382SBill Fenner threv = rev; 3854edb46e9SPaul Traina for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; 3864edb46e9SPaul Traina th->nxt; th = th->nxt) 3875b0fe478SBruce M Simpson if (memcmp((char *)&tha, (char *)&th->addr, 3885b0fe478SBruce M Simpson sizeof(th->addr)) == 0) 3894edb46e9SPaul Traina break; 3904edb46e9SPaul Traina 391685295f4SBill Fenner if (!th->nxt || (flags & TH_SYN)) { 3924edb46e9SPaul Traina /* didn't find it or new conversation */ 3934edb46e9SPaul Traina if (th->nxt == NULL) { 3944edb46e9SPaul Traina th->nxt = (struct tcp_seq_hash *) 3954edb46e9SPaul Traina calloc(1, sizeof(*th)); 3964edb46e9SPaul Traina if (th->nxt == NULL) 3974edb46e9SPaul Traina error("tcp_print: calloc"); 3984edb46e9SPaul Traina } 3994edb46e9SPaul Traina th->addr = tha; 4004edb46e9SPaul Traina if (rev) 4014edb46e9SPaul Traina th->ack = seq, th->seq = ack - 1; 4024edb46e9SPaul Traina else 4034edb46e9SPaul Traina th->seq = seq, th->ack = ack - 1; 4044edb46e9SPaul Traina } else { 4054edb46e9SPaul Traina if (rev) 4064edb46e9SPaul Traina seq -= th->ack, ack -= th->seq; 4074edb46e9SPaul Traina else 4084edb46e9SPaul Traina seq -= th->seq, ack -= th->ack; 4094edb46e9SPaul Traina } 410685295f4SBill Fenner 411685295f4SBill Fenner thseq = th->seq; 412685295f4SBill Fenner thack = th->ack; 413685295f4SBill Fenner } else { 414685295f4SBill Fenner /*fool gcc*/ 415685295f4SBill Fenner thseq = thack = threv = 0; 4164edb46e9SPaul Traina } 4174de76e31SBill Fenner if (hlen > length) { 4181de50e9fSSam Leffler (void)printf(" [bad hdr length %u - too long, > %u]", 4191de50e9fSSam Leffler hlen, length); 4204de76e31SBill Fenner return; 4214de76e31SBill Fenner } 422685295f4SBill Fenner 423685295f4SBill Fenner if (IP_V(ip) == 4 && vflag && !fragmented) { 4245b0fe478SBruce M Simpson u_int16_t sum, tcp_sum; 425685295f4SBill Fenner if (TTEST2(tp->th_sport, length)) { 426685295f4SBill Fenner sum = tcp_cksum(ip, tp, length); 4271de50e9fSSam Leffler 4281de50e9fSSam Leffler (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); 4295b0fe478SBruce M Simpson if (sum != 0) { 4305b0fe478SBruce M Simpson tcp_sum = EXTRACT_16BITS(&tp->th_sum); 4311de50e9fSSam Leffler (void)printf(" (incorrect (-> 0x%04x),",in_cksum_shouldbe(tcp_sum, sum)); 4325b0fe478SBruce M Simpson } else 4331de50e9fSSam Leffler (void)printf(" (correct),"); 434685295f4SBill Fenner } 435685295f4SBill Fenner } 436685295f4SBill Fenner #ifdef INET6 437685295f4SBill Fenner if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !fragmented) { 4381de50e9fSSam Leffler u_int16_t sum,tcp_sum; 439685295f4SBill Fenner if (TTEST2(tp->th_sport, length)) { 440685295f4SBill Fenner sum = tcp6_cksum(ip6, tp, length); 4411de50e9fSSam Leffler (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); 4421de50e9fSSam Leffler if (sum != 0) { 4431de50e9fSSam Leffler tcp_sum = EXTRACT_16BITS(&tp->th_sum); 4441de50e9fSSam Leffler (void)printf(" (incorrect (-> 0x%04x),",in_cksum_shouldbe(tcp_sum, sum)); 4451de50e9fSSam Leffler } else 4461de50e9fSSam Leffler (void)printf(" (correct),"); 4471de50e9fSSam Leffler 448685295f4SBill Fenner } 449685295f4SBill Fenner } 450685295f4SBill Fenner #endif 451685295f4SBill Fenner 4524edb46e9SPaul Traina length -= hlen; 453b0453382SBill Fenner if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) 454a90e161bSBill Fenner (void)printf(" %u:%u(%u)", seq, seq + length, length); 4554edb46e9SPaul Traina if (flags & TH_ACK) 4564edb46e9SPaul Traina (void)printf(" ack %u", ack); 4574edb46e9SPaul Traina 4584edb46e9SPaul Traina (void)printf(" win %d", win); 4594edb46e9SPaul Traina 4604edb46e9SPaul Traina if (flags & TH_URG) 4614edb46e9SPaul Traina (void)printf(" urg %d", urp); 4624edb46e9SPaul Traina /* 4634edb46e9SPaul Traina * Handle any options. 4644edb46e9SPaul Traina */ 4655b0fe478SBruce M Simpson if (hlen > sizeof(*tp)) { 4664edb46e9SPaul Traina register const u_char *cp; 4675b0fe478SBruce M Simpson register u_int i, opt, datalen; 4685b0fe478SBruce M Simpson register u_int len; 4694edb46e9SPaul Traina 4705b0fe478SBruce M Simpson hlen -= sizeof(*tp); 4714edb46e9SPaul Traina cp = (const u_char *)tp + sizeof(*tp); 4724edb46e9SPaul Traina putchar(' '); 4734edb46e9SPaul Traina ch = '<'; 4744edb46e9SPaul Traina while (hlen > 0) { 4754edb46e9SPaul Traina putchar(ch); 4764de76e31SBill Fenner TCHECK(*cp); 4774edb46e9SPaul Traina opt = *cp++; 4784edb46e9SPaul Traina if (ZEROLENOPT(opt)) 4794edb46e9SPaul Traina len = 1; 4804edb46e9SPaul Traina else { 4814de76e31SBill Fenner TCHECK(*cp); 4824de76e31SBill Fenner len = *cp++; /* total including type, len */ 4834de76e31SBill Fenner if (len < 2 || len > hlen) 4844de76e31SBill Fenner goto bad; 4854de76e31SBill Fenner --hlen; /* account for length byte */ 4864edb46e9SPaul Traina } 4874de76e31SBill Fenner --hlen; /* account for type byte */ 4884edb46e9SPaul Traina datalen = 0; 4894de76e31SBill Fenner 4904de76e31SBill Fenner /* Bail if "l" bytes of data are not left or were not captured */ 4914de76e31SBill Fenner #define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); } 4924de76e31SBill Fenner 4934edb46e9SPaul Traina switch (opt) { 4944edb46e9SPaul Traina 4954edb46e9SPaul Traina case TCPOPT_MAXSEG: 4964edb46e9SPaul Traina (void)printf("mss"); 4974edb46e9SPaul Traina datalen = 2; 4984de76e31SBill Fenner LENCHECK(datalen); 4994edb46e9SPaul Traina (void)printf(" %u", EXTRACT_16BITS(cp)); 5004edb46e9SPaul Traina 5014edb46e9SPaul Traina break; 5024edb46e9SPaul Traina 5034edb46e9SPaul Traina case TCPOPT_EOL: 5044edb46e9SPaul Traina (void)printf("eol"); 5054edb46e9SPaul Traina break; 5064edb46e9SPaul Traina 5074edb46e9SPaul Traina case TCPOPT_NOP: 5084edb46e9SPaul Traina (void)printf("nop"); 5094edb46e9SPaul Traina break; 5104edb46e9SPaul Traina 5114edb46e9SPaul Traina case TCPOPT_WSCALE: 5124edb46e9SPaul Traina (void)printf("wscale"); 5134edb46e9SPaul Traina datalen = 1; 5144de76e31SBill Fenner LENCHECK(datalen); 5154edb46e9SPaul Traina (void)printf(" %u", *cp); 5164edb46e9SPaul Traina break; 5174edb46e9SPaul Traina 5184edb46e9SPaul Traina case TCPOPT_SACKOK: 5194edb46e9SPaul Traina (void)printf("sackOK"); 5204edb46e9SPaul Traina break; 5214edb46e9SPaul Traina 5224edb46e9SPaul Traina case TCPOPT_SACK: 5234edb46e9SPaul Traina (void)printf("sack"); 5244edb46e9SPaul Traina datalen = len - 2; 525b0453382SBill Fenner if (datalen % 8 != 0) { 526b0453382SBill Fenner (void)printf(" malformed sack "); 527b0453382SBill Fenner } else { 528b0453382SBill Fenner u_int32_t s, e; 529b0453382SBill Fenner 530b0453382SBill Fenner (void)printf(" sack %d ", datalen / 8); 531b0453382SBill Fenner for (i = 0; i < datalen; i += 8) { 5324de76e31SBill Fenner LENCHECK(i + 4); 533b0453382SBill Fenner s = EXTRACT_32BITS(cp + i); 534b0453382SBill Fenner LENCHECK(i + 8); 535b0453382SBill Fenner e = EXTRACT_32BITS(cp + i + 4); 536b0453382SBill Fenner if (threv) { 537b0453382SBill Fenner s -= thseq; 538b0453382SBill Fenner e -= thseq; 539b0453382SBill Fenner } else { 540b0453382SBill Fenner s -= thack; 541b0453382SBill Fenner e -= thack; 5424edb46e9SPaul Traina } 543b0453382SBill Fenner (void)printf("{%u:%u}", s, e); 544b0453382SBill Fenner } 545b0453382SBill Fenner (void)printf(" "); 546b0453382SBill Fenner } 5474edb46e9SPaul Traina break; 5484edb46e9SPaul Traina 5494edb46e9SPaul Traina case TCPOPT_ECHO: 5504edb46e9SPaul Traina (void)printf("echo"); 5514edb46e9SPaul Traina datalen = 4; 5524de76e31SBill Fenner LENCHECK(datalen); 5534edb46e9SPaul Traina (void)printf(" %u", EXTRACT_32BITS(cp)); 5544edb46e9SPaul Traina break; 5554edb46e9SPaul Traina 5564edb46e9SPaul Traina case TCPOPT_ECHOREPLY: 5574edb46e9SPaul Traina (void)printf("echoreply"); 5584edb46e9SPaul Traina datalen = 4; 5594de76e31SBill Fenner LENCHECK(datalen); 5604edb46e9SPaul Traina (void)printf(" %u", EXTRACT_32BITS(cp)); 5614edb46e9SPaul Traina break; 5624edb46e9SPaul Traina 5634edb46e9SPaul Traina case TCPOPT_TIMESTAMP: 5644edb46e9SPaul Traina (void)printf("timestamp"); 5654de76e31SBill Fenner datalen = 8; 5664de76e31SBill Fenner LENCHECK(4); 5674edb46e9SPaul Traina (void)printf(" %u", EXTRACT_32BITS(cp)); 5684de76e31SBill Fenner LENCHECK(datalen); 5694edb46e9SPaul Traina (void)printf(" %u", EXTRACT_32BITS(cp + 4)); 5704edb46e9SPaul Traina break; 5714edb46e9SPaul Traina 5724edb46e9SPaul Traina case TCPOPT_CC: 5734edb46e9SPaul Traina (void)printf("cc"); 5744edb46e9SPaul Traina datalen = 4; 5754de76e31SBill Fenner LENCHECK(datalen); 5764edb46e9SPaul Traina (void)printf(" %u", EXTRACT_32BITS(cp)); 5774edb46e9SPaul Traina break; 5784edb46e9SPaul Traina 5794edb46e9SPaul Traina case TCPOPT_CCNEW: 5804edb46e9SPaul Traina (void)printf("ccnew"); 5814edb46e9SPaul Traina datalen = 4; 5824de76e31SBill Fenner LENCHECK(datalen); 5834edb46e9SPaul Traina (void)printf(" %u", EXTRACT_32BITS(cp)); 5844edb46e9SPaul Traina break; 5854edb46e9SPaul Traina 5864edb46e9SPaul Traina case TCPOPT_CCECHO: 5874edb46e9SPaul Traina (void)printf("ccecho"); 5884edb46e9SPaul Traina datalen = 4; 5894de76e31SBill Fenner LENCHECK(datalen); 5904edb46e9SPaul Traina (void)printf(" %u", EXTRACT_32BITS(cp)); 5914edb46e9SPaul Traina break; 5924edb46e9SPaul Traina 5931de50e9fSSam Leffler case TCPOPT_SIGNATURE: 5941de50e9fSSam Leffler (void)printf("md5:"); 5951de50e9fSSam Leffler datalen = TCP_SIGLEN; 5961de50e9fSSam Leffler LENCHECK(datalen); 5971de50e9fSSam Leffler #ifdef HAVE_LIBCRYPTO 5981de50e9fSSam Leffler switch (tcp_verify_signature(ip, tp, 5991de50e9fSSam Leffler bp + TH_OFF(tp) * 4, length, cp)) { 6001de50e9fSSam Leffler 6011de50e9fSSam Leffler case SIGNATURE_VALID: 6021de50e9fSSam Leffler (void)printf("valid"); 6031de50e9fSSam Leffler break; 6041de50e9fSSam Leffler 6051de50e9fSSam Leffler case SIGNATURE_INVALID: 6061de50e9fSSam Leffler (void)printf("invalid"); 6071de50e9fSSam Leffler break; 6081de50e9fSSam Leffler 6091de50e9fSSam Leffler case CANT_CHECK_SIGNATURE: 6101de50e9fSSam Leffler (void)printf("can't check - "); 6111de50e9fSSam Leffler for (i = 0; i < TCP_SIGLEN; ++i) 6121de50e9fSSam Leffler (void)printf("%02x", cp[i]); 6131de50e9fSSam Leffler break; 6141de50e9fSSam Leffler } 6151de50e9fSSam Leffler #else 6161de50e9fSSam Leffler for (i = 0; i < TCP_SIGLEN; ++i) 6171de50e9fSSam Leffler (void)printf("%02x", cp[i]); 6181de50e9fSSam Leffler #endif 6191de50e9fSSam Leffler break; 6201de50e9fSSam Leffler 6214edb46e9SPaul Traina default: 6225b0fe478SBruce M Simpson (void)printf("opt-%u:", opt); 6234edb46e9SPaul Traina datalen = len - 2; 6244edb46e9SPaul Traina for (i = 0; i < datalen; ++i) { 6254de76e31SBill Fenner LENCHECK(i); 6264edb46e9SPaul Traina (void)printf("%02x", cp[i]); 6274edb46e9SPaul Traina } 6284edb46e9SPaul Traina break; 6294edb46e9SPaul Traina } 6304edb46e9SPaul Traina 6314edb46e9SPaul Traina /* Account for data printed */ 6324edb46e9SPaul Traina cp += datalen; 6334edb46e9SPaul Traina hlen -= datalen; 6344edb46e9SPaul Traina 6354edb46e9SPaul Traina /* Check specification against observed length */ 6364edb46e9SPaul Traina ++datalen; /* option octet */ 6374edb46e9SPaul Traina if (!ZEROLENOPT(opt)) 6384edb46e9SPaul Traina ++datalen; /* size octet */ 6394edb46e9SPaul Traina if (datalen != len) 6404edb46e9SPaul Traina (void)printf("[len %d]", len); 6414edb46e9SPaul Traina ch = ','; 6424de76e31SBill Fenner if (opt == TCPOPT_EOL) 6434de76e31SBill Fenner break; 6444edb46e9SPaul Traina } 6454edb46e9SPaul Traina putchar('>'); 6464edb46e9SPaul Traina } 647b0453382SBill Fenner 648b0453382SBill Fenner if (length <= 0) 649b0453382SBill Fenner return; 650b0453382SBill Fenner 651b0453382SBill Fenner /* 652b0453382SBill Fenner * Decode payload if necessary. 653b0453382SBill Fenner */ 654685295f4SBill Fenner bp += TH_OFF(tp) * 4; 655685295f4SBill Fenner if (flags & TH_RST) { 656685295f4SBill Fenner if (vflag) 657685295f4SBill Fenner print_tcp_rst_data(bp, length); 658685295f4SBill Fenner } else { 659685295f4SBill Fenner if (sport == TELNET_PORT || dport == TELNET_PORT) { 660685295f4SBill Fenner if (!qflag && vflag) 661b0453382SBill Fenner telnet_print(bp, length); 662685295f4SBill Fenner } else if (sport == BGP_PORT || dport == BGP_PORT) 663b0453382SBill Fenner bgp_print(bp, length); 664a90e161bSBill Fenner else if (sport == PPTP_PORT || dport == PPTP_PORT) 6655b0fe478SBruce M Simpson pptp_print(bp); 666a90e161bSBill Fenner #ifdef TCPDUMP_DO_SMB 667b0453382SBill Fenner else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT) 668b0453382SBill Fenner nbt_tcp_print(bp, length); 669a90e161bSBill Fenner #endif 670a90e161bSBill Fenner else if (sport == BEEP_PORT || dport == BEEP_PORT) 671a90e161bSBill Fenner beep_print(bp, length); 672a90e161bSBill Fenner else if (length > 2 && 6735b0fe478SBruce M Simpson (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT || 6745b0fe478SBruce M Simpson sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) { 675a90e161bSBill Fenner /* 676a90e161bSBill Fenner * TCP DNS query has 2byte length at the head. 677a90e161bSBill Fenner * XXX packet could be unaligned, it can go strange 678a90e161bSBill Fenner */ 6795b0fe478SBruce M Simpson ns_print(bp + 2, length - 2, 0); 680a90e161bSBill Fenner } else if (sport == MSDP_PORT || dport == MSDP_PORT) { 681a90e161bSBill Fenner msdp_print(bp, length); 682a90e161bSBill Fenner } 6831de50e9fSSam Leffler else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) { 6841de50e9fSSam Leffler ldp_print(bp, length); 6851de50e9fSSam Leffler } 686685295f4SBill Fenner } 6874edb46e9SPaul Traina return; 6884de76e31SBill Fenner bad: 6894de76e31SBill Fenner fputs("[bad opt]", stdout); 6904de76e31SBill Fenner if (ch != '\0') 6914de76e31SBill Fenner putchar('>'); 6924de76e31SBill Fenner return; 6934edb46e9SPaul Traina trunc: 6944edb46e9SPaul Traina fputs("[|tcp]", stdout); 6954edb46e9SPaul Traina if (ch != '\0') 6964edb46e9SPaul Traina putchar('>'); 6974edb46e9SPaul Traina } 6984edb46e9SPaul Traina 699685295f4SBill Fenner /* 700685295f4SBill Fenner * RFC1122 says the following on data in RST segments: 701685295f4SBill Fenner * 702685295f4SBill Fenner * 4.2.2.12 RST Segment: RFC-793 Section 3.4 703685295f4SBill Fenner * 704685295f4SBill Fenner * A TCP SHOULD allow a received RST segment to include data. 705685295f4SBill Fenner * 706685295f4SBill Fenner * DISCUSSION 707685295f4SBill Fenner * It has been suggested that a RST segment could contain 708685295f4SBill Fenner * ASCII text that encoded and explained the cause of the 709685295f4SBill Fenner * RST. No standard has yet been established for such 710685295f4SBill Fenner * data. 711685295f4SBill Fenner * 712685295f4SBill Fenner */ 713685295f4SBill Fenner 714685295f4SBill Fenner static void 715685295f4SBill Fenner print_tcp_rst_data(register const u_char *sp, u_int length) 716685295f4SBill Fenner { 717685295f4SBill Fenner int c; 718685295f4SBill Fenner 719685295f4SBill Fenner if (TTEST2(*sp, length)) 720685295f4SBill Fenner printf(" [RST"); 721685295f4SBill Fenner else 722685295f4SBill Fenner printf(" [!RST"); 723685295f4SBill Fenner if (length > MAX_RST_DATA_LEN) { 724685295f4SBill Fenner length = MAX_RST_DATA_LEN; /* can use -X for longer */ 725685295f4SBill Fenner putchar('+'); /* indicate we truncate */ 726685295f4SBill Fenner } 727685295f4SBill Fenner putchar(' '); 728685295f4SBill Fenner while (length-- && sp <= snapend) { 729685295f4SBill Fenner c = *sp++; 730a90e161bSBill Fenner safeputchar(c); 731685295f4SBill Fenner } 732685295f4SBill Fenner putchar(']'); 733685295f4SBill Fenner } 7341de50e9fSSam Leffler 7351de50e9fSSam Leffler #ifdef HAVE_LIBCRYPTO 7361de50e9fSSam Leffler static int 7371de50e9fSSam Leffler tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp, 7381de50e9fSSam Leffler const u_char *data, int length, const u_char *rcvsig) 7391de50e9fSSam Leffler { 7401de50e9fSSam Leffler struct tcphdr tp1; 7411de50e9fSSam Leffler char sig[TCP_SIGLEN]; 7421de50e9fSSam Leffler char zero_proto = 0; 7431de50e9fSSam Leffler MD5_CTX ctx; 7441de50e9fSSam Leffler u_int16_t savecsum, tlen; 7451de50e9fSSam Leffler #ifdef INET6 7461de50e9fSSam Leffler struct ip6_hdr *ip6; 7471de50e9fSSam Leffler #endif 7481de50e9fSSam Leffler u_int32_t len32; 7491de50e9fSSam Leffler u_int8_t nxt; 7501de50e9fSSam Leffler 7511de50e9fSSam Leffler tp1 = *tp; 7521de50e9fSSam Leffler 7531de50e9fSSam Leffler if (tcpmd5secret == NULL) 7541de50e9fSSam Leffler return (CANT_CHECK_SIGNATURE); 7551de50e9fSSam Leffler 7561de50e9fSSam Leffler MD5_Init(&ctx); 7571de50e9fSSam Leffler /* 7581de50e9fSSam Leffler * Step 1: Update MD5 hash with IP pseudo-header. 7591de50e9fSSam Leffler */ 7601de50e9fSSam Leffler if (IP_V(ip) == 4) { 7611de50e9fSSam Leffler MD5_Update(&ctx, (char *)&ip->ip_src, sizeof(ip->ip_src)); 7621de50e9fSSam Leffler MD5_Update(&ctx, (char *)&ip->ip_dst, sizeof(ip->ip_dst)); 7631de50e9fSSam Leffler MD5_Update(&ctx, (char *)&zero_proto, sizeof(zero_proto)); 7641de50e9fSSam Leffler MD5_Update(&ctx, (char *)&ip->ip_p, sizeof(ip->ip_p)); 7651de50e9fSSam Leffler tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4; 7661de50e9fSSam Leffler tlen = htons(tlen); 7671de50e9fSSam Leffler MD5_Update(&ctx, (char *)&tlen, sizeof(tlen)); 7681de50e9fSSam Leffler #ifdef INET6 7691de50e9fSSam Leffler } else if (IP_V(ip) == 6) { 7701de50e9fSSam Leffler ip6 = (struct ip6_hdr *)ip; 7711de50e9fSSam Leffler MD5_Update(&ctx, (char *)&ip6->ip6_src, sizeof(ip6->ip6_src)); 7721de50e9fSSam Leffler MD5_Update(&ctx, (char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst)); 7731de50e9fSSam Leffler len32 = htonl(ntohs(ip6->ip6_plen)); 7741de50e9fSSam Leffler MD5_Update(&ctx, (char *)&len32, sizeof(len32)); 7751de50e9fSSam Leffler nxt = 0; 7761de50e9fSSam Leffler MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); 7771de50e9fSSam Leffler MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); 7781de50e9fSSam Leffler MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); 7791de50e9fSSam Leffler nxt = IPPROTO_TCP; 7801de50e9fSSam Leffler MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); 7811de50e9fSSam Leffler #endif 7821de50e9fSSam Leffler } else 7831de50e9fSSam Leffler return (CANT_CHECK_SIGNATURE); 7841de50e9fSSam Leffler 7851de50e9fSSam Leffler /* 7861de50e9fSSam Leffler * Step 2: Update MD5 hash with TCP header, excluding options. 7871de50e9fSSam Leffler * The TCP checksum must be set to zero. 7881de50e9fSSam Leffler */ 7891de50e9fSSam Leffler savecsum = tp1.th_sum; 7901de50e9fSSam Leffler tp1.th_sum = 0; 7911de50e9fSSam Leffler MD5_Update(&ctx, (char *)&tp1, sizeof(struct tcphdr)); 7921de50e9fSSam Leffler tp1.th_sum = savecsum; 7931de50e9fSSam Leffler /* 7941de50e9fSSam Leffler * Step 3: Update MD5 hash with TCP segment data, if present. 7951de50e9fSSam Leffler */ 7961de50e9fSSam Leffler if (length > 0) 7971de50e9fSSam Leffler MD5_Update(&ctx, data, length); 7981de50e9fSSam Leffler /* 7991de50e9fSSam Leffler * Step 4: Update MD5 hash with shared secret. 8001de50e9fSSam Leffler */ 8011de50e9fSSam Leffler MD5_Update(&ctx, tcpmd5secret, strlen(tcpmd5secret)); 8021de50e9fSSam Leffler MD5_Final(sig, &ctx); 8031de50e9fSSam Leffler 8041de50e9fSSam Leffler if (memcmp(rcvsig, sig, 16)) 8051de50e9fSSam Leffler return (SIGNATURE_VALID); 8061de50e9fSSam Leffler else 8071de50e9fSSam Leffler return (SIGNATURE_INVALID); 8081de50e9fSSam Leffler } 8091de50e9fSSam Leffler #endif /* HAVE_LIBCRYPTO */ 810