1a5779b6eSRui Paulo /* $NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky Exp $ */ 2a5779b6eSRui Paulo 34edb46e9SPaul Traina /* 44644f044SBill Fenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 54edb46e9SPaul Traina * The Regents of the University of California. All rights reserved. 64edb46e9SPaul Traina * 71de50e9fSSam Leffler * Copyright (c) 1999-2004 The tcpdump.org project 81de50e9fSSam Leffler * 94edb46e9SPaul Traina * Redistribution and use in source and binary forms, with or without 104edb46e9SPaul Traina * modification, are permitted provided that: (1) source code distributions 114edb46e9SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 124edb46e9SPaul Traina * distributions including binary code include the above copyright notice and 134edb46e9SPaul Traina * this paragraph in its entirety in the documentation or other materials 144edb46e9SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 154edb46e9SPaul Traina * features or use of this software display the following acknowledgement: 164edb46e9SPaul Traina * ``This product includes software developed by the University of California, 174edb46e9SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 184edb46e9SPaul Traina * the University nor the names of its contributors may be used to endorse 194edb46e9SPaul Traina * or promote products derived from this software without specific prior 204edb46e9SPaul Traina * written permission. 214edb46e9SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 224edb46e9SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 234edb46e9SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 244edb46e9SPaul Traina */ 254edb46e9SPaul Traina 263340d773SGleb Smirnoff /* \summary: TCP printer */ 273340d773SGleb Smirnoff 284edb46e9SPaul Traina #ifndef lint 29a5779b6eSRui Paulo #else 30a5779b6eSRui Paulo __RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $"); 31b0453382SBill Fenner #endif 32b0453382SBill Fenner 33b0453382SBill Fenner #ifdef HAVE_CONFIG_H 34b0453382SBill Fenner #include "config.h" 354edb46e9SPaul Traina #endif 364edb46e9SPaul Traina 373340d773SGleb Smirnoff #include <netdissect-stdinc.h> 384edb46e9SPaul Traina 394edb46e9SPaul Traina #include <stdlib.h> 404edb46e9SPaul Traina #include <string.h> 414edb46e9SPaul Traina 423340d773SGleb Smirnoff #include "netdissect.h" 434edb46e9SPaul Traina #include "addrtoname.h" 444edb46e9SPaul Traina #include "extract.h" 454edb46e9SPaul Traina 46685295f4SBill Fenner #include "tcp.h" 47685295f4SBill Fenner 48685295f4SBill Fenner #include "ip.h" 49685295f4SBill Fenner #include "ip6.h" 505b0fe478SBruce M Simpson #include "ipproto.h" 511de50e9fSSam Leffler #include "rpc_auth.h" 521de50e9fSSam Leffler #include "rpc_msg.h" 53685295f4SBill Fenner 541de50e9fSSam Leffler #ifdef HAVE_LIBCRYPTO 551de50e9fSSam Leffler #include <openssl/md5.h> 563340d773SGleb Smirnoff #include "signature.h" 571de50e9fSSam Leffler 583c602fabSXin LI static int tcp_verify_signature(netdissect_options *ndo, 593c602fabSXin LI const struct ip *ip, const struct tcphdr *tp, 601de50e9fSSam Leffler const u_char *data, int length, const u_char *rcvsig); 611de50e9fSSam Leffler #endif 621de50e9fSSam Leffler 633c602fabSXin LI static void print_tcp_rst_data(netdissect_options *, register const u_char *sp, u_int length); 643340d773SGleb Smirnoff static void print_tcp_fastopen_option(netdissect_options *ndo, register const u_char *cp, 653340d773SGleb Smirnoff u_int datalen, int exp); 66685295f4SBill Fenner 67685295f4SBill Fenner #define MAX_RST_DATA_LEN 30 68685295f4SBill Fenner 69685295f4SBill Fenner 704edb46e9SPaul Traina struct tha { 714edb46e9SPaul Traina struct in_addr src; 724edb46e9SPaul Traina struct in_addr dst; 734edb46e9SPaul Traina u_int port; 744edb46e9SPaul Traina }; 754edb46e9SPaul Traina 764edb46e9SPaul Traina struct tcp_seq_hash { 774edb46e9SPaul Traina struct tcp_seq_hash *nxt; 784edb46e9SPaul Traina struct tha addr; 794edb46e9SPaul Traina tcp_seq seq; 804edb46e9SPaul Traina tcp_seq ack; 814edb46e9SPaul Traina }; 824edb46e9SPaul Traina 833c602fabSXin LI struct tha6 { 843c602fabSXin LI struct in6_addr src; 853c602fabSXin LI struct in6_addr dst; 863c602fabSXin LI u_int port; 873c602fabSXin LI }; 883c602fabSXin LI 893c602fabSXin LI struct tcp_seq_hash6 { 903c602fabSXin LI struct tcp_seq_hash6 *nxt; 913c602fabSXin LI struct tha6 addr; 923c602fabSXin LI tcp_seq seq; 933c602fabSXin LI tcp_seq ack; 943c602fabSXin LI }; 953c602fabSXin LI 964edb46e9SPaul Traina #define TSEQ_HASHSIZE 919 974edb46e9SPaul Traina 984edb46e9SPaul Traina /* These tcp optinos do not have the size octet */ 994edb46e9SPaul Traina #define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP) 1004edb46e9SPaul Traina 1013c602fabSXin LI static struct tcp_seq_hash tcp_seq_hash4[TSEQ_HASHSIZE]; 1023c602fabSXin LI static struct tcp_seq_hash6 tcp_seq_hash6[TSEQ_HASHSIZE]; 1034edb46e9SPaul Traina 1043c602fabSXin LI static const struct tok tcp_flag_values[] = { 105a5779b6eSRui Paulo { TH_FIN, "F" }, 106a5779b6eSRui Paulo { TH_SYN, "S" }, 107a5779b6eSRui Paulo { TH_RST, "R" }, 108a5779b6eSRui Paulo { TH_PUSH, "P" }, 109a5779b6eSRui Paulo { TH_ACK, "." }, 110a5779b6eSRui Paulo { TH_URG, "U" }, 111a5779b6eSRui Paulo { TH_ECNECHO, "E" }, 112a5779b6eSRui Paulo { TH_CWR, "W" }, 113a5779b6eSRui Paulo { 0, NULL } 114a5779b6eSRui Paulo }; 1154edb46e9SPaul Traina 1163c602fabSXin LI static const struct tok tcp_option_values[] = { 117a5779b6eSRui Paulo { TCPOPT_EOL, "eol" }, 118a5779b6eSRui Paulo { TCPOPT_NOP, "nop" }, 119a5779b6eSRui Paulo { TCPOPT_MAXSEG, "mss" }, 120a5779b6eSRui Paulo { TCPOPT_WSCALE, "wscale" }, 121a5779b6eSRui Paulo { TCPOPT_SACKOK, "sackOK" }, 122a5779b6eSRui Paulo { TCPOPT_SACK, "sack" }, 123a5779b6eSRui Paulo { TCPOPT_ECHO, "echo" }, 124a5779b6eSRui Paulo { TCPOPT_ECHOREPLY, "echoreply" }, 125a5779b6eSRui Paulo { TCPOPT_TIMESTAMP, "TS" }, 126a5779b6eSRui Paulo { TCPOPT_CC, "cc" }, 127a5779b6eSRui Paulo { TCPOPT_CCNEW, "ccnew" }, 128a5779b6eSRui Paulo { TCPOPT_CCECHO, "" }, 129a5779b6eSRui Paulo { TCPOPT_SIGNATURE, "md5" }, 1303340d773SGleb Smirnoff { TCPOPT_SCPS, "scps" }, 131ce3ed1caSRui Paulo { TCPOPT_UTO, "uto" }, 1323340d773SGleb Smirnoff { TCPOPT_TCPAO, "tcp-ao" }, 1333c602fabSXin LI { TCPOPT_MPTCP, "mptcp" }, 1343340d773SGleb Smirnoff { TCPOPT_FASTOPEN, "tfo" }, 1353c602fabSXin LI { TCPOPT_EXPERIMENT2, "exp" }, 136a5779b6eSRui Paulo { 0, NULL } 137a5779b6eSRui Paulo }; 138685295f4SBill Fenner 1393c602fabSXin LI static int 1403c602fabSXin LI tcp_cksum(netdissect_options *ndo, 1413c602fabSXin LI register const struct ip *ip, 142685295f4SBill Fenner register const struct tcphdr *tp, 1435b0fe478SBruce M Simpson register u_int len) 144685295f4SBill Fenner { 1453c602fabSXin LI return nextproto4_cksum(ndo, ip, (const uint8_t *)tp, len, len, 1463c602fabSXin LI IPPROTO_TCP); 147685295f4SBill Fenner } 148685295f4SBill Fenner 1493340d773SGleb Smirnoff static int 1503340d773SGleb Smirnoff tcp6_cksum(netdissect_options *ndo, 1513340d773SGleb Smirnoff register const struct ip6_hdr *ip6, 1523340d773SGleb Smirnoff register const struct tcphdr *tp, 1533340d773SGleb Smirnoff register u_int len) 1543340d773SGleb Smirnoff { 1553340d773SGleb Smirnoff return nextproto6_cksum(ndo, ip6, (const uint8_t *)tp, len, len, 1563340d773SGleb Smirnoff IPPROTO_TCP); 1573340d773SGleb Smirnoff } 1583340d773SGleb Smirnoff 1594edb46e9SPaul Traina void 1603c602fabSXin LI tcp_print(netdissect_options *ndo, 1613c602fabSXin LI register const u_char *bp, register u_int length, 162685295f4SBill Fenner register const u_char *bp2, int fragmented) 1634edb46e9SPaul Traina { 1644edb46e9SPaul Traina register const struct tcphdr *tp; 1654edb46e9SPaul Traina register const struct ip *ip; 1664edb46e9SPaul Traina register u_char flags; 1675b0fe478SBruce M Simpson register u_int hlen; 1684edb46e9SPaul Traina register char ch; 1693c602fabSXin LI uint16_t sport, dport, win, urp; 1703c602fabSXin LI uint32_t seq, ack, thseq, thack; 17127df3f5dSRui Paulo u_int utoval; 1723c602fabSXin LI uint16_t magic; 1733c602fabSXin LI register int rev; 174b0453382SBill Fenner register const struct ip6_hdr *ip6; 1754edb46e9SPaul Traina 1763340d773SGleb Smirnoff tp = (const struct tcphdr *)bp; 1773340d773SGleb Smirnoff ip = (const struct ip *)bp2; 178685295f4SBill Fenner if (IP_V(ip) == 6) 1793340d773SGleb Smirnoff ip6 = (const struct ip6_hdr *)bp2; 180b0453382SBill Fenner else 181b0453382SBill Fenner ip6 = NULL; 1824edb46e9SPaul Traina ch = '\0'; 1833c602fabSXin LI if (!ND_TTEST(tp->th_dport)) { 1843c602fabSXin LI ND_PRINT((ndo, "%s > %s: [|tcp]", 1853c602fabSXin LI ipaddr_string(ndo, &ip->ip_src), 1863c602fabSXin LI ipaddr_string(ndo, &ip->ip_dst))); 1874edb46e9SPaul Traina return; 1884edb46e9SPaul Traina } 1894edb46e9SPaul Traina 1905b0fe478SBruce M Simpson sport = EXTRACT_16BITS(&tp->th_sport); 1915b0fe478SBruce M Simpson dport = EXTRACT_16BITS(&tp->th_dport); 192b0453382SBill Fenner 193b0453382SBill Fenner if (ip6) { 194b0453382SBill Fenner if (ip6->ip6_nxt == IPPROTO_TCP) { 1953c602fabSXin LI ND_PRINT((ndo, "%s.%s > %s.%s: ", 1963c602fabSXin LI ip6addr_string(ndo, &ip6->ip6_src), 1973340d773SGleb Smirnoff tcpport_string(ndo, sport), 1983c602fabSXin LI ip6addr_string(ndo, &ip6->ip6_dst), 1993340d773SGleb Smirnoff tcpport_string(ndo, dport))); 200b0453382SBill Fenner } else { 2013c602fabSXin LI ND_PRINT((ndo, "%s > %s: ", 2023340d773SGleb Smirnoff tcpport_string(ndo, sport), tcpport_string(ndo, dport))); 203b0453382SBill Fenner } 2043340d773SGleb Smirnoff } else { 205b0453382SBill Fenner if (ip->ip_p == IPPROTO_TCP) { 2063c602fabSXin LI ND_PRINT((ndo, "%s.%s > %s.%s: ", 2073c602fabSXin LI ipaddr_string(ndo, &ip->ip_src), 2083340d773SGleb Smirnoff tcpport_string(ndo, sport), 2093c602fabSXin LI ipaddr_string(ndo, &ip->ip_dst), 2103340d773SGleb Smirnoff tcpport_string(ndo, dport))); 211b0453382SBill Fenner } else { 2123c602fabSXin LI ND_PRINT((ndo, "%s > %s: ", 2133340d773SGleb Smirnoff tcpport_string(ndo, sport), tcpport_string(ndo, dport))); 214b0453382SBill Fenner } 215b0453382SBill Fenner } 216b0453382SBill Fenner 2173340d773SGleb Smirnoff ND_TCHECK(*tp); 2183340d773SGleb Smirnoff 2193340d773SGleb Smirnoff hlen = TH_OFF(tp) * 4; 2203340d773SGleb Smirnoff 2211de50e9fSSam Leffler if (hlen < sizeof(*tp)) { 2223c602fabSXin LI ND_PRINT((ndo, " tcp %d [bad hdr length %u - too short, < %lu]", 2233c602fabSXin LI length - hlen, hlen, (unsigned long)sizeof(*tp))); 2241de50e9fSSam Leffler return; 2251de50e9fSSam Leffler } 2261de50e9fSSam Leffler 2275b0fe478SBruce M Simpson seq = EXTRACT_32BITS(&tp->th_seq); 2285b0fe478SBruce M Simpson ack = EXTRACT_32BITS(&tp->th_ack); 2295b0fe478SBruce M Simpson win = EXTRACT_16BITS(&tp->th_win); 2305b0fe478SBruce M Simpson urp = EXTRACT_16BITS(&tp->th_urp); 2314edb46e9SPaul Traina 2323c602fabSXin LI if (ndo->ndo_qflag) { 2333c602fabSXin LI ND_PRINT((ndo, "tcp %d", length - hlen)); 2341de50e9fSSam Leffler if (hlen > length) { 2353c602fabSXin LI ND_PRINT((ndo, " [bad hdr length %u - too long, > %u]", 2363c602fabSXin LI hlen, length)); 2371de50e9fSSam Leffler } 2384edb46e9SPaul Traina return; 2394edb46e9SPaul Traina } 240a5779b6eSRui Paulo 241a5779b6eSRui Paulo flags = tp->th_flags; 2423c602fabSXin LI ND_PRINT((ndo, "Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags))); 2434edb46e9SPaul Traina 2443c602fabSXin LI if (!ndo->ndo_Sflag && (flags & TH_ACK)) { 2454edb46e9SPaul Traina /* 2464edb46e9SPaul Traina * Find (or record) the initial sequence numbers for 2474edb46e9SPaul Traina * this conversation. (we pick an arbitrary 2484edb46e9SPaul Traina * collating order so there's only one entry for 2494edb46e9SPaul Traina * both directions). 2504edb46e9SPaul Traina */ 251b0453382SBill Fenner rev = 0; 252b0453382SBill Fenner if (ip6) { 2533c602fabSXin LI register struct tcp_seq_hash6 *th; 2543c602fabSXin LI struct tcp_seq_hash6 *tcp_seq_hash; 2553340d773SGleb Smirnoff const struct in6_addr *src, *dst; 2563c602fabSXin LI struct tha6 tha; 2573c602fabSXin LI 2583c602fabSXin LI tcp_seq_hash = tcp_seq_hash6; 2595b0fe478SBruce M Simpson src = &ip6->ip6_src; 2605b0fe478SBruce M Simpson dst = &ip6->ip6_dst; 261a90e161bSBill Fenner if (sport > dport) 262b0453382SBill Fenner rev = 1; 263a90e161bSBill Fenner else if (sport == dport) { 2643c602fabSXin LI if (UNALIGNED_MEMCMP(src, dst, sizeof ip6->ip6_dst) > 0) 265b0453382SBill Fenner rev = 1; 266b0453382SBill Fenner } 267b0453382SBill Fenner if (rev) { 2683c602fabSXin LI UNALIGNED_MEMCPY(&tha.src, dst, sizeof ip6->ip6_dst); 2693c602fabSXin LI UNALIGNED_MEMCPY(&tha.dst, src, sizeof ip6->ip6_src); 27039e421e8SCy Schubert tha.port = ((u_int)dport) << 16 | sport; 271b0453382SBill Fenner } else { 2723c602fabSXin LI UNALIGNED_MEMCPY(&tha.dst, dst, sizeof ip6->ip6_dst); 2733c602fabSXin LI UNALIGNED_MEMCPY(&tha.src, src, sizeof ip6->ip6_src); 27439e421e8SCy Schubert tha.port = ((u_int)sport) << 16 | dport; 275b0453382SBill Fenner } 2764edb46e9SPaul Traina 2773c602fabSXin LI for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; 2783c602fabSXin LI th->nxt; th = th->nxt) 2793c602fabSXin LI if (memcmp((char *)&tha, (char *)&th->addr, 2803c602fabSXin LI sizeof(th->addr)) == 0) 2813c602fabSXin LI break; 2823c602fabSXin LI 2833c602fabSXin LI if (!th->nxt || (flags & TH_SYN)) { 2843c602fabSXin LI /* didn't find it or new conversation */ 2853c602fabSXin LI if (th->nxt == NULL) { 2863c602fabSXin LI th->nxt = (struct tcp_seq_hash6 *) 2873c602fabSXin LI calloc(1, sizeof(*th)); 2883c602fabSXin LI if (th->nxt == NULL) 2893340d773SGleb Smirnoff (*ndo->ndo_error)(ndo, 2903340d773SGleb Smirnoff "tcp_print: calloc"); 2913c602fabSXin LI } 2923c602fabSXin LI th->addr = tha; 2933c602fabSXin LI if (rev) 2943c602fabSXin LI th->ack = seq, th->seq = ack - 1; 2953c602fabSXin LI else 2963c602fabSXin LI th->seq = seq, th->ack = ack - 1; 2973c602fabSXin LI } else { 2983c602fabSXin LI if (rev) 2993c602fabSXin LI seq -= th->ack, ack -= th->seq; 3003c602fabSXin LI else 3013c602fabSXin LI seq -= th->seq, ack -= th->ack; 3023c602fabSXin LI } 3033c602fabSXin LI 3043c602fabSXin LI thseq = th->seq; 3053c602fabSXin LI thack = th->ack; 3063c602fabSXin LI } else { 3073c602fabSXin LI register struct tcp_seq_hash *th; 3083c602fabSXin LI struct tcp_seq_hash *tcp_seq_hash; 3093c602fabSXin LI struct tha tha; 3103c602fabSXin LI 3113c602fabSXin LI tcp_seq_hash = tcp_seq_hash4; 3123c602fabSXin LI if (sport > dport) 3133c602fabSXin LI rev = 1; 3143c602fabSXin LI else if (sport == dport) { 3153340d773SGleb Smirnoff if (UNALIGNED_MEMCMP(&ip->ip_src, &ip->ip_dst, sizeof ip->ip_dst) > 0) 3163c602fabSXin LI rev = 1; 3173c602fabSXin LI } 3183c602fabSXin LI if (rev) { 3193340d773SGleb Smirnoff UNALIGNED_MEMCPY(&tha.src, &ip->ip_dst, sizeof ip->ip_dst); 3203340d773SGleb Smirnoff UNALIGNED_MEMCPY(&tha.dst, &ip->ip_src, sizeof ip->ip_src); 32139e421e8SCy Schubert tha.port = ((u_int)dport) << 16 | sport; 3223c602fabSXin LI } else { 3233340d773SGleb Smirnoff UNALIGNED_MEMCPY(&tha.dst, &ip->ip_dst, sizeof ip->ip_dst); 3243340d773SGleb Smirnoff UNALIGNED_MEMCPY(&tha.src, &ip->ip_src, sizeof ip->ip_src); 32539e421e8SCy Schubert tha.port = ((u_int)sport) << 16 | dport; 3263c602fabSXin LI } 3273c602fabSXin LI 3284edb46e9SPaul Traina for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; 3294edb46e9SPaul Traina th->nxt; th = th->nxt) 3305b0fe478SBruce M Simpson if (memcmp((char *)&tha, (char *)&th->addr, 3315b0fe478SBruce M Simpson sizeof(th->addr)) == 0) 3324edb46e9SPaul Traina break; 3334edb46e9SPaul Traina 334685295f4SBill Fenner if (!th->nxt || (flags & TH_SYN)) { 3354edb46e9SPaul Traina /* didn't find it or new conversation */ 3364edb46e9SPaul Traina if (th->nxt == NULL) { 3374edb46e9SPaul Traina th->nxt = (struct tcp_seq_hash *) 3384edb46e9SPaul Traina calloc(1, sizeof(*th)); 3394edb46e9SPaul Traina if (th->nxt == NULL) 3403340d773SGleb Smirnoff (*ndo->ndo_error)(ndo, 3413340d773SGleb Smirnoff "tcp_print: calloc"); 3424edb46e9SPaul Traina } 3434edb46e9SPaul Traina th->addr = tha; 3444edb46e9SPaul Traina if (rev) 3454edb46e9SPaul Traina th->ack = seq, th->seq = ack - 1; 3464edb46e9SPaul Traina else 3474edb46e9SPaul Traina th->seq = seq, th->ack = ack - 1; 3484edb46e9SPaul Traina } else { 3494edb46e9SPaul Traina if (rev) 3504edb46e9SPaul Traina seq -= th->ack, ack -= th->seq; 3514edb46e9SPaul Traina else 3524edb46e9SPaul Traina seq -= th->seq, ack -= th->ack; 3534edb46e9SPaul Traina } 354685295f4SBill Fenner 355685295f4SBill Fenner thseq = th->seq; 356685295f4SBill Fenner thack = th->ack; 3573c602fabSXin LI } 358685295f4SBill Fenner } else { 359685295f4SBill Fenner /*fool gcc*/ 3603c602fabSXin LI thseq = thack = rev = 0; 3614edb46e9SPaul Traina } 3624de76e31SBill Fenner if (hlen > length) { 3633c602fabSXin LI ND_PRINT((ndo, " [bad hdr length %u - too long, > %u]", 3643c602fabSXin LI hlen, length)); 3654de76e31SBill Fenner return; 3664de76e31SBill Fenner } 367685295f4SBill Fenner 3683c602fabSXin LI if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) { 369cac3dcd5SXin LI /* Check the checksum, if possible. */ 3703c602fabSXin LI uint16_t sum, tcp_sum; 371cac3dcd5SXin LI 372cac3dcd5SXin LI if (IP_V(ip) == 4) { 3733c602fabSXin LI if (ND_TTEST2(tp->th_sport, length)) { 3743c602fabSXin LI sum = tcp_cksum(ndo, ip, tp, length); 3755b0fe478SBruce M Simpson tcp_sum = EXTRACT_16BITS(&tp->th_sum); 376cac3dcd5SXin LI 3773c602fabSXin LI ND_PRINT((ndo, ", cksum 0x%04x", tcp_sum)); 378cac3dcd5SXin LI if (sum != 0) 3793c602fabSXin LI ND_PRINT((ndo, " (incorrect -> 0x%04x)", 3803c602fabSXin LI in_cksum_shouldbe(tcp_sum, sum))); 381cac3dcd5SXin LI else 3823c602fabSXin LI ND_PRINT((ndo, " (correct)")); 383685295f4SBill Fenner } 3843340d773SGleb Smirnoff } else if (IP_V(ip) == 6 && ip6->ip6_plen) { 3853c602fabSXin LI if (ND_TTEST2(tp->th_sport, length)) { 3863340d773SGleb Smirnoff sum = tcp6_cksum(ndo, ip6, tp, length); 3871de50e9fSSam Leffler tcp_sum = EXTRACT_16BITS(&tp->th_sum); 388cac3dcd5SXin LI 3893c602fabSXin LI ND_PRINT((ndo, ", cksum 0x%04x", tcp_sum)); 390cac3dcd5SXin LI if (sum != 0) 3913c602fabSXin LI ND_PRINT((ndo, " (incorrect -> 0x%04x)", 3923c602fabSXin LI in_cksum_shouldbe(tcp_sum, sum))); 393cac3dcd5SXin LI else 3943c602fabSXin LI ND_PRINT((ndo, " (correct)")); 3951de50e9fSSam Leffler 396685295f4SBill Fenner } 397685295f4SBill Fenner } 398cac3dcd5SXin LI } 399685295f4SBill Fenner 4004edb46e9SPaul Traina length -= hlen; 4013c602fabSXin LI if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { 4023c602fabSXin LI ND_PRINT((ndo, ", seq %u", seq)); 4034edb46e9SPaul Traina 404a5779b6eSRui Paulo if (length > 0) { 4053c602fabSXin LI ND_PRINT((ndo, ":%u", seq + length)); 406a5779b6eSRui Paulo } 407a5779b6eSRui Paulo } 408a5779b6eSRui Paulo 409a5779b6eSRui Paulo if (flags & TH_ACK) { 4103c602fabSXin LI ND_PRINT((ndo, ", ack %u", ack)); 411a5779b6eSRui Paulo } 412a5779b6eSRui Paulo 4133c602fabSXin LI ND_PRINT((ndo, ", win %d", win)); 4144edb46e9SPaul Traina 4154edb46e9SPaul Traina if (flags & TH_URG) 4163c602fabSXin LI ND_PRINT((ndo, ", urg %d", urp)); 4174edb46e9SPaul Traina /* 4184edb46e9SPaul Traina * Handle any options. 4194edb46e9SPaul Traina */ 4205b0fe478SBruce M Simpson if (hlen > sizeof(*tp)) { 4214edb46e9SPaul Traina register const u_char *cp; 4225b0fe478SBruce M Simpson register u_int i, opt, datalen; 4235b0fe478SBruce M Simpson register u_int len; 4244edb46e9SPaul Traina 4255b0fe478SBruce M Simpson hlen -= sizeof(*tp); 4264edb46e9SPaul Traina cp = (const u_char *)tp + sizeof(*tp); 4273c602fabSXin LI ND_PRINT((ndo, ", options [")); 4284edb46e9SPaul Traina while (hlen > 0) { 429a5779b6eSRui Paulo if (ch != '\0') 4303c602fabSXin LI ND_PRINT((ndo, "%c", ch)); 4313c602fabSXin LI ND_TCHECK(*cp); 4324edb46e9SPaul Traina opt = *cp++; 4334edb46e9SPaul Traina if (ZEROLENOPT(opt)) 4344edb46e9SPaul Traina len = 1; 4354edb46e9SPaul Traina else { 4363c602fabSXin LI ND_TCHECK(*cp); 4374de76e31SBill Fenner len = *cp++; /* total including type, len */ 4384de76e31SBill Fenner if (len < 2 || len > hlen) 4394de76e31SBill Fenner goto bad; 4404de76e31SBill Fenner --hlen; /* account for length byte */ 4414edb46e9SPaul Traina } 4424de76e31SBill Fenner --hlen; /* account for type byte */ 4434edb46e9SPaul Traina datalen = 0; 4444de76e31SBill Fenner 4454de76e31SBill Fenner /* Bail if "l" bytes of data are not left or were not captured */ 4463c602fabSXin LI #define LENCHECK(l) { if ((l) > hlen) goto bad; ND_TCHECK2(*cp, l); } 4474de76e31SBill Fenner 448a5779b6eSRui Paulo 4493c602fabSXin LI ND_PRINT((ndo, "%s", tok2str(tcp_option_values, "unknown-%u", opt))); 450a5779b6eSRui Paulo 4514edb46e9SPaul Traina switch (opt) { 4524edb46e9SPaul Traina 4534edb46e9SPaul Traina case TCPOPT_MAXSEG: 4544edb46e9SPaul Traina datalen = 2; 4554de76e31SBill Fenner LENCHECK(datalen); 4563c602fabSXin LI ND_PRINT((ndo, " %u", EXTRACT_16BITS(cp))); 4574edb46e9SPaul Traina break; 4584edb46e9SPaul Traina 4594edb46e9SPaul Traina case TCPOPT_WSCALE: 4604edb46e9SPaul Traina datalen = 1; 4614de76e31SBill Fenner LENCHECK(datalen); 4623c602fabSXin LI ND_PRINT((ndo, " %u", *cp)); 4634edb46e9SPaul Traina break; 4644edb46e9SPaul Traina 4654edb46e9SPaul Traina case TCPOPT_SACK: 4664edb46e9SPaul Traina datalen = len - 2; 467b0453382SBill Fenner if (datalen % 8 != 0) { 4683340d773SGleb Smirnoff ND_PRINT((ndo, " invalid sack")); 469b0453382SBill Fenner } else { 4703c602fabSXin LI uint32_t s, e; 471b0453382SBill Fenner 4723c602fabSXin LI ND_PRINT((ndo, " %d ", datalen / 8)); 473b0453382SBill Fenner for (i = 0; i < datalen; i += 8) { 4744de76e31SBill Fenner LENCHECK(i + 4); 475b0453382SBill Fenner s = EXTRACT_32BITS(cp + i); 476b0453382SBill Fenner LENCHECK(i + 8); 477b0453382SBill Fenner e = EXTRACT_32BITS(cp + i + 4); 4783c602fabSXin LI if (rev) { 479b0453382SBill Fenner s -= thseq; 480b0453382SBill Fenner e -= thseq; 481b0453382SBill Fenner } else { 482b0453382SBill Fenner s -= thack; 483b0453382SBill Fenner e -= thack; 4844edb46e9SPaul Traina } 4853c602fabSXin LI ND_PRINT((ndo, "{%u:%u}", s, e)); 486b0453382SBill Fenner } 487b0453382SBill Fenner } 4884edb46e9SPaul Traina break; 4894edb46e9SPaul Traina 490a5779b6eSRui Paulo case TCPOPT_CC: 491a5779b6eSRui Paulo case TCPOPT_CCNEW: 492a5779b6eSRui Paulo case TCPOPT_CCECHO: 4934edb46e9SPaul Traina case TCPOPT_ECHO: 4944edb46e9SPaul Traina case TCPOPT_ECHOREPLY: 495a5779b6eSRui Paulo 496a5779b6eSRui Paulo /* 497a5779b6eSRui Paulo * those options share their semantics. 498a5779b6eSRui Paulo * fall through 499a5779b6eSRui Paulo */ 5004edb46e9SPaul Traina datalen = 4; 5014de76e31SBill Fenner LENCHECK(datalen); 5023c602fabSXin LI ND_PRINT((ndo, " %u", EXTRACT_32BITS(cp))); 5034edb46e9SPaul Traina break; 5044edb46e9SPaul Traina 5054edb46e9SPaul Traina case TCPOPT_TIMESTAMP: 5064de76e31SBill Fenner datalen = 8; 5074de76e31SBill Fenner LENCHECK(datalen); 5083c602fabSXin LI ND_PRINT((ndo, " val %u ecr %u", 509a5779b6eSRui Paulo EXTRACT_32BITS(cp), 5103c602fabSXin LI EXTRACT_32BITS(cp + 4))); 5114edb46e9SPaul Traina break; 5124edb46e9SPaul Traina 5131de50e9fSSam Leffler case TCPOPT_SIGNATURE: 5141de50e9fSSam Leffler datalen = TCP_SIGLEN; 5151de50e9fSSam Leffler LENCHECK(datalen); 5163340d773SGleb Smirnoff ND_PRINT((ndo, " ")); 5171de50e9fSSam Leffler #ifdef HAVE_LIBCRYPTO 5183c602fabSXin LI switch (tcp_verify_signature(ndo, ip, tp, 5191de50e9fSSam Leffler bp + TH_OFF(tp) * 4, length, cp)) { 5201de50e9fSSam Leffler 5211de50e9fSSam Leffler case SIGNATURE_VALID: 5223c602fabSXin LI ND_PRINT((ndo, "valid")); 5231de50e9fSSam Leffler break; 5241de50e9fSSam Leffler 5251de50e9fSSam Leffler case SIGNATURE_INVALID: 5263c602fabSXin LI ND_PRINT((ndo, "invalid")); 5271de50e9fSSam Leffler break; 5281de50e9fSSam Leffler 5291de50e9fSSam Leffler case CANT_CHECK_SIGNATURE: 5303c602fabSXin LI ND_PRINT((ndo, "can't check - ")); 5311de50e9fSSam Leffler for (i = 0; i < TCP_SIGLEN; ++i) 5323c602fabSXin LI ND_PRINT((ndo, "%02x", cp[i])); 5331de50e9fSSam Leffler break; 5341de50e9fSSam Leffler } 5351de50e9fSSam Leffler #else 5361de50e9fSSam Leffler for (i = 0; i < TCP_SIGLEN; ++i) 5373c602fabSXin LI ND_PRINT((ndo, "%02x", cp[i])); 5381de50e9fSSam Leffler #endif 5391de50e9fSSam Leffler break; 5401de50e9fSSam Leffler 5413340d773SGleb Smirnoff case TCPOPT_SCPS: 5423340d773SGleb Smirnoff datalen = 2; 5433340d773SGleb Smirnoff LENCHECK(datalen); 5443340d773SGleb Smirnoff ND_PRINT((ndo, " cap %02x id %u", cp[0], cp[1])); 545a5779b6eSRui Paulo break; 546a5779b6eSRui Paulo 5473340d773SGleb Smirnoff case TCPOPT_TCPAO: 5483340d773SGleb Smirnoff datalen = len - 2; 5493340d773SGleb Smirnoff /* RFC 5925 Section 2.2: 5503340d773SGleb Smirnoff * "The Length value MUST be greater than or equal to 4." 5513340d773SGleb Smirnoff * (This includes the Kind and Length fields already processed 5523340d773SGleb Smirnoff * at this point.) 5533340d773SGleb Smirnoff */ 5543340d773SGleb Smirnoff if (datalen < 2) { 5553340d773SGleb Smirnoff ND_PRINT((ndo, " invalid")); 5563340d773SGleb Smirnoff } else { 5573340d773SGleb Smirnoff LENCHECK(1); 5583340d773SGleb Smirnoff ND_PRINT((ndo, " keyid %u", cp[0])); 5593340d773SGleb Smirnoff LENCHECK(2); 5603340d773SGleb Smirnoff ND_PRINT((ndo, " rnextkeyid %u", cp[1])); 5613340d773SGleb Smirnoff if (datalen > 2) { 5623340d773SGleb Smirnoff ND_PRINT((ndo, " mac 0x")); 5633340d773SGleb Smirnoff for (i = 2; i < datalen; i++) { 5643340d773SGleb Smirnoff LENCHECK(i + 1); 5653340d773SGleb Smirnoff ND_PRINT((ndo, "%02x", cp[i])); 5663340d773SGleb Smirnoff } 5673340d773SGleb Smirnoff } 5683340d773SGleb Smirnoff } 5693340d773SGleb Smirnoff break; 570a5779b6eSRui Paulo 571a5779b6eSRui Paulo case TCPOPT_EOL: 572a5779b6eSRui Paulo case TCPOPT_NOP: 573a5779b6eSRui Paulo case TCPOPT_SACKOK: 574a5779b6eSRui Paulo /* 575a5779b6eSRui Paulo * Nothing interesting. 576a5779b6eSRui Paulo * fall through 577a5779b6eSRui Paulo */ 578a5779b6eSRui Paulo break; 579a5779b6eSRui Paulo 580ce3ed1caSRui Paulo case TCPOPT_UTO: 581ce3ed1caSRui Paulo datalen = 2; 582ce3ed1caSRui Paulo LENCHECK(datalen); 58327df3f5dSRui Paulo utoval = EXTRACT_16BITS(cp); 5843c602fabSXin LI ND_PRINT((ndo, " 0x%x", utoval)); 585ce3ed1caSRui Paulo if (utoval & 0x0001) 586ce3ed1caSRui Paulo utoval = (utoval >> 1) * 60; 587ce3ed1caSRui Paulo else 588ce3ed1caSRui Paulo utoval >>= 1; 5893c602fabSXin LI ND_PRINT((ndo, " %u", utoval)); 5903c602fabSXin LI break; 5913c602fabSXin LI 5923c602fabSXin LI case TCPOPT_MPTCP: 5933c602fabSXin LI datalen = len - 2; 5943c602fabSXin LI LENCHECK(datalen); 5953c602fabSXin LI if (!mptcp_print(ndo, cp-2, len, flags)) 5963c602fabSXin LI goto bad; 5973c602fabSXin LI break; 5983c602fabSXin LI 5993340d773SGleb Smirnoff case TCPOPT_FASTOPEN: 6003340d773SGleb Smirnoff datalen = len - 2; 6013340d773SGleb Smirnoff LENCHECK(datalen); 6023340d773SGleb Smirnoff ND_PRINT((ndo, " ")); 6033340d773SGleb Smirnoff print_tcp_fastopen_option(ndo, cp, datalen, FALSE); 6043340d773SGleb Smirnoff break; 6053340d773SGleb Smirnoff 6063c602fabSXin LI case TCPOPT_EXPERIMENT2: 6073c602fabSXin LI datalen = len - 2; 6083c602fabSXin LI LENCHECK(datalen); 6093c602fabSXin LI if (datalen < 2) 6103c602fabSXin LI goto bad; 6113c602fabSXin LI /* RFC6994 */ 6123c602fabSXin LI magic = EXTRACT_16BITS(cp); 6133c602fabSXin LI ND_PRINT((ndo, "-")); 6143c602fabSXin LI 6153c602fabSXin LI switch(magic) { 6163c602fabSXin LI 6173340d773SGleb Smirnoff case 0xf989: /* TCP Fast Open RFC 7413 */ 6183340d773SGleb Smirnoff print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE); 6193c602fabSXin LI break; 6203c602fabSXin LI 6213c602fabSXin LI default: 6223c602fabSXin LI /* Unknown magic number */ 6233c602fabSXin LI ND_PRINT((ndo, "%04x", magic)); 6243c602fabSXin LI break; 6253c602fabSXin LI } 626ce3ed1caSRui Paulo break; 627ce3ed1caSRui Paulo 6284edb46e9SPaul Traina default: 6294edb46e9SPaul Traina datalen = len - 2; 6303c602fabSXin LI if (datalen) 6313c602fabSXin LI ND_PRINT((ndo, " 0x")); 6324edb46e9SPaul Traina for (i = 0; i < datalen; ++i) { 6333340d773SGleb Smirnoff LENCHECK(i + 1); 6343c602fabSXin LI ND_PRINT((ndo, "%02x", cp[i])); 6354edb46e9SPaul Traina } 6364edb46e9SPaul Traina break; 6374edb46e9SPaul Traina } 6384edb46e9SPaul Traina 6394edb46e9SPaul Traina /* Account for data printed */ 6404edb46e9SPaul Traina cp += datalen; 6414edb46e9SPaul Traina hlen -= datalen; 6424edb46e9SPaul Traina 6434edb46e9SPaul Traina /* Check specification against observed length */ 6444edb46e9SPaul Traina ++datalen; /* option octet */ 6454edb46e9SPaul Traina if (!ZEROLENOPT(opt)) 6464edb46e9SPaul Traina ++datalen; /* size octet */ 6474edb46e9SPaul Traina if (datalen != len) 6483c602fabSXin LI ND_PRINT((ndo, "[len %d]", len)); 6494edb46e9SPaul Traina ch = ','; 6504de76e31SBill Fenner if (opt == TCPOPT_EOL) 6514de76e31SBill Fenner break; 6524edb46e9SPaul Traina } 6533c602fabSXin LI ND_PRINT((ndo, "]")); 6544edb46e9SPaul Traina } 655b0453382SBill Fenner 656a5779b6eSRui Paulo /* 657a5779b6eSRui Paulo * Print length field before crawling down the stack. 658a5779b6eSRui Paulo */ 6593c602fabSXin LI ND_PRINT((ndo, ", length %u", length)); 660a5779b6eSRui Paulo 661b0453382SBill Fenner if (length <= 0) 662b0453382SBill Fenner return; 663b0453382SBill Fenner 664b0453382SBill Fenner /* 665b0453382SBill Fenner * Decode payload if necessary. 666b0453382SBill Fenner */ 667685295f4SBill Fenner bp += TH_OFF(tp) * 4; 6683c602fabSXin LI if ((flags & TH_RST) && ndo->ndo_vflag) { 6693c602fabSXin LI print_tcp_rst_data(ndo, bp, length); 670a5779b6eSRui Paulo return; 671a5779b6eSRui Paulo } 672a5779b6eSRui Paulo 6733c602fabSXin LI if (ndo->ndo_packettype) { 6743c602fabSXin LI switch (ndo->ndo_packettype) { 675d03c0883SXin LI case PT_ZMTP1: 6763c602fabSXin LI zmtp1_print(ndo, bp, length); 677d03c0883SXin LI break; 6783340d773SGleb Smirnoff case PT_RESP: 6793340d773SGleb Smirnoff resp_print(ndo, bp, length); 6803340d773SGleb Smirnoff break; 681d03c0883SXin LI } 682d03c0883SXin LI return; 683d03c0883SXin LI } 684d03c0883SXin LI 6853340d773SGleb Smirnoff if (IS_SRC_OR_DST_PORT(TELNET_PORT)) { 6863c602fabSXin LI telnet_print(ndo, bp, length); 6873340d773SGleb Smirnoff } else if (IS_SRC_OR_DST_PORT(SMTP_PORT)) { 6888bdc5a62SPatrick Kelsey ND_PRINT((ndo, ": ")); 6898bdc5a62SPatrick Kelsey smtp_print(ndo, bp, length); 6903340d773SGleb Smirnoff } else if (IS_SRC_OR_DST_PORT(BGP_PORT)) 6913c602fabSXin LI bgp_print(ndo, bp, length); 6923340d773SGleb Smirnoff else if (IS_SRC_OR_DST_PORT(PPTP_PORT)) 6933c602fabSXin LI pptp_print(ndo, bp); 6943340d773SGleb Smirnoff else if (IS_SRC_OR_DST_PORT(REDIS_PORT)) 6953340d773SGleb Smirnoff resp_print(ndo, bp, length); 6963340d773SGleb Smirnoff #ifdef ENABLE_SMB 6973340d773SGleb Smirnoff else if (IS_SRC_OR_DST_PORT(NETBIOS_SSN_PORT)) 6983c602fabSXin LI nbt_tcp_print(ndo, bp, length); 6993340d773SGleb Smirnoff else if (IS_SRC_OR_DST_PORT(SMB_PORT)) 7003c602fabSXin LI smb_tcp_print(ndo, bp, length); 701a90e161bSBill Fenner #endif 7023340d773SGleb Smirnoff else if (IS_SRC_OR_DST_PORT(BEEP_PORT)) 7033c602fabSXin LI beep_print(ndo, bp, length); 7043340d773SGleb Smirnoff else if (IS_SRC_OR_DST_PORT(OPENFLOW_PORT_OLD) || IS_SRC_OR_DST_PORT(OPENFLOW_PORT_IANA)) 7053c602fabSXin LI openflow_print(ndo, bp, length); 7063340d773SGleb Smirnoff else if (IS_SRC_OR_DST_PORT(FTP_PORT)) { 7078bdc5a62SPatrick Kelsey ND_PRINT((ndo, ": ")); 7088bdc5a62SPatrick Kelsey ftp_print(ndo, bp, length); 7093340d773SGleb Smirnoff } else if (IS_SRC_OR_DST_PORT(HTTP_PORT) || IS_SRC_OR_DST_PORT(HTTP_PORT_ALT)) { 7108bdc5a62SPatrick Kelsey ND_PRINT((ndo, ": ")); 7118bdc5a62SPatrick Kelsey http_print(ndo, bp, length); 7123340d773SGleb Smirnoff } else if (IS_SRC_OR_DST_PORT(RTSP_PORT) || IS_SRC_OR_DST_PORT(RTSP_PORT_ALT)) { 7138bdc5a62SPatrick Kelsey ND_PRINT((ndo, ": ")); 7148bdc5a62SPatrick Kelsey rtsp_print(ndo, bp, length); 7158bdc5a62SPatrick Kelsey } else if (length > 2 && 7163340d773SGleb Smirnoff (IS_SRC_OR_DST_PORT(NAMESERVER_PORT))) { 71739e421e8SCy Schubert /* domain_print() assumes it does not have to prepend a space before its 71839e421e8SCy Schubert * own output to separate it from the output of the calling function. This 71939e421e8SCy Schubert * works well with udp_print(), but requires a small prop here. 72039e421e8SCy Schubert */ 72139e421e8SCy Schubert ND_PRINT((ndo, " ")); 72239e421e8SCy Schubert 723a90e161bSBill Fenner /* 724a90e161bSBill Fenner * TCP DNS query has 2byte length at the head. 725a90e161bSBill Fenner * XXX packet could be unaligned, it can go strange 726a90e161bSBill Fenner */ 7273c602fabSXin LI ns_print(ndo, bp + 2, length - 2, 0); 7283340d773SGleb Smirnoff } else if (IS_SRC_OR_DST_PORT(MSDP_PORT)) { 7293c602fabSXin LI msdp_print(ndo, bp, length); 7303340d773SGleb Smirnoff } else if (IS_SRC_OR_DST_PORT(RPKI_RTR_PORT)) { 7313c602fabSXin LI rpki_rtr_print(ndo, bp, length); 732a90e161bSBill Fenner } 7333340d773SGleb Smirnoff else if (length > 0 && (IS_SRC_OR_DST_PORT(LDP_PORT))) { 7343c602fabSXin LI ldp_print(ndo, bp, length); 7353c602fabSXin LI } 7363340d773SGleb Smirnoff else if ((IS_SRC_OR_DST_PORT(NFS_PORT)) && 7373c602fabSXin LI length >= 4 && ND_TTEST2(*bp, 4)) { 7383c602fabSXin LI /* 7393c602fabSXin LI * If data present, header length valid, and NFS port used, 7403c602fabSXin LI * assume NFS. 7413c602fabSXin LI * Pass offset of data plus 4 bytes for RPC TCP msg length 7423c602fabSXin LI * to NFS print routines. 7433c602fabSXin LI */ 7443c602fabSXin LI uint32_t fraglen; 7453340d773SGleb Smirnoff register const struct sunrpc_msg *rp; 7463c602fabSXin LI enum sunrpc_msg_type direction; 7473c602fabSXin LI 7483c602fabSXin LI fraglen = EXTRACT_32BITS(bp) & 0x7FFFFFFF; 7493c602fabSXin LI if (fraglen > (length) - 4) 7503c602fabSXin LI fraglen = (length) - 4; 7513340d773SGleb Smirnoff rp = (const struct sunrpc_msg *)(bp + 4); 7523c602fabSXin LI if (ND_TTEST(rp->rm_direction)) { 7533c602fabSXin LI direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); 7543c602fabSXin LI if (dport == NFS_PORT && direction == SUNRPC_CALL) { 7553c602fabSXin LI ND_PRINT((ndo, ": NFS request xid %u ", EXTRACT_32BITS(&rp->rm_xid))); 7563340d773SGleb Smirnoff nfsreq_print_noaddr(ndo, (const u_char *)rp, fraglen, (const u_char *)ip); 7573c602fabSXin LI return; 7583c602fabSXin LI } 7593c602fabSXin LI if (sport == NFS_PORT && direction == SUNRPC_REPLY) { 7603c602fabSXin LI ND_PRINT((ndo, ": NFS reply xid %u ", EXTRACT_32BITS(&rp->rm_xid))); 7613340d773SGleb Smirnoff nfsreply_print_noaddr(ndo, (const u_char *)rp, fraglen, (const u_char *)ip); 7623c602fabSXin LI return; 7633c602fabSXin LI } 7643c602fabSXin LI } 7651de50e9fSSam Leffler } 766a5779b6eSRui Paulo 7674edb46e9SPaul Traina return; 7684de76e31SBill Fenner bad: 7693c602fabSXin LI ND_PRINT((ndo, "[bad opt]")); 7704de76e31SBill Fenner if (ch != '\0') 7713c602fabSXin LI ND_PRINT((ndo, ">")); 7724de76e31SBill Fenner return; 7734edb46e9SPaul Traina trunc: 7743c602fabSXin LI ND_PRINT((ndo, "[|tcp]")); 7754edb46e9SPaul Traina if (ch != '\0') 7763c602fabSXin LI ND_PRINT((ndo, ">")); 7774edb46e9SPaul Traina } 7784edb46e9SPaul Traina 779685295f4SBill Fenner /* 780685295f4SBill Fenner * RFC1122 says the following on data in RST segments: 781685295f4SBill Fenner * 782685295f4SBill Fenner * 4.2.2.12 RST Segment: RFC-793 Section 3.4 783685295f4SBill Fenner * 784685295f4SBill Fenner * A TCP SHOULD allow a received RST segment to include data. 785685295f4SBill Fenner * 786685295f4SBill Fenner * DISCUSSION 787685295f4SBill Fenner * It has been suggested that a RST segment could contain 788685295f4SBill Fenner * ASCII text that encoded and explained the cause of the 789685295f4SBill Fenner * RST. No standard has yet been established for such 790685295f4SBill Fenner * data. 791685295f4SBill Fenner * 792685295f4SBill Fenner */ 793685295f4SBill Fenner 794685295f4SBill Fenner static void 7953c602fabSXin LI print_tcp_rst_data(netdissect_options *ndo, 7963c602fabSXin LI register const u_char *sp, u_int length) 797685295f4SBill Fenner { 798685295f4SBill Fenner int c; 799685295f4SBill Fenner 8003c602fabSXin LI ND_PRINT((ndo, ND_TTEST2(*sp, length) ? " [RST" : " [!RST")); 801685295f4SBill Fenner if (length > MAX_RST_DATA_LEN) { 802685295f4SBill Fenner length = MAX_RST_DATA_LEN; /* can use -X for longer */ 8033c602fabSXin LI ND_PRINT((ndo, "+")); /* indicate we truncate */ 804685295f4SBill Fenner } 8053c602fabSXin LI ND_PRINT((ndo, " ")); 8063340d773SGleb Smirnoff while (length-- && sp < ndo->ndo_snapend) { 807685295f4SBill Fenner c = *sp++; 8083c602fabSXin LI safeputchar(ndo, c); 809685295f4SBill Fenner } 8103c602fabSXin LI ND_PRINT((ndo, "]")); 811685295f4SBill Fenner } 8121de50e9fSSam Leffler 8133340d773SGleb Smirnoff static void 8143340d773SGleb Smirnoff print_tcp_fastopen_option(netdissect_options *ndo, register const u_char *cp, 8153340d773SGleb Smirnoff u_int datalen, int exp) 8163340d773SGleb Smirnoff { 8173340d773SGleb Smirnoff u_int i; 8183340d773SGleb Smirnoff 8193340d773SGleb Smirnoff if (exp) 8203340d773SGleb Smirnoff ND_PRINT((ndo, "tfo")); 8213340d773SGleb Smirnoff 8223340d773SGleb Smirnoff if (datalen == 0) { 8233340d773SGleb Smirnoff /* Fast Open Cookie Request */ 8243340d773SGleb Smirnoff ND_PRINT((ndo, " cookiereq")); 8253340d773SGleb Smirnoff } else { 8263340d773SGleb Smirnoff /* Fast Open Cookie */ 8273340d773SGleb Smirnoff if (datalen % 2 != 0 || datalen < 4 || datalen > 16) { 8283340d773SGleb Smirnoff ND_PRINT((ndo, " invalid")); 8293340d773SGleb Smirnoff } else { 8303340d773SGleb Smirnoff ND_PRINT((ndo, " cookie ")); 8313340d773SGleb Smirnoff for (i = 0; i < datalen; ++i) 8323340d773SGleb Smirnoff ND_PRINT((ndo, "%02x", cp[i])); 8333340d773SGleb Smirnoff } 8343340d773SGleb Smirnoff } 8353340d773SGleb Smirnoff } 8363340d773SGleb Smirnoff 8371de50e9fSSam Leffler #ifdef HAVE_LIBCRYPTO 8383c602fabSXin LI USES_APPLE_DEPRECATED_API 8391de50e9fSSam Leffler static int 8403c602fabSXin LI tcp_verify_signature(netdissect_options *ndo, 8413c602fabSXin LI const struct ip *ip, const struct tcphdr *tp, 8421de50e9fSSam Leffler const u_char *data, int length, const u_char *rcvsig) 8431de50e9fSSam Leffler { 8441de50e9fSSam Leffler struct tcphdr tp1; 845f4d0c64aSSam Leffler u_char sig[TCP_SIGLEN]; 8461de50e9fSSam Leffler char zero_proto = 0; 8471de50e9fSSam Leffler MD5_CTX ctx; 8483c602fabSXin LI uint16_t savecsum, tlen; 8493340d773SGleb Smirnoff const struct ip6_hdr *ip6; 8503c602fabSXin LI uint32_t len32; 8513c602fabSXin LI uint8_t nxt; 8521de50e9fSSam Leffler 8533c602fabSXin LI if (data + length > ndo->ndo_snapend) { 8543c602fabSXin LI ND_PRINT((ndo, "snaplen too short, ")); 85527df3f5dSRui Paulo return (CANT_CHECK_SIGNATURE); 85627df3f5dSRui Paulo } 85727df3f5dSRui Paulo 8581de50e9fSSam Leffler tp1 = *tp; 8591de50e9fSSam Leffler 8603c602fabSXin LI if (ndo->ndo_sigsecret == NULL) { 8613c602fabSXin LI ND_PRINT((ndo, "shared secret not supplied with -M, ")); 8621de50e9fSSam Leffler return (CANT_CHECK_SIGNATURE); 86327df3f5dSRui Paulo } 8641de50e9fSSam Leffler 8651de50e9fSSam Leffler MD5_Init(&ctx); 8661de50e9fSSam Leffler /* 8671de50e9fSSam Leffler * Step 1: Update MD5 hash with IP pseudo-header. 8681de50e9fSSam Leffler */ 8691de50e9fSSam Leffler if (IP_V(ip) == 4) { 8703340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&ip->ip_src, sizeof(ip->ip_src)); 8713340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&ip->ip_dst, sizeof(ip->ip_dst)); 8723340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&zero_proto, sizeof(zero_proto)); 8733340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&ip->ip_p, sizeof(ip->ip_p)); 8741de50e9fSSam Leffler tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4; 8751de50e9fSSam Leffler tlen = htons(tlen); 8763340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&tlen, sizeof(tlen)); 8771de50e9fSSam Leffler } else if (IP_V(ip) == 6) { 8783340d773SGleb Smirnoff ip6 = (const struct ip6_hdr *)ip; 8793340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&ip6->ip6_src, sizeof(ip6->ip6_src)); 8803340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst)); 88127df3f5dSRui Paulo len32 = htonl(EXTRACT_16BITS(&ip6->ip6_plen)); 8823340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&len32, sizeof(len32)); 8831de50e9fSSam Leffler nxt = 0; 8843340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); 8853340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); 8863340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); 8871de50e9fSSam Leffler nxt = IPPROTO_TCP; 8883340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); 88927df3f5dSRui Paulo } else { 8903c602fabSXin LI ND_PRINT((ndo, "IP version not 4 or 6, ")); 8911de50e9fSSam Leffler return (CANT_CHECK_SIGNATURE); 89227df3f5dSRui Paulo } 8931de50e9fSSam Leffler 8941de50e9fSSam Leffler /* 8951de50e9fSSam Leffler * Step 2: Update MD5 hash with TCP header, excluding options. 8961de50e9fSSam Leffler * The TCP checksum must be set to zero. 8971de50e9fSSam Leffler */ 8981de50e9fSSam Leffler savecsum = tp1.th_sum; 8991de50e9fSSam Leffler tp1.th_sum = 0; 9003340d773SGleb Smirnoff MD5_Update(&ctx, (const char *)&tp1, sizeof(struct tcphdr)); 9011de50e9fSSam Leffler tp1.th_sum = savecsum; 9021de50e9fSSam Leffler /* 9031de50e9fSSam Leffler * Step 3: Update MD5 hash with TCP segment data, if present. 9041de50e9fSSam Leffler */ 9051de50e9fSSam Leffler if (length > 0) 9061de50e9fSSam Leffler MD5_Update(&ctx, data, length); 9071de50e9fSSam Leffler /* 9081de50e9fSSam Leffler * Step 4: Update MD5 hash with shared secret. 9091de50e9fSSam Leffler */ 9103c602fabSXin LI MD5_Update(&ctx, ndo->ndo_sigsecret, strlen(ndo->ndo_sigsecret)); 9111de50e9fSSam Leffler MD5_Final(sig, &ctx); 9121de50e9fSSam Leffler 913b5bfcb5dSMax Laier if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0) 9141de50e9fSSam Leffler return (SIGNATURE_VALID); 9151de50e9fSSam Leffler else 9161de50e9fSSam Leffler return (SIGNATURE_INVALID); 9171de50e9fSSam Leffler } 9183c602fabSXin LI USES_APPLE_RST 9191de50e9fSSam Leffler #endif /* HAVE_LIBCRYPTO */ 920a5779b6eSRui Paulo 921a5779b6eSRui Paulo /* 922a5779b6eSRui Paulo * Local Variables: 923a5779b6eSRui Paulo * c-style: whitesmith 924a5779b6eSRui Paulo * c-basic-offset: 8 925a5779b6eSRui Paulo * End: 926a5779b6eSRui Paulo */ 927