xref: /freebsd/contrib/tcpdump/print-tcp.c (revision 0a7e5f1f02aad2ff5fff1c60f44c6975fd07e1d9)
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 
33ee67461eSJoseph Mingrone #include <config.h>
344edb46e9SPaul Traina 
35ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
364edb46e9SPaul Traina 
374edb46e9SPaul Traina #include <stdlib.h>
384edb46e9SPaul Traina #include <string.h>
394edb46e9SPaul Traina 
403340d773SGleb Smirnoff #include "netdissect.h"
414edb46e9SPaul Traina #include "addrtoname.h"
424edb46e9SPaul Traina #include "extract.h"
434edb46e9SPaul Traina 
44ee67461eSJoseph Mingrone #include "diag-control.h"
45ee67461eSJoseph Mingrone 
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,
60ee67461eSJoseph Mingrone                                 const u_char *data, u_int length, const u_char *rcvsig);
611de50e9fSSam Leffler #endif
621de50e9fSSam Leffler 
63ee67461eSJoseph Mingrone static void print_tcp_rst_data(netdissect_options *, const u_char *sp, u_int length);
64ee67461eSJoseph Mingrone static void print_tcp_fastopen_option(netdissect_options *ndo, 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 {
71ee67461eSJoseph Mingrone         nd_ipv4 src;
72ee67461eSJoseph Mingrone         nd_ipv4 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;
79ee67461eSJoseph Mingrone         uint32_t seq;
80ee67461eSJoseph Mingrone         uint32_t ack;
814edb46e9SPaul Traina };
824edb46e9SPaul Traina 
833c602fabSXin LI struct tha6 {
84ee67461eSJoseph Mingrone         nd_ipv6 src;
85ee67461eSJoseph Mingrone         nd_ipv6 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;
92ee67461eSJoseph Mingrone         uint32_t seq;
93ee67461eSJoseph Mingrone         uint32_t ack;
943c602fabSXin LI };
953c602fabSXin LI 
964edb46e9SPaul Traina #define TSEQ_HASHSIZE 919
974edb46e9SPaul Traina 
98ee67461eSJoseph Mingrone /* These tcp options 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" },
128*0a7e5f1fSJoseph Mingrone         { TCPOPT_CCECHO, "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 
139ee67461eSJoseph Mingrone static uint16_t
tcp_cksum(netdissect_options * ndo,const struct ip * ip,const struct tcphdr * tp,u_int len)1403c602fabSXin LI tcp_cksum(netdissect_options *ndo,
141ee67461eSJoseph Mingrone           const struct ip *ip,
142ee67461eSJoseph Mingrone           const struct tcphdr *tp,
143ee67461eSJoseph Mingrone           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 
149ee67461eSJoseph Mingrone static uint16_t
tcp6_cksum(netdissect_options * ndo,const struct ip6_hdr * ip6,const struct tcphdr * tp,u_int len)1503340d773SGleb Smirnoff tcp6_cksum(netdissect_options *ndo,
151ee67461eSJoseph Mingrone            const struct ip6_hdr *ip6,
152ee67461eSJoseph Mingrone            const struct tcphdr *tp,
153ee67461eSJoseph Mingrone            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
tcp_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2,int fragmented)1603c602fabSXin LI tcp_print(netdissect_options *ndo,
161ee67461eSJoseph Mingrone           const u_char *bp, u_int length,
162ee67461eSJoseph Mingrone           const u_char *bp2, int fragmented)
1634edb46e9SPaul Traina {
164ee67461eSJoseph Mingrone         const struct tcphdr *tp;
165ee67461eSJoseph Mingrone         const struct ip *ip;
166ee67461eSJoseph Mingrone         u_char flags;
167ee67461eSJoseph Mingrone         u_int hlen;
168ee67461eSJoseph Mingrone         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;
173ee67461eSJoseph Mingrone         int rev;
174ee67461eSJoseph Mingrone         const struct ip6_hdr *ip6;
175ee67461eSJoseph Mingrone         u_int header_len;	/* Header length in bytes */
1764edb46e9SPaul Traina 
177ee67461eSJoseph Mingrone         ndo->ndo_protocol = "tcp";
1783340d773SGleb Smirnoff         tp = (const struct tcphdr *)bp;
1793340d773SGleb Smirnoff         ip = (const struct ip *)bp2;
180685295f4SBill Fenner         if (IP_V(ip) == 6)
1813340d773SGleb Smirnoff                 ip6 = (const struct ip6_hdr *)bp2;
182b0453382SBill Fenner         else
183b0453382SBill Fenner                 ip6 = NULL;
1844edb46e9SPaul Traina         ch = '\0';
185ee67461eSJoseph Mingrone         if (!ND_TTEST_2(tp->th_dport)) {
186ee67461eSJoseph Mingrone                 if (ip6) {
187ee67461eSJoseph Mingrone                         ND_PRINT("%s > %s:",
188ee67461eSJoseph Mingrone                                  GET_IP6ADDR_STRING(ip6->ip6_src),
189ee67461eSJoseph Mingrone                                  GET_IP6ADDR_STRING(ip6->ip6_dst));
190ee67461eSJoseph Mingrone                 } else {
191ee67461eSJoseph Mingrone                         ND_PRINT("%s > %s:",
192ee67461eSJoseph Mingrone                                  GET_IPADDR_STRING(ip->ip_src),
193ee67461eSJoseph Mingrone                                  GET_IPADDR_STRING(ip->ip_dst));
194ee67461eSJoseph Mingrone                 }
195ee67461eSJoseph Mingrone                 nd_print_trunc(ndo);
1964edb46e9SPaul Traina                 return;
1974edb46e9SPaul Traina         }
1984edb46e9SPaul Traina 
199ee67461eSJoseph Mingrone         sport = GET_BE_U_2(tp->th_sport);
200ee67461eSJoseph Mingrone         dport = GET_BE_U_2(tp->th_dport);
201b0453382SBill Fenner 
202b0453382SBill Fenner         if (ip6) {
203ee67461eSJoseph Mingrone                 if (GET_U_1(ip6->ip6_nxt) == IPPROTO_TCP) {
204ee67461eSJoseph Mingrone                         ND_PRINT("%s.%s > %s.%s: ",
205ee67461eSJoseph Mingrone                                  GET_IP6ADDR_STRING(ip6->ip6_src),
2063340d773SGleb Smirnoff                                  tcpport_string(ndo, sport),
207ee67461eSJoseph Mingrone                                  GET_IP6ADDR_STRING(ip6->ip6_dst),
208ee67461eSJoseph Mingrone                                  tcpport_string(ndo, dport));
209b0453382SBill Fenner                 } else {
210ee67461eSJoseph Mingrone                         ND_PRINT("%s > %s: ",
211ee67461eSJoseph Mingrone                                  tcpport_string(ndo, sport), tcpport_string(ndo, dport));
212b0453382SBill Fenner                 }
2133340d773SGleb Smirnoff         } else {
214ee67461eSJoseph Mingrone                 if (GET_U_1(ip->ip_p) == IPPROTO_TCP) {
215ee67461eSJoseph Mingrone                         ND_PRINT("%s.%s > %s.%s: ",
216ee67461eSJoseph Mingrone                                  GET_IPADDR_STRING(ip->ip_src),
2173340d773SGleb Smirnoff                                  tcpport_string(ndo, sport),
218ee67461eSJoseph Mingrone                                  GET_IPADDR_STRING(ip->ip_dst),
219ee67461eSJoseph Mingrone                                  tcpport_string(ndo, dport));
220b0453382SBill Fenner                 } else {
221ee67461eSJoseph Mingrone                         ND_PRINT("%s > %s: ",
222ee67461eSJoseph Mingrone                                  tcpport_string(ndo, sport), tcpport_string(ndo, dport));
223b0453382SBill Fenner                 }
224b0453382SBill Fenner         }
225b0453382SBill Fenner 
226ee67461eSJoseph Mingrone         ND_TCHECK_SIZE(tp);
2273340d773SGleb Smirnoff 
2283340d773SGleb Smirnoff         hlen = TH_OFF(tp) * 4;
2293340d773SGleb Smirnoff 
2301de50e9fSSam Leffler         if (hlen < sizeof(*tp)) {
231ee67461eSJoseph Mingrone                 ND_PRINT(" tcp %u [bad hdr length %u - too short, < %zu]",
232ee67461eSJoseph Mingrone                          length - hlen, hlen, sizeof(*tp));
2331de50e9fSSam Leffler                 return;
2341de50e9fSSam Leffler         }
2351de50e9fSSam Leffler 
236ee67461eSJoseph Mingrone         seq = GET_BE_U_4(tp->th_seq);
237ee67461eSJoseph Mingrone         ack = GET_BE_U_4(tp->th_ack);
238ee67461eSJoseph Mingrone         win = GET_BE_U_2(tp->th_win);
239ee67461eSJoseph Mingrone         urp = GET_BE_U_2(tp->th_urp);
2404edb46e9SPaul Traina 
2413c602fabSXin LI         if (ndo->ndo_qflag) {
242ee67461eSJoseph Mingrone                 ND_PRINT("tcp %u", length - hlen);
2431de50e9fSSam Leffler                 if (hlen > length) {
244ee67461eSJoseph Mingrone                         ND_PRINT(" [bad hdr length %u - too long, > %u]",
245ee67461eSJoseph Mingrone                                  hlen, length);
2461de50e9fSSam Leffler                 }
2474edb46e9SPaul Traina                 return;
2484edb46e9SPaul Traina         }
249a5779b6eSRui Paulo 
250ee67461eSJoseph Mingrone         flags = GET_U_1(tp->th_flags);
251ee67461eSJoseph Mingrone         ND_PRINT("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags));
2524edb46e9SPaul Traina 
2533c602fabSXin LI         if (!ndo->ndo_Sflag && (flags & TH_ACK)) {
2544edb46e9SPaul Traina                 /*
2554edb46e9SPaul Traina                  * Find (or record) the initial sequence numbers for
2564edb46e9SPaul Traina                  * this conversation.  (we pick an arbitrary
2574edb46e9SPaul Traina                  * collating order so there's only one entry for
2584edb46e9SPaul Traina                  * both directions).
2594edb46e9SPaul Traina                  */
260b0453382SBill Fenner                 rev = 0;
261b0453382SBill Fenner                 if (ip6) {
262ee67461eSJoseph Mingrone                         struct tcp_seq_hash6 *th;
2633c602fabSXin LI                         struct tcp_seq_hash6 *tcp_seq_hash;
264ee67461eSJoseph Mingrone                         const void *src, *dst;
2653c602fabSXin LI                         struct tha6 tha;
2663c602fabSXin LI 
2673c602fabSXin LI                         tcp_seq_hash = tcp_seq_hash6;
268ee67461eSJoseph Mingrone                         src = (const void *)ip6->ip6_src;
269ee67461eSJoseph Mingrone                         dst = (const void *)ip6->ip6_dst;
270a90e161bSBill Fenner                         if (sport > dport)
271b0453382SBill Fenner                                 rev = 1;
272a90e161bSBill Fenner                         else if (sport == dport) {
273ee67461eSJoseph Mingrone                                 if (UNALIGNED_MEMCMP(src, dst, sizeof(ip6->ip6_dst)) > 0)
274b0453382SBill Fenner                                         rev = 1;
275b0453382SBill Fenner                         }
276b0453382SBill Fenner                         if (rev) {
277ee67461eSJoseph Mingrone                                 UNALIGNED_MEMCPY(&tha.src, dst, sizeof(ip6->ip6_dst));
278ee67461eSJoseph Mingrone                                 UNALIGNED_MEMCPY(&tha.dst, src, sizeof(ip6->ip6_src));
27939e421e8SCy Schubert                                 tha.port = ((u_int)dport) << 16 | sport;
280b0453382SBill Fenner                         } else {
281ee67461eSJoseph Mingrone                                 UNALIGNED_MEMCPY(&tha.dst, dst, sizeof(ip6->ip6_dst));
282ee67461eSJoseph Mingrone                                 UNALIGNED_MEMCPY(&tha.src, src, sizeof(ip6->ip6_src));
28339e421e8SCy Schubert                                 tha.port = ((u_int)sport) << 16 | dport;
284b0453382SBill Fenner                         }
2854edb46e9SPaul Traina 
2863c602fabSXin LI                         for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
2873c602fabSXin LI                              th->nxt; th = th->nxt)
2883c602fabSXin LI                                 if (memcmp((char *)&tha, (char *)&th->addr,
2893c602fabSXin LI                                            sizeof(th->addr)) == 0)
2903c602fabSXin LI                                         break;
2913c602fabSXin LI 
2923c602fabSXin LI                         if (!th->nxt || (flags & TH_SYN)) {
2933c602fabSXin LI                                 /* didn't find it or new conversation */
294ee67461eSJoseph Mingrone                                 /* calloc() return used by the 'tcp_seq_hash6'
295ee67461eSJoseph Mingrone                                    hash table: do not free() */
2963c602fabSXin LI                                 if (th->nxt == NULL) {
2973c602fabSXin LI                                         th->nxt = (struct tcp_seq_hash6 *)
2983c602fabSXin LI                                                 calloc(1, sizeof(*th));
2993c602fabSXin LI                                         if (th->nxt == NULL)
3003340d773SGleb Smirnoff                                                 (*ndo->ndo_error)(ndo,
301ee67461eSJoseph Mingrone                                                         S_ERR_ND_MEM_ALLOC,
302ee67461eSJoseph Mingrone                                                         "%s: calloc", __func__);
3033c602fabSXin LI                                 }
3043c602fabSXin LI                                 th->addr = tha;
3053c602fabSXin LI                                 if (rev)
3063c602fabSXin LI                                         th->ack = seq, th->seq = ack - 1;
3073c602fabSXin LI                                 else
3083c602fabSXin LI                                         th->seq = seq, th->ack = ack - 1;
3093c602fabSXin LI                         } else {
3103c602fabSXin LI                                 if (rev)
3113c602fabSXin LI                                         seq -= th->ack, ack -= th->seq;
3123c602fabSXin LI                                 else
3133c602fabSXin LI                                         seq -= th->seq, ack -= th->ack;
3143c602fabSXin LI                         }
3153c602fabSXin LI 
3163c602fabSXin LI                         thseq = th->seq;
3173c602fabSXin LI                         thack = th->ack;
3183c602fabSXin LI                 } else {
319ee67461eSJoseph Mingrone                         struct tcp_seq_hash *th;
3203c602fabSXin LI                         struct tcp_seq_hash *tcp_seq_hash;
3213c602fabSXin LI                         struct tha tha;
3223c602fabSXin LI 
3233c602fabSXin LI                         tcp_seq_hash = tcp_seq_hash4;
3243c602fabSXin LI                         if (sport > dport)
3253c602fabSXin LI                                 rev = 1;
3263c602fabSXin LI                         else if (sport == dport) {
327ee67461eSJoseph Mingrone                                 if (UNALIGNED_MEMCMP(ip->ip_src, ip->ip_dst, sizeof(ip->ip_dst)) > 0)
3283c602fabSXin LI                                         rev = 1;
3293c602fabSXin LI                         }
3303c602fabSXin LI                         if (rev) {
331ee67461eSJoseph Mingrone                                 UNALIGNED_MEMCPY(&tha.src, ip->ip_dst,
332ee67461eSJoseph Mingrone                                                  sizeof(ip->ip_dst));
333ee67461eSJoseph Mingrone                                 UNALIGNED_MEMCPY(&tha.dst, ip->ip_src,
334ee67461eSJoseph Mingrone                                                  sizeof(ip->ip_src));
33539e421e8SCy Schubert                                 tha.port = ((u_int)dport) << 16 | sport;
3363c602fabSXin LI                         } else {
337ee67461eSJoseph Mingrone                                 UNALIGNED_MEMCPY(&tha.dst, ip->ip_dst,
338ee67461eSJoseph Mingrone                                                  sizeof(ip->ip_dst));
339ee67461eSJoseph Mingrone                                 UNALIGNED_MEMCPY(&tha.src, ip->ip_src,
340ee67461eSJoseph Mingrone                                                  sizeof(ip->ip_src));
34139e421e8SCy Schubert                                 tha.port = ((u_int)sport) << 16 | dport;
3423c602fabSXin LI                         }
3433c602fabSXin LI 
3444edb46e9SPaul Traina                         for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
3454edb46e9SPaul Traina                              th->nxt; th = th->nxt)
3465b0fe478SBruce M Simpson                                 if (memcmp((char *)&tha, (char *)&th->addr,
3475b0fe478SBruce M Simpson                                            sizeof(th->addr)) == 0)
3484edb46e9SPaul Traina                                         break;
3494edb46e9SPaul Traina 
350685295f4SBill Fenner                         if (!th->nxt || (flags & TH_SYN)) {
3514edb46e9SPaul Traina                                 /* didn't find it or new conversation */
352ee67461eSJoseph Mingrone                                 /* calloc() return used by the 'tcp_seq_hash4'
353ee67461eSJoseph Mingrone                                    hash table: do not free() */
3544edb46e9SPaul Traina                                 if (th->nxt == NULL) {
3554edb46e9SPaul Traina                                         th->nxt = (struct tcp_seq_hash *)
3564edb46e9SPaul Traina                                                 calloc(1, sizeof(*th));
3574edb46e9SPaul Traina                                         if (th->nxt == NULL)
3583340d773SGleb Smirnoff                                                 (*ndo->ndo_error)(ndo,
359ee67461eSJoseph Mingrone                                                         S_ERR_ND_MEM_ALLOC,
360ee67461eSJoseph Mingrone                                                         "%s: calloc", __func__);
3614edb46e9SPaul Traina                                 }
3624edb46e9SPaul Traina                                 th->addr = tha;
3634edb46e9SPaul Traina                                 if (rev)
3644edb46e9SPaul Traina                                         th->ack = seq, th->seq = ack - 1;
3654edb46e9SPaul Traina                                 else
3664edb46e9SPaul Traina                                         th->seq = seq, th->ack = ack - 1;
3674edb46e9SPaul Traina                         } else {
3684edb46e9SPaul Traina                                 if (rev)
3694edb46e9SPaul Traina                                         seq -= th->ack, ack -= th->seq;
3704edb46e9SPaul Traina                                 else
3714edb46e9SPaul Traina                                         seq -= th->seq, ack -= th->ack;
3724edb46e9SPaul Traina                         }
373685295f4SBill Fenner 
374685295f4SBill Fenner                         thseq = th->seq;
375685295f4SBill Fenner                         thack = th->ack;
3763c602fabSXin LI                 }
377685295f4SBill Fenner         } else {
378685295f4SBill Fenner                 /*fool gcc*/
3793c602fabSXin LI                 thseq = thack = rev = 0;
3804edb46e9SPaul Traina         }
3814de76e31SBill Fenner         if (hlen > length) {
382ee67461eSJoseph Mingrone                 ND_PRINT(" [bad hdr length %u - too long, > %u]",
383ee67461eSJoseph Mingrone                          hlen, length);
3844de76e31SBill Fenner                 return;
3854de76e31SBill Fenner         }
386685295f4SBill Fenner 
3873c602fabSXin LI         if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) {
388cac3dcd5SXin LI                 /* Check the checksum, if possible. */
3893c602fabSXin LI                 uint16_t sum, tcp_sum;
390cac3dcd5SXin LI 
391cac3dcd5SXin LI                 if (IP_V(ip) == 4) {
392ee67461eSJoseph Mingrone                         if (ND_TTEST_LEN(tp->th_sport, length)) {
3933c602fabSXin LI                                 sum = tcp_cksum(ndo, ip, tp, length);
394ee67461eSJoseph Mingrone                                 tcp_sum = GET_BE_U_2(tp->th_sum);
395cac3dcd5SXin LI 
396ee67461eSJoseph Mingrone                                 ND_PRINT(", cksum 0x%04x", tcp_sum);
397cac3dcd5SXin LI                                 if (sum != 0)
398ee67461eSJoseph Mingrone                                         ND_PRINT(" (incorrect -> 0x%04x)",
399ee67461eSJoseph Mingrone                                             in_cksum_shouldbe(tcp_sum, sum));
400cac3dcd5SXin LI                                 else
401ee67461eSJoseph Mingrone                                         ND_PRINT(" (correct)");
402685295f4SBill Fenner                         }
403ee67461eSJoseph Mingrone                 } else if (IP_V(ip) == 6) {
404ee67461eSJoseph Mingrone                         if (ND_TTEST_LEN(tp->th_sport, length)) {
4053340d773SGleb Smirnoff                                 sum = tcp6_cksum(ndo, ip6, tp, length);
406ee67461eSJoseph Mingrone                                 tcp_sum = GET_BE_U_2(tp->th_sum);
407cac3dcd5SXin LI 
408ee67461eSJoseph Mingrone                                 ND_PRINT(", cksum 0x%04x", tcp_sum);
409cac3dcd5SXin LI                                 if (sum != 0)
410ee67461eSJoseph Mingrone                                         ND_PRINT(" (incorrect -> 0x%04x)",
411ee67461eSJoseph Mingrone                                             in_cksum_shouldbe(tcp_sum, sum));
412cac3dcd5SXin LI                                 else
413ee67461eSJoseph Mingrone                                         ND_PRINT(" (correct)");
4141de50e9fSSam Leffler 
415685295f4SBill Fenner                         }
416685295f4SBill Fenner                 }
417cac3dcd5SXin LI         }
418685295f4SBill Fenner 
4194edb46e9SPaul Traina         length -= hlen;
4203c602fabSXin LI         if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) {
421ee67461eSJoseph Mingrone                 ND_PRINT(", seq %u", seq);
4224edb46e9SPaul Traina 
423a5779b6eSRui Paulo                 if (length > 0) {
424ee67461eSJoseph Mingrone                         ND_PRINT(":%u", seq + length);
425a5779b6eSRui Paulo                 }
426a5779b6eSRui Paulo         }
427a5779b6eSRui Paulo 
428a5779b6eSRui Paulo         if (flags & TH_ACK) {
429ee67461eSJoseph Mingrone                 ND_PRINT(", ack %u", ack);
430a5779b6eSRui Paulo         }
431a5779b6eSRui Paulo 
432ee67461eSJoseph Mingrone         ND_PRINT(", win %u", win);
4334edb46e9SPaul Traina 
4344edb46e9SPaul Traina         if (flags & TH_URG)
435ee67461eSJoseph Mingrone                 ND_PRINT(", urg %u", urp);
4364edb46e9SPaul Traina         /*
4374edb46e9SPaul Traina          * Handle any options.
4384edb46e9SPaul Traina          */
4395b0fe478SBruce M Simpson         if (hlen > sizeof(*tp)) {
440ee67461eSJoseph Mingrone                 const u_char *cp;
441ee67461eSJoseph Mingrone                 u_int i, opt, datalen;
442ee67461eSJoseph Mingrone                 u_int len;
4434edb46e9SPaul Traina 
4445b0fe478SBruce M Simpson                 hlen -= sizeof(*tp);
4454edb46e9SPaul Traina                 cp = (const u_char *)tp + sizeof(*tp);
446ee67461eSJoseph Mingrone                 ND_PRINT(", options [");
4474edb46e9SPaul Traina                 while (hlen > 0) {
448a5779b6eSRui Paulo                         if (ch != '\0')
449ee67461eSJoseph Mingrone                                 ND_PRINT("%c", ch);
450ee67461eSJoseph Mingrone                         opt = GET_U_1(cp);
451ee67461eSJoseph Mingrone                         cp++;
4524edb46e9SPaul Traina                         if (ZEROLENOPT(opt))
4534edb46e9SPaul Traina                                 len = 1;
4544edb46e9SPaul Traina                         else {
455ee67461eSJoseph Mingrone                                 len = GET_U_1(cp);
456ee67461eSJoseph Mingrone                                 cp++;	/* total including type, len */
4574de76e31SBill Fenner                                 if (len < 2 || len > hlen)
4584de76e31SBill Fenner                                         goto bad;
4594de76e31SBill Fenner                                 --hlen;		/* account for length byte */
4604edb46e9SPaul Traina                         }
4614de76e31SBill Fenner                         --hlen;			/* account for type byte */
4624edb46e9SPaul Traina                         datalen = 0;
4634de76e31SBill Fenner 
4644de76e31SBill Fenner /* Bail if "l" bytes of data are not left or were not captured  */
465ee67461eSJoseph Mingrone #define LENCHECK(l) { if ((l) > hlen) goto bad; ND_TCHECK_LEN(cp, l); }
4664de76e31SBill Fenner 
467a5779b6eSRui Paulo 
468ee67461eSJoseph Mingrone                         ND_PRINT("%s", tok2str(tcp_option_values, "unknown-%u", opt));
469a5779b6eSRui Paulo 
4704edb46e9SPaul Traina                         switch (opt) {
4714edb46e9SPaul Traina 
4724edb46e9SPaul Traina                         case TCPOPT_MAXSEG:
4734edb46e9SPaul Traina                                 datalen = 2;
4744de76e31SBill Fenner                                 LENCHECK(datalen);
475ee67461eSJoseph Mingrone                                 ND_PRINT(" %u", GET_BE_U_2(cp));
4764edb46e9SPaul Traina                                 break;
4774edb46e9SPaul Traina 
4784edb46e9SPaul Traina                         case TCPOPT_WSCALE:
4794edb46e9SPaul Traina                                 datalen = 1;
4804de76e31SBill Fenner                                 LENCHECK(datalen);
481ee67461eSJoseph Mingrone                                 ND_PRINT(" %u", GET_U_1(cp));
4824edb46e9SPaul Traina                                 break;
4834edb46e9SPaul Traina 
4844edb46e9SPaul Traina                         case TCPOPT_SACK:
4854edb46e9SPaul Traina                                 datalen = len - 2;
486b0453382SBill Fenner                                 if (datalen % 8 != 0) {
487ee67461eSJoseph Mingrone                                         ND_PRINT(" invalid sack");
488b0453382SBill Fenner                                 } else {
4893c602fabSXin LI                                         uint32_t s, e;
490b0453382SBill Fenner 
491ee67461eSJoseph Mingrone                                         ND_PRINT(" %u ", datalen / 8);
492b0453382SBill Fenner                                         for (i = 0; i < datalen; i += 8) {
4934de76e31SBill Fenner                                                 LENCHECK(i + 4);
494ee67461eSJoseph Mingrone                                                 s = GET_BE_U_4(cp + i);
495b0453382SBill Fenner                                                 LENCHECK(i + 8);
496ee67461eSJoseph Mingrone                                                 e = GET_BE_U_4(cp + i + 4);
4973c602fabSXin LI                                                 if (rev) {
498b0453382SBill Fenner                                                         s -= thseq;
499b0453382SBill Fenner                                                         e -= thseq;
500b0453382SBill Fenner                                                 } else {
501b0453382SBill Fenner                                                         s -= thack;
502b0453382SBill Fenner                                                         e -= thack;
5034edb46e9SPaul Traina                                                 }
504ee67461eSJoseph Mingrone                                                 ND_PRINT("{%u:%u}", s, e);
505b0453382SBill Fenner                                         }
506b0453382SBill Fenner                                 }
5074edb46e9SPaul Traina                                 break;
5084edb46e9SPaul Traina 
509a5779b6eSRui Paulo                         case TCPOPT_CC:
510a5779b6eSRui Paulo                         case TCPOPT_CCNEW:
511a5779b6eSRui Paulo                         case TCPOPT_CCECHO:
5124edb46e9SPaul Traina                         case TCPOPT_ECHO:
5134edb46e9SPaul Traina                         case TCPOPT_ECHOREPLY:
514a5779b6eSRui Paulo 
515a5779b6eSRui Paulo                                 /*
516a5779b6eSRui Paulo                                  * those options share their semantics.
517a5779b6eSRui Paulo                                  * fall through
518a5779b6eSRui Paulo                                  */
5194edb46e9SPaul Traina                                 datalen = 4;
5204de76e31SBill Fenner                                 LENCHECK(datalen);
521ee67461eSJoseph Mingrone                                 ND_PRINT(" %u", GET_BE_U_4(cp));
5224edb46e9SPaul Traina                                 break;
5234edb46e9SPaul Traina 
5244edb46e9SPaul Traina                         case TCPOPT_TIMESTAMP:
5254de76e31SBill Fenner                                 datalen = 8;
5264de76e31SBill Fenner                                 LENCHECK(datalen);
527ee67461eSJoseph Mingrone                                 ND_PRINT(" val %u ecr %u",
528ee67461eSJoseph Mingrone                                              GET_BE_U_4(cp),
529ee67461eSJoseph Mingrone                                              GET_BE_U_4(cp + 4));
5304edb46e9SPaul Traina                                 break;
5314edb46e9SPaul Traina 
5321de50e9fSSam Leffler                         case TCPOPT_SIGNATURE:
5331de50e9fSSam Leffler                                 datalen = TCP_SIGLEN;
5341de50e9fSSam Leffler                                 LENCHECK(datalen);
535ee67461eSJoseph Mingrone                                 ND_PRINT(" ");
5361de50e9fSSam Leffler #ifdef HAVE_LIBCRYPTO
5373c602fabSXin LI                                 switch (tcp_verify_signature(ndo, ip, tp,
5381de50e9fSSam Leffler                                                              bp + TH_OFF(tp) * 4, length, cp)) {
5391de50e9fSSam Leffler 
5401de50e9fSSam Leffler                                 case SIGNATURE_VALID:
541ee67461eSJoseph Mingrone                                         ND_PRINT("valid");
5421de50e9fSSam Leffler                                         break;
5431de50e9fSSam Leffler 
5441de50e9fSSam Leffler                                 case SIGNATURE_INVALID:
545ee67461eSJoseph Mingrone                                         nd_print_invalid(ndo);
5461de50e9fSSam Leffler                                         break;
5471de50e9fSSam Leffler 
5481de50e9fSSam Leffler                                 case CANT_CHECK_SIGNATURE:
549ee67461eSJoseph Mingrone                                         ND_PRINT("can't check - ");
5501de50e9fSSam Leffler                                         for (i = 0; i < TCP_SIGLEN; ++i)
551ee67461eSJoseph Mingrone                                                 ND_PRINT("%02x",
552ee67461eSJoseph Mingrone                                                          GET_U_1(cp + i));
5531de50e9fSSam Leffler                                         break;
5541de50e9fSSam Leffler                                 }
5551de50e9fSSam Leffler #else
5561de50e9fSSam Leffler                                 for (i = 0; i < TCP_SIGLEN; ++i)
557ee67461eSJoseph Mingrone                                         ND_PRINT("%02x", GET_U_1(cp + i));
5581de50e9fSSam Leffler #endif
5591de50e9fSSam Leffler                                 break;
5601de50e9fSSam Leffler 
5613340d773SGleb Smirnoff                         case TCPOPT_SCPS:
5623340d773SGleb Smirnoff                                 datalen = 2;
5633340d773SGleb Smirnoff                                 LENCHECK(datalen);
564ee67461eSJoseph Mingrone                                 ND_PRINT(" cap %02x id %u", GET_U_1(cp),
565ee67461eSJoseph Mingrone                                          GET_U_1(cp + 1));
566a5779b6eSRui Paulo                                 break;
567a5779b6eSRui Paulo 
5683340d773SGleb Smirnoff                         case TCPOPT_TCPAO:
5693340d773SGleb Smirnoff                                 datalen = len - 2;
5703340d773SGleb Smirnoff                                 /* RFC 5925 Section 2.2:
5713340d773SGleb Smirnoff                                  * "The Length value MUST be greater than or equal to 4."
5723340d773SGleb Smirnoff                                  * (This includes the Kind and Length fields already processed
5733340d773SGleb Smirnoff                                  * at this point.)
5743340d773SGleb Smirnoff                                  */
5753340d773SGleb Smirnoff                                 if (datalen < 2) {
576ee67461eSJoseph Mingrone                                         nd_print_invalid(ndo);
5773340d773SGleb Smirnoff                                 } else {
5783340d773SGleb Smirnoff                                         LENCHECK(1);
579ee67461eSJoseph Mingrone                                         ND_PRINT(" keyid %u", GET_U_1(cp));
5803340d773SGleb Smirnoff                                         LENCHECK(2);
581ee67461eSJoseph Mingrone                                         ND_PRINT(" rnextkeyid %u",
582ee67461eSJoseph Mingrone                                                  GET_U_1(cp + 1));
5833340d773SGleb Smirnoff                                         if (datalen > 2) {
584ee67461eSJoseph Mingrone                                                 ND_PRINT(" mac 0x");
5853340d773SGleb Smirnoff                                                 for (i = 2; i < datalen; i++) {
5863340d773SGleb Smirnoff                                                         LENCHECK(i + 1);
587ee67461eSJoseph Mingrone                                                         ND_PRINT("%02x",
588ee67461eSJoseph Mingrone                                                                  GET_U_1(cp + i));
5893340d773SGleb Smirnoff                                                 }
5903340d773SGleb Smirnoff                                         }
5913340d773SGleb Smirnoff                                 }
5923340d773SGleb Smirnoff                                 break;
593a5779b6eSRui Paulo 
594a5779b6eSRui Paulo                         case TCPOPT_EOL:
595a5779b6eSRui Paulo                         case TCPOPT_NOP:
596a5779b6eSRui Paulo                         case TCPOPT_SACKOK:
597a5779b6eSRui Paulo                                 /*
598a5779b6eSRui Paulo                                  * Nothing interesting.
599a5779b6eSRui Paulo                                  * fall through
600a5779b6eSRui Paulo                                  */
601a5779b6eSRui Paulo                                 break;
602a5779b6eSRui Paulo 
603ce3ed1caSRui Paulo                         case TCPOPT_UTO:
604ce3ed1caSRui Paulo                                 datalen = 2;
605ce3ed1caSRui Paulo                                 LENCHECK(datalen);
606ee67461eSJoseph Mingrone                                 utoval = GET_BE_U_2(cp);
607ee67461eSJoseph Mingrone                                 ND_PRINT(" 0x%x", utoval);
608ce3ed1caSRui Paulo                                 if (utoval & 0x0001)
609ce3ed1caSRui Paulo                                         utoval = (utoval >> 1) * 60;
610ce3ed1caSRui Paulo                                 else
611ce3ed1caSRui Paulo                                         utoval >>= 1;
612ee67461eSJoseph Mingrone                                 ND_PRINT(" %u", utoval);
6133c602fabSXin LI                                 break;
6143c602fabSXin LI 
6153c602fabSXin LI                         case TCPOPT_MPTCP:
616ee67461eSJoseph Mingrone                             {
617ee67461eSJoseph Mingrone                                 const u_char *snapend_save;
618ee67461eSJoseph Mingrone                                 int ret;
619ee67461eSJoseph Mingrone 
6203c602fabSXin LI                                 datalen = len - 2;
6213c602fabSXin LI                                 LENCHECK(datalen);
622ee67461eSJoseph Mingrone                                 /* Update the snapend to the end of the option
623ee67461eSJoseph Mingrone                                  * before calling mptcp_print(). Some options
624ee67461eSJoseph Mingrone                                  * (MPTCP or others) may be present after a
625ee67461eSJoseph Mingrone                                  * MPTCP option. This prevents that, in
626ee67461eSJoseph Mingrone                                  * mptcp_print(), the remaining length < the
627ee67461eSJoseph Mingrone                                  * remaining caplen.
628ee67461eSJoseph Mingrone                                  */
629ee67461eSJoseph Mingrone                                 snapend_save = ndo->ndo_snapend;
630ee67461eSJoseph Mingrone                                 ndo->ndo_snapend = ND_MIN(cp - 2 + len,
631ee67461eSJoseph Mingrone                                                           ndo->ndo_snapend);
632ee67461eSJoseph Mingrone                                 ret = mptcp_print(ndo, cp - 2, len, flags);
633ee67461eSJoseph Mingrone                                 ndo->ndo_snapend = snapend_save;
634ee67461eSJoseph Mingrone                                 if (!ret)
6353c602fabSXin LI                                         goto bad;
6363c602fabSXin LI                                 break;
637ee67461eSJoseph Mingrone                             }
6383c602fabSXin LI 
6393340d773SGleb Smirnoff                         case TCPOPT_FASTOPEN:
6403340d773SGleb Smirnoff                                 datalen = len - 2;
6413340d773SGleb Smirnoff                                 LENCHECK(datalen);
642ee67461eSJoseph Mingrone                                 ND_PRINT(" ");
6433340d773SGleb Smirnoff                                 print_tcp_fastopen_option(ndo, cp, datalen, FALSE);
6443340d773SGleb Smirnoff                                 break;
6453340d773SGleb Smirnoff 
6463c602fabSXin LI                         case TCPOPT_EXPERIMENT2:
6473c602fabSXin LI                                 datalen = len - 2;
6483c602fabSXin LI                                 LENCHECK(datalen);
6493c602fabSXin LI                                 if (datalen < 2)
6503c602fabSXin LI                                         goto bad;
6513c602fabSXin LI                                 /* RFC6994 */
652ee67461eSJoseph Mingrone                                 magic = GET_BE_U_2(cp);
653ee67461eSJoseph Mingrone                                 ND_PRINT("-");
6543c602fabSXin LI 
6553c602fabSXin LI                                 switch(magic) {
6563c602fabSXin LI 
6573340d773SGleb Smirnoff                                 case 0xf989: /* TCP Fast Open RFC 7413 */
6583340d773SGleb Smirnoff                                         print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE);
6593c602fabSXin LI                                         break;
6603c602fabSXin LI 
6613c602fabSXin LI                                 default:
6623c602fabSXin LI                                         /* Unknown magic number */
663ee67461eSJoseph Mingrone                                         ND_PRINT("%04x", magic);
6643c602fabSXin LI                                         break;
6653c602fabSXin LI                                 }
666ce3ed1caSRui Paulo                                 break;
667ce3ed1caSRui Paulo 
6684edb46e9SPaul Traina                         default:
6694edb46e9SPaul Traina                                 datalen = len - 2;
6703c602fabSXin LI                                 if (datalen)
671ee67461eSJoseph Mingrone                                         ND_PRINT(" 0x");
6724edb46e9SPaul Traina                                 for (i = 0; i < datalen; ++i) {
6733340d773SGleb Smirnoff                                         LENCHECK(i + 1);
674ee67461eSJoseph Mingrone                                         ND_PRINT("%02x", GET_U_1(cp + i));
6754edb46e9SPaul Traina                                 }
6764edb46e9SPaul Traina                                 break;
6774edb46e9SPaul Traina                         }
6784edb46e9SPaul Traina 
6794edb46e9SPaul Traina                         /* Account for data printed */
6804edb46e9SPaul Traina                         cp += datalen;
6814edb46e9SPaul Traina                         hlen -= datalen;
6824edb46e9SPaul Traina 
6834edb46e9SPaul Traina                         /* Check specification against observed length */
6844edb46e9SPaul Traina                         ++datalen;		/* option octet */
6854edb46e9SPaul Traina                         if (!ZEROLENOPT(opt))
6864edb46e9SPaul Traina                                 ++datalen;	/* size octet */
6874edb46e9SPaul Traina                         if (datalen != len)
688ee67461eSJoseph Mingrone                                 ND_PRINT("[len %u]", len);
6894edb46e9SPaul Traina                         ch = ',';
6904de76e31SBill Fenner                         if (opt == TCPOPT_EOL)
6914de76e31SBill Fenner                                 break;
6924edb46e9SPaul Traina                 }
693ee67461eSJoseph Mingrone                 ND_PRINT("]");
6944edb46e9SPaul Traina         }
695b0453382SBill Fenner 
696a5779b6eSRui Paulo         /*
697a5779b6eSRui Paulo          * Print length field before crawling down the stack.
698a5779b6eSRui Paulo          */
699ee67461eSJoseph Mingrone         ND_PRINT(", length %u", length);
700a5779b6eSRui Paulo 
701ee67461eSJoseph Mingrone         if (length == 0)
702b0453382SBill Fenner                 return;
703b0453382SBill Fenner 
704b0453382SBill Fenner         /*
705b0453382SBill Fenner          * Decode payload if necessary.
706b0453382SBill Fenner          */
707ee67461eSJoseph Mingrone         header_len = TH_OFF(tp) * 4;
708ee67461eSJoseph Mingrone         /*
709ee67461eSJoseph Mingrone          * Do a bounds check before decoding the payload.
710ee67461eSJoseph Mingrone          * At least the header data is required.
711ee67461eSJoseph Mingrone          */
712ee67461eSJoseph Mingrone         if (!ND_TTEST_LEN(bp, header_len)) {
713ee67461eSJoseph Mingrone                 ND_PRINT(" [remaining caplen(%u) < header length(%u)]",
714ee67461eSJoseph Mingrone                          ND_BYTES_AVAILABLE_AFTER(bp), header_len);
715ee67461eSJoseph Mingrone                 nd_trunc_longjmp(ndo);
716ee67461eSJoseph Mingrone         }
717ee67461eSJoseph Mingrone         bp += header_len;
7183c602fabSXin LI         if ((flags & TH_RST) && ndo->ndo_vflag) {
7193c602fabSXin LI                 print_tcp_rst_data(ndo, bp, length);
720a5779b6eSRui Paulo                 return;
721a5779b6eSRui Paulo         }
722a5779b6eSRui Paulo 
7233c602fabSXin LI         if (ndo->ndo_packettype) {
7243c602fabSXin LI                 switch (ndo->ndo_packettype) {
725d03c0883SXin LI                 case PT_ZMTP1:
7263c602fabSXin LI                         zmtp1_print(ndo, bp, length);
727d03c0883SXin LI                         break;
7283340d773SGleb Smirnoff                 case PT_RESP:
7293340d773SGleb Smirnoff                         resp_print(ndo, bp, length);
7303340d773SGleb Smirnoff                         break;
731ee67461eSJoseph Mingrone                 case PT_DOMAIN:
732ee67461eSJoseph Mingrone                         /* over_tcp: TRUE, is_mdns: FALSE */
733ee67461eSJoseph Mingrone                         domain_print(ndo, bp, length, TRUE, FALSE);
734ee67461eSJoseph Mingrone                         break;
735d03c0883SXin LI                 }
736d03c0883SXin LI                 return;
737d03c0883SXin LI         }
738d03c0883SXin LI 
739*0a7e5f1fSJoseph Mingrone         if (IS_SRC_OR_DST_PORT(FTP_PORT)) {
740*0a7e5f1fSJoseph Mingrone                 ND_PRINT(": ");
741*0a7e5f1fSJoseph Mingrone                 ftp_print(ndo, bp, length);
742*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(SSH_PORT)) {
743*0a7e5f1fSJoseph Mingrone                 ssh_print(ndo, bp, length);
744*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(TELNET_PORT)) {
7453c602fabSXin LI                 telnet_print(ndo, bp, length);
7463340d773SGleb Smirnoff         } else if (IS_SRC_OR_DST_PORT(SMTP_PORT)) {
747ee67461eSJoseph Mingrone                 ND_PRINT(": ");
7488bdc5a62SPatrick Kelsey                 smtp_print(ndo, bp, length);
749ee67461eSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(WHOIS_PORT)) {
750ee67461eSJoseph Mingrone                 ND_PRINT(": ");
751ee67461eSJoseph Mingrone                 whois_print(ndo, bp, length);
752ee67461eSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(NAMESERVER_PORT)) {
753ee67461eSJoseph Mingrone                 /* over_tcp: TRUE, is_mdns: FALSE */
754ee67461eSJoseph Mingrone                 domain_print(ndo, bp, length, TRUE, FALSE);
755*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(HTTP_PORT)) {
756*0a7e5f1fSJoseph Mingrone                 ND_PRINT(": ");
757*0a7e5f1fSJoseph Mingrone                 http_print(ndo, bp, length);
758*0a7e5f1fSJoseph Mingrone #ifdef ENABLE_SMB
759*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(NETBIOS_SSN_PORT)) {
760*0a7e5f1fSJoseph Mingrone                 nbt_tcp_print(ndo, bp, length);
761*0a7e5f1fSJoseph Mingrone #endif
762*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(BGP_PORT)) {
763*0a7e5f1fSJoseph Mingrone                 bgp_print(ndo, bp, length);
7643340d773SGleb Smirnoff         } else if (IS_SRC_OR_DST_PORT(RPKI_RTR_PORT)) {
7653c602fabSXin LI                 rpki_rtr_print(ndo, bp, length);
766*0a7e5f1fSJoseph Mingrone #ifdef ENABLE_SMB
767*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(SMB_PORT)) {
768*0a7e5f1fSJoseph Mingrone                 smb_tcp_print(ndo, bp, length);
769*0a7e5f1fSJoseph Mingrone #endif
770*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(RTSP_PORT)) {
771*0a7e5f1fSJoseph Mingrone                 ND_PRINT(": ");
772*0a7e5f1fSJoseph Mingrone                 rtsp_print(ndo, bp, length);
773*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(MSDP_PORT)) {
774*0a7e5f1fSJoseph Mingrone                 msdp_print(ndo, bp, length);
775ee67461eSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(LDP_PORT)) {
7763c602fabSXin LI                 ldp_print(ndo, bp, length);
777*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(PPTP_PORT))
778*0a7e5f1fSJoseph Mingrone                 pptp_print(ndo, bp);
779*0a7e5f1fSJoseph Mingrone         else if (IS_SRC_OR_DST_PORT(REDIS_PORT))
780*0a7e5f1fSJoseph Mingrone                 resp_print(ndo, bp, length);
781*0a7e5f1fSJoseph Mingrone         else if (IS_SRC_OR_DST_PORT(BEEP_PORT))
782*0a7e5f1fSJoseph Mingrone                 beep_print(ndo, bp, length);
783*0a7e5f1fSJoseph Mingrone         else if (IS_SRC_OR_DST_PORT(OPENFLOW_PORT_OLD) || IS_SRC_OR_DST_PORT(OPENFLOW_PORT_IANA)) {
784*0a7e5f1fSJoseph Mingrone                 openflow_print(ndo, bp, length);
785*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(HTTP_PORT_ALT)) {
786*0a7e5f1fSJoseph Mingrone                 ND_PRINT(": ");
787*0a7e5f1fSJoseph Mingrone                 http_print(ndo, bp, length);
788*0a7e5f1fSJoseph Mingrone         } else if (IS_SRC_OR_DST_PORT(RTSP_PORT_ALT)) {
789*0a7e5f1fSJoseph Mingrone                 ND_PRINT(": ");
790*0a7e5f1fSJoseph Mingrone                 rtsp_print(ndo, bp, length);
791ee67461eSJoseph Mingrone         } else if ((IS_SRC_OR_DST_PORT(NFS_PORT)) &&
792ee67461eSJoseph Mingrone                  length >= 4 && ND_TTEST_4(bp)) {
7933c602fabSXin LI                 /*
7943c602fabSXin LI                  * If data present, header length valid, and NFS port used,
7953c602fabSXin LI                  * assume NFS.
7963c602fabSXin LI                  * Pass offset of data plus 4 bytes for RPC TCP msg length
7973c602fabSXin LI                  * to NFS print routines.
7983c602fabSXin LI                  */
7993c602fabSXin LI                 uint32_t fraglen;
800ee67461eSJoseph Mingrone                 const struct sunrpc_msg *rp;
8013c602fabSXin LI                 enum sunrpc_msg_type direction;
8023c602fabSXin LI 
803ee67461eSJoseph Mingrone                 fraglen = GET_BE_U_4(bp) & 0x7FFFFFFF;
8043c602fabSXin LI                 if (fraglen > (length) - 4)
8053c602fabSXin LI                         fraglen = (length) - 4;
8063340d773SGleb Smirnoff                 rp = (const struct sunrpc_msg *)(bp + 4);
807ee67461eSJoseph Mingrone                 if (ND_TTEST_4(rp->rm_direction)) {
808ee67461eSJoseph Mingrone                         direction = (enum sunrpc_msg_type) GET_BE_U_4(rp->rm_direction);
8093c602fabSXin LI                         if (dport == NFS_PORT && direction == SUNRPC_CALL) {
810ee67461eSJoseph Mingrone                                 ND_PRINT(": NFS request xid %u ",
811ee67461eSJoseph Mingrone                                          GET_BE_U_4(rp->rm_xid));
812ee67461eSJoseph Mingrone                                 nfsreq_noaddr_print(ndo, (const u_char *)rp, fraglen, (const u_char *)ip);
8133c602fabSXin LI                                 return;
8143c602fabSXin LI                         }
8153c602fabSXin LI                         if (sport == NFS_PORT && direction == SUNRPC_REPLY) {
816ee67461eSJoseph Mingrone                                 ND_PRINT(": NFS reply xid %u ",
817ee67461eSJoseph Mingrone                                          GET_BE_U_4(rp->rm_xid));
818ee67461eSJoseph Mingrone                                 nfsreply_noaddr_print(ndo, (const u_char *)rp, fraglen, (const u_char *)ip);
8193c602fabSXin LI                                 return;
8203c602fabSXin LI                         }
8213c602fabSXin LI                 }
8221de50e9fSSam Leffler         }
823a5779b6eSRui Paulo 
8244edb46e9SPaul Traina         return;
8254de76e31SBill Fenner bad:
826ee67461eSJoseph Mingrone         ND_PRINT("[bad opt]");
8274de76e31SBill Fenner         if (ch != '\0')
828ee67461eSJoseph Mingrone                 ND_PRINT("]");
8294de76e31SBill Fenner         return;
8304edb46e9SPaul Traina trunc:
831ee67461eSJoseph Mingrone         nd_print_trunc(ndo);
8324edb46e9SPaul Traina         if (ch != '\0')
833ee67461eSJoseph Mingrone                 ND_PRINT(">");
8344edb46e9SPaul Traina }
8354edb46e9SPaul Traina 
836685295f4SBill Fenner /*
837685295f4SBill Fenner  * RFC1122 says the following on data in RST segments:
838685295f4SBill Fenner  *
839685295f4SBill Fenner  *         4.2.2.12  RST Segment: RFC-793 Section 3.4
840685295f4SBill Fenner  *
841685295f4SBill Fenner  *            A TCP SHOULD allow a received RST segment to include data.
842685295f4SBill Fenner  *
843685295f4SBill Fenner  *            DISCUSSION
844685295f4SBill Fenner  *                 It has been suggested that a RST segment could contain
845685295f4SBill Fenner  *                 ASCII text that encoded and explained the cause of the
846685295f4SBill Fenner  *                 RST.  No standard has yet been established for such
847685295f4SBill Fenner  *                 data.
848685295f4SBill Fenner  *
849685295f4SBill Fenner  */
850685295f4SBill Fenner 
851685295f4SBill Fenner static void
print_tcp_rst_data(netdissect_options * ndo,const u_char * sp,u_int length)8523c602fabSXin LI print_tcp_rst_data(netdissect_options *ndo,
853ee67461eSJoseph Mingrone                    const u_char *sp, u_int length)
854685295f4SBill Fenner {
855ee67461eSJoseph Mingrone         u_char c;
856685295f4SBill Fenner 
857ee67461eSJoseph Mingrone         ND_PRINT(ND_TTEST_LEN(sp, length) ? " [RST" : " [!RST");
858685295f4SBill Fenner         if (length > MAX_RST_DATA_LEN) {
859685295f4SBill Fenner                 length = MAX_RST_DATA_LEN;	/* can use -X for longer */
860ee67461eSJoseph Mingrone                 ND_PRINT("+");			/* indicate we truncate */
861685295f4SBill Fenner         }
862ee67461eSJoseph Mingrone         ND_PRINT(" ");
863ee67461eSJoseph Mingrone         while (length && sp < ndo->ndo_snapend) {
864ee67461eSJoseph Mingrone                 c = GET_U_1(sp);
865ee67461eSJoseph Mingrone                 sp++;
866ee67461eSJoseph Mingrone                 fn_print_char(ndo, c);
867ee67461eSJoseph Mingrone                 length--;
868685295f4SBill Fenner         }
869ee67461eSJoseph Mingrone         ND_PRINT("]");
870685295f4SBill Fenner }
8711de50e9fSSam Leffler 
8723340d773SGleb Smirnoff static void
print_tcp_fastopen_option(netdissect_options * ndo,const u_char * cp,u_int datalen,int exp)873ee67461eSJoseph Mingrone print_tcp_fastopen_option(netdissect_options *ndo, const u_char *cp,
8743340d773SGleb Smirnoff                           u_int datalen, int exp)
8753340d773SGleb Smirnoff {
8763340d773SGleb Smirnoff         u_int i;
8773340d773SGleb Smirnoff 
8783340d773SGleb Smirnoff         if (exp)
879ee67461eSJoseph Mingrone                 ND_PRINT("tfo");
8803340d773SGleb Smirnoff 
8813340d773SGleb Smirnoff         if (datalen == 0) {
8823340d773SGleb Smirnoff                 /* Fast Open Cookie Request */
883ee67461eSJoseph Mingrone                 ND_PRINT(" cookiereq");
8843340d773SGleb Smirnoff         } else {
8853340d773SGleb Smirnoff                 /* Fast Open Cookie */
8863340d773SGleb Smirnoff                 if (datalen % 2 != 0 || datalen < 4 || datalen > 16) {
887ee67461eSJoseph Mingrone                         nd_print_invalid(ndo);
8883340d773SGleb Smirnoff                 } else {
889ee67461eSJoseph Mingrone                         ND_PRINT(" cookie ");
8903340d773SGleb Smirnoff                         for (i = 0; i < datalen; ++i)
891ee67461eSJoseph Mingrone                                 ND_PRINT("%02x", GET_U_1(cp + i));
8923340d773SGleb Smirnoff                 }
8933340d773SGleb Smirnoff         }
8943340d773SGleb Smirnoff }
8953340d773SGleb Smirnoff 
8961de50e9fSSam Leffler #ifdef HAVE_LIBCRYPTO
897ee67461eSJoseph Mingrone DIAG_OFF_DEPRECATION
8981de50e9fSSam Leffler static int
tcp_verify_signature(netdissect_options * ndo,const struct ip * ip,const struct tcphdr * tp,const u_char * data,u_int length,const u_char * rcvsig)8993c602fabSXin LI tcp_verify_signature(netdissect_options *ndo,
9003c602fabSXin LI                      const struct ip *ip, const struct tcphdr *tp,
901ee67461eSJoseph Mingrone                      const u_char *data, u_int length, const u_char *rcvsig)
9021de50e9fSSam Leffler {
9031de50e9fSSam Leffler         struct tcphdr tp1;
904f4d0c64aSSam Leffler         u_char sig[TCP_SIGLEN];
9051de50e9fSSam Leffler         char zero_proto = 0;
9061de50e9fSSam Leffler         MD5_CTX ctx;
9073c602fabSXin LI         uint16_t savecsum, tlen;
9083340d773SGleb Smirnoff         const struct ip6_hdr *ip6;
9093c602fabSXin LI         uint32_t len32;
9103c602fabSXin LI         uint8_t nxt;
9111de50e9fSSam Leffler 
9123c602fabSXin LI         if (data + length > ndo->ndo_snapend) {
913ee67461eSJoseph Mingrone                 ND_PRINT("snaplen too short, ");
91427df3f5dSRui Paulo                 return (CANT_CHECK_SIGNATURE);
91527df3f5dSRui Paulo         }
91627df3f5dSRui Paulo 
9171de50e9fSSam Leffler         tp1 = *tp;
9181de50e9fSSam Leffler 
9193c602fabSXin LI         if (ndo->ndo_sigsecret == NULL) {
920ee67461eSJoseph Mingrone                 ND_PRINT("shared secret not supplied with -M, ");
9211de50e9fSSam Leffler                 return (CANT_CHECK_SIGNATURE);
92227df3f5dSRui Paulo         }
9231de50e9fSSam Leffler 
9241de50e9fSSam Leffler         MD5_Init(&ctx);
9251de50e9fSSam Leffler         /*
9261de50e9fSSam Leffler          * Step 1: Update MD5 hash with IP pseudo-header.
9271de50e9fSSam Leffler          */
9281de50e9fSSam Leffler         if (IP_V(ip) == 4) {
9293340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&ip->ip_src, sizeof(ip->ip_src));
9303340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&ip->ip_dst, sizeof(ip->ip_dst));
9313340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&zero_proto, sizeof(zero_proto));
9323340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&ip->ip_p, sizeof(ip->ip_p));
933ee67461eSJoseph Mingrone                 tlen = GET_BE_U_2(ip->ip_len) - IP_HL(ip) * 4;
9341de50e9fSSam Leffler                 tlen = htons(tlen);
9353340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&tlen, sizeof(tlen));
9361de50e9fSSam Leffler         } else if (IP_V(ip) == 6) {
9373340d773SGleb Smirnoff                 ip6 = (const struct ip6_hdr *)ip;
9383340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&ip6->ip6_src, sizeof(ip6->ip6_src));
9393340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst));
940ee67461eSJoseph Mingrone                 len32 = htonl(GET_BE_U_2(ip6->ip6_plen));
9413340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&len32, sizeof(len32));
9421de50e9fSSam Leffler                 nxt = 0;
9433340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt));
9443340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt));
9453340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt));
9461de50e9fSSam Leffler                 nxt = IPPROTO_TCP;
9473340d773SGleb Smirnoff                 MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt));
94827df3f5dSRui Paulo         } else {
949ee67461eSJoseph Mingrone                 ND_PRINT("IP version not 4 or 6, ");
9501de50e9fSSam Leffler                 return (CANT_CHECK_SIGNATURE);
95127df3f5dSRui Paulo         }
9521de50e9fSSam Leffler 
9531de50e9fSSam Leffler         /*
9541de50e9fSSam Leffler          * Step 2: Update MD5 hash with TCP header, excluding options.
9551de50e9fSSam Leffler          * The TCP checksum must be set to zero.
9561de50e9fSSam Leffler          */
957ee67461eSJoseph Mingrone         memcpy(&savecsum, tp1.th_sum, sizeof(savecsum));
958ee67461eSJoseph Mingrone         memset(tp1.th_sum, 0, sizeof(tp1.th_sum));
9593340d773SGleb Smirnoff         MD5_Update(&ctx, (const char *)&tp1, sizeof(struct tcphdr));
960ee67461eSJoseph Mingrone         memcpy(tp1.th_sum, &savecsum, sizeof(tp1.th_sum));
9611de50e9fSSam Leffler         /*
9621de50e9fSSam Leffler          * Step 3: Update MD5 hash with TCP segment data, if present.
9631de50e9fSSam Leffler          */
9641de50e9fSSam Leffler         if (length > 0)
9651de50e9fSSam Leffler                 MD5_Update(&ctx, data, length);
9661de50e9fSSam Leffler         /*
9671de50e9fSSam Leffler          * Step 4: Update MD5 hash with shared secret.
9681de50e9fSSam Leffler          */
9693c602fabSXin LI         MD5_Update(&ctx, ndo->ndo_sigsecret, strlen(ndo->ndo_sigsecret));
9701de50e9fSSam Leffler         MD5_Final(sig, &ctx);
9711de50e9fSSam Leffler 
972b5bfcb5dSMax Laier         if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0)
9731de50e9fSSam Leffler                 return (SIGNATURE_VALID);
9741de50e9fSSam Leffler         else
9751de50e9fSSam Leffler                 return (SIGNATURE_INVALID);
9761de50e9fSSam Leffler }
977ee67461eSJoseph Mingrone DIAG_ON_DEPRECATION
9781de50e9fSSam Leffler #endif /* HAVE_LIBCRYPTO */
979