1/*	$NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky Exp $	*/
2
3/*
4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Copyright (c) 1999-2004 The tcpdump.org project
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that: (1) source code distributions
11 * retain the above copyright notice and this paragraph in its entirety, (2)
12 * distributions including binary code include the above copyright notice and
13 * this paragraph in its entirety in the documentation or other materials
14 * provided with the distribution, and (3) all advertising materials mentioning
15 * features or use of this software display the following acknowledgement:
16 * ``This product includes software developed by the University of California,
17 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
18 * the University nor the names of its contributors may be used to endorse
19 * or promote products derived from this software without specific prior
20 * written permission.
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 */
25
26#ifndef lint
27static const char rcsid[] _U_ =
28"@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.135 2008-11-09 23:35:03 mcr Exp $ (LBL)";
29#else
30__RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $");
31#endif
32
33#ifdef HAVE_CONFIG_H
34#include "config.h"
35#endif
36
37#include <tcpdump-stdinc.h>
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
43#include "interface.h"
44#include "addrtoname.h"
45#include "extract.h"
46
47#include "tcp.h"
48
49#include "ip.h"
50#ifdef INET6
51#include "ip6.h"
52#endif
53#include "ipproto.h"
54#include "rpc_auth.h"
55#include "rpc_msg.h"
56
57#include "nameser.h"
58
59#ifdef HAVE_LIBCRYPTO
60#include <CommonCrypto/CommonDigest.h>
61#include <signature.h>
62
63static int tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp,
64                                const u_char *data, int length, const u_char *rcvsig);
65#endif
66
67static void print_tcp_rst_data(register const u_char *sp, u_int length);
68
69#define MAX_RST_DATA_LEN	30
70
71
72struct tha {
73#ifndef INET6
74        struct in_addr src;
75        struct in_addr dst;
76#else
77        struct in6_addr src;
78        struct in6_addr dst;
79#endif /*INET6*/
80        u_int port;
81};
82
83struct tcp_seq_hash {
84        struct tcp_seq_hash *nxt;
85        struct tha addr;
86        tcp_seq seq;
87        tcp_seq ack;
88};
89
90#define TSEQ_HASHSIZE 919
91
92/* These tcp optinos do not have the size octet */
93#define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP)
94
95static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
96
97struct tok tcp_flag_values[] = {
98        { TH_FIN, "F" },
99        { TH_SYN, "S" },
100        { TH_RST, "R" },
101        { TH_PUSH, "P" },
102        { TH_ACK, "." },
103        { TH_URG, "U" },
104        { TH_ECNECHO, "E" },
105        { TH_CWR, "W" },
106        { 0, NULL }
107};
108
109struct tok tcp_option_values[] = {
110        { TCPOPT_EOL, "eol" },
111        { TCPOPT_NOP, "nop" },
112        { TCPOPT_MAXSEG, "mss" },
113        { TCPOPT_WSCALE, "wscale" },
114        { TCPOPT_SACKOK, "sackOK" },
115        { TCPOPT_SACK, "sack" },
116        { TCPOPT_ECHO, "echo" },
117        { TCPOPT_ECHOREPLY, "echoreply" },
118        { TCPOPT_TIMESTAMP, "TS" },
119        { TCPOPT_CC, "cc" },
120        { TCPOPT_CCNEW, "ccnew" },
121        { TCPOPT_CCECHO, "" },
122        { TCPOPT_SIGNATURE, "md5" },
123        { TCPOPT_AUTH, "enhanced auth" },
124        { TCPOPT_MPTCP, "mp" },
125        { TCPOPT_UTO, "uto" },
126        { 0, NULL }
127};
128
129struct tok mptcp_subtypes[] = {
130	{ TCPOPT_MPTCP_MP_CAPABLE, "capable" },
131	{ TCPOPT_MPTCP_MP_JOIN, "join" },
132	{ TCPOPT_MPTCP_DSS, "dss" },
133	{ TCPOPT_MPTCP_ADD_ADDR, "addaddr" },
134	{ TCPOPT_MPTCP_REMOVE_ADDR, "removeaddr" },
135	{ TCPOPT_MPTCP_MP_PRIO, "prio" },
136	{ TCPOPT_MPTCP_MP_FAIL, "fail" },
137	{ TCPOPT_MPTCP_MP_FASTCLOSE, "fastclose" },
138	{ 0, NULL }
139};
140
141static int tcp_cksum(register const struct ip *ip,
142		     register const struct tcphdr *tp,
143		     register u_int len)
144{
145	return (nextproto4_cksum(ip, (const u_int8_t *)tp, len,
146	    IPPROTO_TCP));
147}
148
149void
150tcp_print(register const u_char *bp, register u_int length,
151	  register const u_char *bp2, int fragmented)
152{
153        register const struct tcphdr *tp;
154        register const struct ip *ip;
155        register u_char flags;
156        register u_int hlen;
157        register char ch;
158        u_int16_t sport, dport, win, urp;
159        u_int32_t seq, ack, thseq, thack;
160        u_int utoval;
161        int threv;
162#ifdef INET6
163        register const struct ip6_hdr *ip6;
164#endif
165
166        tp = (struct tcphdr *)bp;
167        ip = (struct ip *)bp2;
168#ifdef INET6
169        if (IP_V(ip) == 6)
170                ip6 = (struct ip6_hdr *)bp2;
171        else
172                ip6 = NULL;
173#endif /*INET6*/
174        ch = '\0';
175        if (!TTEST(tp->th_dport)) {
176                (void)printf("%s > %s: [|tcp]",
177                             ipaddr_string(&ip->ip_src),
178                             ipaddr_string(&ip->ip_dst));
179                return;
180        }
181
182        sport = EXTRACT_16BITS(&tp->th_sport);
183        dport = EXTRACT_16BITS(&tp->th_dport);
184
185        hlen = TH_OFF(tp) * 4;
186
187        /*
188	 * If data present, header length valid, and NFS port used,
189	 * assume NFS.
190	 * Pass offset of data plus 4 bytes for RPC TCP msg length
191	 * to NFS print routines.
192	 */
193	if (!qflag && hlen >= sizeof(*tp) && hlen <= length &&
194	    (length - hlen) >= 4) {
195		u_char *fraglenp;
196		u_int32_t fraglen;
197		register struct sunrpc_msg *rp;
198		enum sunrpc_msg_type direction;
199
200		fraglenp = (u_char *)tp + hlen;
201		if (TTEST2(*fraglenp, 4)) {
202			fraglen = EXTRACT_32BITS(fraglenp) & 0x7FFFFFFF;
203			if (fraglen > (length - hlen) - 4)
204				fraglen = (length - hlen) - 4;
205			rp = (struct sunrpc_msg *)(fraglenp + 4);
206			if (TTEST(rp->rm_direction)) {
207				direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction);
208				if (dport == NFS_PORT &&
209				    direction == SUNRPC_CALL) {
210					nfsreq_print((u_char *)rp, fraglen,
211					    (u_char *)ip);
212					return;
213				}
214				if (sport == NFS_PORT &&
215				    direction == SUNRPC_REPLY) {
216					nfsreply_print((u_char *)rp, fraglen,
217					    (u_char *)ip);
218					return;
219				}
220			}
221                }
222        }
223#ifdef INET6
224        if (ip6) {
225                if (ip6->ip6_nxt == IPPROTO_TCP) {
226                        (void)printf("%s.%s > %s.%s: ",
227                                     ip6addr_string(&ip6->ip6_src),
228                                     tcpport_string(sport),
229                                     ip6addr_string(&ip6->ip6_dst),
230                                     tcpport_string(dport));
231                } else {
232                        (void)printf("%s > %s: ",
233                                     tcpport_string(sport), tcpport_string(dport));
234                }
235        } else
236#endif /*INET6*/
237        {
238                if (ip->ip_p == IPPROTO_TCP) {
239                        (void)printf("%s.%s > %s.%s: ",
240                                     ipaddr_string(&ip->ip_src),
241                                     tcpport_string(sport),
242                                     ipaddr_string(&ip->ip_dst),
243                                     tcpport_string(dport));
244                } else {
245                        (void)printf("%s > %s: ",
246                                     tcpport_string(sport), tcpport_string(dport));
247                }
248        }
249
250        if (hlen < sizeof(*tp)) {
251                (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]",
252                             length - hlen, hlen, (unsigned long)sizeof(*tp));
253                return;
254        }
255
256        TCHECK(*tp);
257
258        seq = EXTRACT_32BITS(&tp->th_seq);
259        ack = EXTRACT_32BITS(&tp->th_ack);
260        win = EXTRACT_16BITS(&tp->th_win);
261        urp = EXTRACT_16BITS(&tp->th_urp);
262
263        if (qflag) {
264                (void)printf("tcp %d", length - hlen);
265                if (hlen > length) {
266                        (void)printf(" [bad hdr length %u - too long, > %u]",
267                                     hlen, length);
268                }
269                return;
270        }
271
272        flags = tp->th_flags;
273        printf("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags));
274
275        if (!Sflag && (flags & TH_ACK)) {
276                register struct tcp_seq_hash *th;
277                const void *src, *dst;
278                register int rev;
279                struct tha tha;
280                /*
281                 * Find (or record) the initial sequence numbers for
282                 * this conversation.  (we pick an arbitrary
283                 * collating order so there's only one entry for
284                 * both directions).
285                 */
286#ifdef INET6
287                rev = 0;
288                if (ip6) {
289                        src = &ip6->ip6_src;
290                        dst = &ip6->ip6_dst;
291                        if (sport > dport)
292                                rev = 1;
293                        else if (sport == dport) {
294                                if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0)
295                                        rev = 1;
296                        }
297                        if (rev) {
298                                memcpy(&tha.src, dst, sizeof ip6->ip6_dst);
299                                memcpy(&tha.dst, src, sizeof ip6->ip6_src);
300                                tha.port = dport << 16 | sport;
301                        } else {
302                                memcpy(&tha.dst, dst, sizeof ip6->ip6_dst);
303                                memcpy(&tha.src, src, sizeof ip6->ip6_src);
304                                tha.port = sport << 16 | dport;
305                        }
306                } else {
307                        /*
308                         * Zero out the tha structure; the src and dst
309                         * fields are big enough to hold an IPv6
310                         * address, but we only have IPv4 addresses
311                         * and thus must clear out the remaining 124
312                         * bits.
313                         *
314                         * XXX - should we just clear those bytes after
315                         * copying the IPv4 addresses, rather than
316                         * zeroing out the entire structure and then
317                         * overwriting some of the zeroes?
318                         *
319                         * XXX - this could fail if we see TCP packets
320                         * with an IPv6 address with the lower 124 bits
321                         * all zero and also see TCP packes with an
322                         * IPv4 address with the same 32 bits as the
323                         * upper 32 bits of the IPv6 address in question.
324                         * Can that happen?  Is it likely enough to be
325                         * an issue?
326                         */
327                        memset(&tha, 0, sizeof(tha));
328                        src = &ip->ip_src;
329                        dst = &ip->ip_dst;
330                        if (sport > dport)
331                                rev = 1;
332                        else if (sport == dport) {
333                                if (memcmp(src, dst, sizeof ip->ip_dst) > 0)
334                                        rev = 1;
335                        }
336                        if (rev) {
337                                memcpy(&tha.src, dst, sizeof ip->ip_dst);
338                                memcpy(&tha.dst, src, sizeof ip->ip_src);
339                                tha.port = dport << 16 | sport;
340                        } else {
341                                memcpy(&tha.dst, dst, sizeof ip->ip_dst);
342                                memcpy(&tha.src, src, sizeof ip->ip_src);
343                                tha.port = sport << 16 | dport;
344                        }
345                }
346#else
347                rev = 0;
348                src = &ip->ip_src;
349                dst = &ip->ip_dst;
350                if (sport > dport)
351                        rev = 1;
352                else if (sport == dport) {
353                        if (memcmp(src, dst, sizeof ip->ip_dst) > 0)
354                                rev = 1;
355                }
356                if (rev) {
357                        memcpy(&tha.src, dst, sizeof ip->ip_dst);
358                        memcpy(&tha.dst, src, sizeof ip->ip_src);
359                        tha.port = dport << 16 | sport;
360                } else {
361                        memcpy(&tha.dst, dst, sizeof ip->ip_dst);
362                        memcpy(&tha.src, src, sizeof ip->ip_src);
363                        tha.port = sport << 16 | dport;
364                }
365#endif
366
367                threv = rev;
368                for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
369                     th->nxt; th = th->nxt)
370                        if (memcmp((char *)&tha, (char *)&th->addr,
371                                   sizeof(th->addr)) == 0)
372                                break;
373
374                if (!th->nxt || (flags & TH_SYN)) {
375                        /* didn't find it or new conversation */
376                        if (th->nxt == NULL) {
377                                th->nxt = (struct tcp_seq_hash *)
378                                        calloc(1, sizeof(*th));
379                                if (th->nxt == NULL)
380                                        error("tcp_print: calloc");
381                        }
382                        th->addr = tha;
383                        if (rev)
384                                th->ack = seq, th->seq = ack - 1;
385                        else
386                                th->seq = seq, th->ack = ack - 1;
387                } else {
388                        if (rev)
389                                seq -= th->ack, ack -= th->seq;
390                        else
391                                seq -= th->seq, ack -= th->ack;
392                }
393
394                thseq = th->seq;
395                thack = th->ack;
396        } else {
397                /*fool gcc*/
398                thseq = thack = threv = 0;
399        }
400        if (hlen > length) {
401                (void)printf(" [bad hdr length %u - too long, > %u]",
402                             hlen, length);
403                return;
404        }
405
406        if (vflag && !Kflag && !fragmented) {
407                /* Check the checksum, if possible. */
408                u_int16_t sum, tcp_sum;
409
410                if (IP_V(ip) == 4) {
411                        if (TTEST2(tp->th_sport, length)) {
412                                sum = tcp_cksum(ip, tp, length);
413                                tcp_sum = EXTRACT_16BITS(&tp->th_sum);
414
415                                (void)printf(", cksum 0x%04x", tcp_sum);
416                                if (sum != 0)
417                                        (void)printf(" (incorrect -> 0x%04x)",
418                                            in_cksum_shouldbe(tcp_sum, sum));
419                                else
420                                        (void)printf(" (correct)");
421                        }
422                }
423#ifdef INET6
424                else if (IP_V(ip) == 6 && ip6->ip6_plen) {
425                        if (TTEST2(tp->th_sport, length)) {
426                                sum = nextproto6_cksum(ip6, (const u_int8_t *)tp, length, IPPROTO_TCP);
427                                tcp_sum = EXTRACT_16BITS(&tp->th_sum);
428
429                                (void)printf(", cksum 0x%04x", tcp_sum);
430                                if (sum != 0)
431                                        (void)printf(" (incorrect -> 0x%04x)",
432                                            in_cksum_shouldbe(tcp_sum, sum));
433                                else
434                                        (void)printf(" (correct)");
435
436                        }
437                }
438#endif
439        }
440
441        length -= hlen;
442        if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) {
443                (void)printf(", seq %u", seq);
444
445                if (length > 0) {
446                        (void)printf(":%u", seq + length);
447                }
448        }
449
450        if (flags & TH_ACK) {
451                (void)printf(", ack %u", ack);
452        }
453
454        (void)printf(", win %d", win);
455
456        if (flags & TH_URG)
457                (void)printf(", urg %d", urp);
458        /*
459         * Handle any options.
460         */
461        if (hlen > sizeof(*tp)) {
462                register const u_char *cp;
463                register u_int i, opt, datalen;
464                register u_int len;
465
466                hlen -= sizeof(*tp);
467                cp = (const u_char *)tp + sizeof(*tp);
468                printf(", options [");
469                while (hlen > 0) {
470                        if (ch != '\0')
471                                putchar(ch);
472                        TCHECK(*cp);
473                        opt = *cp++;
474                        if (ZEROLENOPT(opt))
475                                len = 1;
476                        else {
477                                TCHECK(*cp);
478                                len = *cp++;	/* total including type, len */
479                                if (len < 2 || len > hlen)
480                                        goto bad;
481                                --hlen;		/* account for length byte */
482                        }
483                        --hlen;			/* account for type byte */
484                        datalen = 0;
485
486/* Bail if "l" bytes of data are not left or were not captured  */
487#define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); }
488
489
490                        printf("%s", tok2str(tcp_option_values, "Unknown Option %u", opt));
491
492                        switch (opt) {
493
494                        case TCPOPT_MAXSEG:
495                                datalen = 2;
496                                LENCHECK(datalen);
497                                (void)printf(" %u", EXTRACT_16BITS(cp));
498                                break;
499
500                        case TCPOPT_WSCALE:
501                                datalen = 1;
502                                LENCHECK(datalen);
503                                (void)printf(" %u", *cp);
504                                break;
505
506                        case TCPOPT_SACK:
507                                datalen = len - 2;
508                                if (datalen % 8 != 0) {
509                                        (void)printf("malformed sack");
510                                } else {
511                                        u_int32_t s, e;
512
513                                        (void)printf(" %d ", datalen / 8);
514                                        for (i = 0; i < datalen; i += 8) {
515                                                LENCHECK(i + 4);
516                                                s = EXTRACT_32BITS(cp + i);
517                                                LENCHECK(i + 8);
518                                                e = EXTRACT_32BITS(cp + i + 4);
519                                                if (threv) {
520                                                        s -= thseq;
521                                                        e -= thseq;
522                                                } else {
523                                                        s -= thack;
524                                                        e -= thack;
525                                                }
526                                                (void)printf("{%u:%u}", s, e);
527                                        }
528                                }
529                                break;
530
531                        case TCPOPT_CC:
532                        case TCPOPT_CCNEW:
533                        case TCPOPT_CCECHO:
534                        case TCPOPT_ECHO:
535                        case TCPOPT_ECHOREPLY:
536
537                                /*
538                                 * those options share their semantics.
539                                 * fall through
540                                 */
541                                datalen = 4;
542                                LENCHECK(datalen);
543                                (void)printf(" %u", EXTRACT_32BITS(cp));
544                                break;
545
546                        case TCPOPT_TIMESTAMP:
547                                datalen = 8;
548                                LENCHECK(datalen);
549                                (void)printf(" val %u ecr %u",
550                                             EXTRACT_32BITS(cp),
551                                             EXTRACT_32BITS(cp + 4));
552                                break;
553
554                        case TCPOPT_SIGNATURE:
555                                datalen = TCP_SIGLEN;
556                                LENCHECK(datalen);
557#ifdef HAVE_LIBCRYPTO
558                                switch (tcp_verify_signature(ip, tp,
559                                                             bp + TH_OFF(tp) * 4, length, cp)) {
560
561                                case SIGNATURE_VALID:
562                                        (void)printf("valid");
563                                        break;
564
565                                case SIGNATURE_INVALID:
566                                        (void)printf("invalid");
567                                        break;
568
569                                case CANT_CHECK_SIGNATURE:
570                                        (void)printf("can't check - ");
571                                        for (i = 0; i < TCP_SIGLEN; ++i)
572                                                (void)printf("%02x", cp[i]);
573                                        break;
574                                }
575#else
576                                for (i = 0; i < TCP_SIGLEN; ++i)
577                                        (void)printf("%02x", cp[i]);
578#endif
579                                break;
580
581                        case TCPOPT_AUTH:
582                                (void)printf("keyid %d", *cp++);
583                                datalen = len - 3;
584                                for (i = 0; i < datalen; ++i) {
585                                        LENCHECK(i);
586                                        (void)printf("%02x", cp[i]);
587                                }
588                                break;
589
590
591                        case TCPOPT_EOL:
592                        case TCPOPT_NOP:
593                        case TCPOPT_SACKOK:
594                                /*
595                                 * Nothing interesting.
596                                 * fall through
597                                 */
598                                break;
599
600                        case TCPOPT_UTO:
601                                datalen = 2;
602                                LENCHECK(datalen);
603                                utoval = EXTRACT_16BITS(cp);
604                                (void)printf("0x%x", utoval);
605                                if (utoval & 0x0001)
606                                        utoval = (utoval >> 1) * 60;
607                                else
608                                        utoval >>= 1;
609                                (void)printf(" %u", utoval);
610                                break;
611
612						case TCPOPT_MPTCP: {
613							uint8_t subtype;
614
615							datalen = 1;
616							LENCHECK(datalen);
617
618							subtype = (*cp) >> 4;
619
620							printf(" %s ", tok2str(mptcp_subtypes, "Unknown MPTCP subtype %u", subtype));
621
622							switch (subtype) {
623							case TCPOPT_MPTCP_MP_CAPABLE: {
624								uint8_t version = (*cp) & 0x0f;
625								uint8_t mpflags;
626
627								if (version != 0) {
628									printf(" version %u ", version);
629									for (i = 0; i < datalen; ++i) {
630										LENCHECK(i);
631										(void)printf("%02x", cp[i]);
632									}
633									break;
634								}
635
636								datalen += 1;
637								LENCHECK(datalen);
638								mpflags = cp[1];
639								printf("%s%s%s%s%s%s%s%s%s",
640									   (mpflags) ? "flags:" : "",
641									   (mpflags & 0x80) ? "A" : "",
642									   (mpflags & 0x40) ? "B" : "",
643									   (mpflags & 0x20) ? "C" : "",
644									   (mpflags & 0x10) ? "D" : "",
645									   (mpflags & 0x08) ? "E" : "",
646									   (mpflags & 0x04) ? "F" : "",
647									   (mpflags & 0x02) ? "G" : "",
648									   (mpflags & 0x01) ? "H" : "");
649
650								if (len == 12 || len == 20) {
651									printf(" sndkey:");
652									for (i = 0; i < 8; ++i) {
653										datalen++;
654										LENCHECK(datalen);
655										(void)printf("%02x", cp[2 + i]);
656									}
657
658									if (len == 20) {
659										printf(" rcvkey:");
660										for (i = 0; i < 8; ++i) {
661											datalen++;
662											LENCHECK(datalen);
663											(void)printf("%02x", cp[10 + i]);
664										}
665									}
666								} else {
667									printf(" unknown:");
668									datalen = len - 2;
669									for (i = 0; i < datalen; ++i) {
670										LENCHECK(i);
671										(void)printf("%02x", cp[i]);
672									}
673								}
674
675								break;
676							}
677							case TCPOPT_MPTCP_MP_JOIN: {
678								uint8_t mpflags = (*cp) & 0x0f;
679
680								/* Flags on SYN only */
681								if (flags & TH_SYN) {
682									printf("%s%s%s%s%s",
683										   (mpflags) ? "flags:" : "",
684										   (mpflags & 0x08) ? "0" : "",
685										   (mpflags & 0x04) ? "1" : "",
686										   (mpflags & 0x02) ? "2" : "",
687										   (mpflags & 0x01) ? "B" : "");
688								}
689								/* Address ID on SYN only, otherwise ignored */
690								datalen += 1;
691								LENCHECK(datalen);
692								if ((flags & TH_SYN))
693									printf(" addrid:%0x", cp[1]);
694
695								if (flags == TH_SYN && len == 12) {
696									/* Initial SYN */
697									printf(" rcvtok:");
698									for (i = 0; i < 4; ++i) {
699										datalen++;
700										LENCHECK(datalen);
701										(void)printf("%02x", cp[2 + i]);
702									}
703									printf(" sndrand:");
704									for (i = 0; i < 4; ++i) {
705										datalen++;
706										LENCHECK(datalen);
707										(void)printf("%02x", cp[6 + i]);
708									}
709								} else if ((flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK) && len == 16) {
710									/* Responding SYN/ACK */
711									printf(" sndhmac:");
712									for (i = 0; i < 8; ++i) {
713										datalen++;
714										LENCHECK(datalen);
715										(void)printf("%02x", cp[2 + i]);
716									}
717									printf(" sndrand:");
718									for (i = 0; i < 4; ++i) {
719										datalen++;
720										LENCHECK(datalen);
721										(void)printf("%02x", cp[8 + i]);
722									}
723								} else if ((flags & (TH_SYN | TH_ACK)) == TH_ACK && len == 24) {
724									/* Third ACK */
725									printf(" sndhmac:");
726									for (i = 0; i < 20; ++i) {
727										datalen++;
728										LENCHECK(i);
729										(void)printf("%02x", cp[2 + i]);
730									}
731								} else {
732									datalen = len - 2;
733									for (i = 0; i < datalen; ++i) {
734										LENCHECK(i);
735										(void)printf("%02x", cp[i]);
736									}
737								}
738								break;
739							}
740							case TCPOPT_MPTCP_DSS: {
741								uint8_t mpflags;
742								u_int ack_len = 0;
743								u_int dsn_len = 0;
744								u_int64_t dack;
745								u_int64_t dsn;
746								u_int32_t sfsn;
747								u_int16_t dlen;
748								u_int16_t csum;
749
750								datalen += 1;
751								LENCHECK(datalen);
752								mpflags = cp[1] & 0x1f;
753
754								printf("%s%s%s%s%s%s",
755									   (mpflags) ? "flags:" : "",
756									   (mpflags & 0x10) ? "F" : "",
757									   (mpflags & 0x08) ? "m" : "",
758									   (mpflags & 0x04) ? "M" : "",
759									   (mpflags & 0x02) ? "a" : "",
760									   (mpflags & 0x01) ? "A" : "");
761
762								if ((mpflags & MPDSS_FLAG_A)) {
763									if ((mpflags & MPDSS_FLAG_a)) {
764										ack_len = 8;
765										datalen += ack_len;
766										LENCHECK(datalen);
767										dack = EXTRACT_64BITS(cp + 2);
768									} else {
769										ack_len = 4;
770										datalen += ack_len;
771										LENCHECK(datalen);
772										dack = EXTRACT_32BITS(cp + 2);
773									}
774									(void)printf(" dack: %" PRIu64, dack);
775								}
776								if ((mpflags & MPDSS_FLAG_M)) {
777									if ((mpflags & MPDSS_FLAG_m)) {
778										dsn_len = 8;
779										datalen += dsn_len;
780										LENCHECK(datalen);
781										dsn = EXTRACT_64BITS(cp + 2 + ack_len);
782									} else {
783										dsn_len = 4;
784										datalen += dsn_len;
785										LENCHECK(datalen);
786										dsn = EXTRACT_32BITS(cp + 2 + ack_len);
787									}
788									(void)printf(" dsn: %" PRIu64, dsn);
789
790									datalen += 4;
791									LENCHECK(datalen);
792									sfsn = EXTRACT_32BITS(cp + 2 + ack_len + dsn_len);
793									(void)printf(" sfsn: %" PRIu32, sfsn);
794
795									datalen += 2;
796									LENCHECK(datalen);
797									dlen = EXTRACT_16BITS(cp + 2 + ack_len + dsn_len + 4);
798									(void)printf(" dlen: %" PRIu16, dlen);
799
800									/*
801									 * Use the length of the option to find out if
802									 * the checksum is present
803									 */
804									if (datalen < len - 2) {
805										datalen += 2;
806										LENCHECK(datalen);
807										csum = EXTRACT_16BITS(cp + 2 + ack_len + dsn_len + 6);
808										(void)printf(" csum: %" PRIu16, csum);
809									}
810								}
811								break;
812							}
813							case TCPOPT_MPTCP_ADD_ADDR: {
814								uint8_t ipvers;
815								u_int addrlen = 0;
816								u_int16_t port;
817
818								ipvers = cp[1] & 0xf0;
819								printf(" vers:%u", ipvers);
820
821								datalen = 2;
822								LENCHECK(datalen);
823								printf(" addrid:%0x", cp[1]);
824
825								switch (ipvers) {
826									case 4: {
827										datalen = 6;
828										LENCHECK(datalen);
829										ipaddr_string(cp + 2);
830										break;
831									}
832									case 6: {
833										datalen = 18;
834										LENCHECK(datalen);
835#ifdef INET6
836										ip6addr_string(cp + 2);
837#endif
838										break;
839									}
840									default:
841										goto bad;
842								}
843								/*
844								 * Use the length of the option to find out if
845								 * the port is present
846								 */
847								if (datalen < len - 2) {
848									datalen += 2;
849									LENCHECK(datalen);
850
851									port = EXTRACT_16BITS(cp + 2 + addrlen);
852
853									printf(" port: %u", port);
854								}
855								break;
856							}
857							case TCPOPT_MPTCP_REMOVE_ADDR:
858								datalen = len - 2;
859								for (i = 0; i < datalen; ++i) {
860									LENCHECK(i);
861									(void)printf(" %u", cp[i]);
862								}
863								break;
864
865							case TCPOPT_MPTCP_MP_PRIO: {
866								uint8_t mpflags = (*cp) & 0x0f;
867
868								printf("flag %s",
869									   (mpflags & 0x01) ? "B" : "");
870
871								if (len == 4) {
872									datalen = 2;
873									LENCHECK(i);
874									printf(" addrid:%0x", cp[1]);
875								}
876								break;
877							}
878							case TCPOPT_MPTCP_MP_FAIL:
879								datalen = 10;
880								LENCHECK(datalen);
881
882								printf(" dsn:");
883								for (i = 0; i < 8; ++i) {
884									(void)printf("%02x", cp[2 + i]);
885								}
886								break;
887
888							case TCPOPT_MPTCP_MP_FASTCLOSE:
889								datalen = 10;
890								LENCHECK(datalen);
891
892								printf(" rcvrkey:");
893								for (i = 0; i < 8; ++i) {
894									(void)printf("%02x", cp[2 + i]);
895								}
896								break;
897
898							default:
899								datalen = len - 2;
900								for (i = 0; i < datalen; ++i) {
901									LENCHECK(i);
902									(void)printf("%02x", cp[i]);
903								}
904								break;
905							}
906							break;
907						}
908
909                        default:
910                                datalen = len - 2;
911                                for (i = 0; i < datalen; ++i) {
912                                        LENCHECK(i);
913                                        (void)printf("%02x", cp[i]);
914                                }
915                                break;
916                        }
917
918                        /* Account for data printed */
919                        cp += datalen;
920                        hlen -= datalen;
921
922                        /* Check specification against observed length */
923                        ++datalen;			/* option octet */
924                        if (!ZEROLENOPT(opt))
925                                ++datalen;		/* size octet */
926                        if (datalen != len)
927                                (void)printf("[len %d]", len);
928                        ch = ',';
929                        if (opt == TCPOPT_EOL)
930                                break;
931                }
932                putchar(']');
933        }
934
935        /*
936         * Print length field before crawling down the stack.
937         */
938        printf(", length %u", length);
939
940        if (length <= 0)
941                return;
942
943        /*
944         * Decode payload if necessary.
945         */
946        bp += TH_OFF(tp) * 4;
947        if ((flags & TH_RST) && vflag) {
948                print_tcp_rst_data(bp, length);
949                return;
950        }
951
952        if (sport == TELNET_PORT || dport == TELNET_PORT) {
953                if (!qflag && vflag)
954                        telnet_print(bp, length);
955        } else if (sport == BGP_PORT || dport == BGP_PORT)
956                bgp_print(bp, length);
957        else if (sport == PPTP_PORT || dport == PPTP_PORT)
958                pptp_print(bp);
959#ifdef TCPDUMP_DO_SMB
960        else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT)
961                nbt_tcp_print(bp, length);
962	else if (sport == SMB_PORT || dport == SMB_PORT)
963		smb_tcp_print(bp, length);
964#endif
965        else if (sport == BEEP_PORT || dport == BEEP_PORT)
966                beep_print(bp, length);
967        else if (length > 2 &&
968                 (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT ||
969                  sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) {
970                /*
971                 * TCP DNS query has 2byte length at the head.
972                 * XXX packet could be unaligned, it can go strange
973                 */
974                ns_print(bp + 2, length - 2, 0);
975        } else if (sport == MSDP_PORT || dport == MSDP_PORT) {
976                msdp_print(bp, length);
977        } else if (sport == RPKI_RTR_PORT || dport == RPKI_RTR_PORT) {
978                rpki_rtr_print(bp, length);
979        }
980        else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) {
981                ldp_print(bp, length);
982        }
983
984        return;
985 bad:
986        fputs("[bad opt]", stdout);
987        if (ch != '\0')
988                putchar('>');
989        return;
990 trunc:
991        fputs("[|tcp]", stdout);
992        if (ch != '\0')
993                putchar('>');
994}
995
996/*
997 * RFC1122 says the following on data in RST segments:
998 *
999 *         4.2.2.12  RST Segment: RFC-793 Section 3.4
1000 *
1001 *            A TCP SHOULD allow a received RST segment to include data.
1002 *
1003 *            DISCUSSION
1004 *                 It has been suggested that a RST segment could contain
1005 *                 ASCII text that encoded and explained the cause of the
1006 *                 RST.  No standard has yet been established for such
1007 *                 data.
1008 *
1009 */
1010
1011static void
1012print_tcp_rst_data(register const u_char *sp, u_int length)
1013{
1014        int c;
1015
1016        if (TTEST2(*sp, length))
1017                printf(" [RST");
1018        else
1019                printf(" [!RST");
1020        if (length > MAX_RST_DATA_LEN) {
1021                length = MAX_RST_DATA_LEN;	/* can use -X for longer */
1022                putchar('+');			/* indicate we truncate */
1023        }
1024        putchar(' ');
1025        while (length-- && sp <= snapend) {
1026                c = *sp++;
1027                safeputchar(c);
1028        }
1029        putchar(']');
1030}
1031
1032#ifdef HAVE_LIBCRYPTO
1033static int
1034tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp,
1035                     const u_char *data, int length, const u_char *rcvsig)
1036{
1037        struct tcphdr tp1;
1038        u_char sig[TCP_SIGLEN];
1039        char zero_proto = 0;
1040        CC_MD5_CTX ctx;
1041        u_int16_t savecsum, tlen;
1042#ifdef INET6
1043        struct ip6_hdr *ip6;
1044        u_int32_t len32;
1045        u_int8_t nxt;
1046#endif
1047
1048	if (data + length > snapend) {
1049		printf("snaplen too short, ");
1050		return (CANT_CHECK_SIGNATURE);
1051	}
1052
1053        tp1 = *tp;
1054
1055        if (sigsecret == NULL) {
1056		printf("shared secret not supplied with -M, ");
1057                return (CANT_CHECK_SIGNATURE);
1058        }
1059
1060        CC_MD5_Init(&ctx);
1061        /*
1062         * Step 1: Update MD5 hash with IP pseudo-header.
1063         */
1064        if (IP_V(ip) == 4) {
1065                CC_MD5_Update(&ctx, (char *)&ip->ip_src, sizeof(ip->ip_src));
1066                CC_MD5_Update(&ctx, (char *)&ip->ip_dst, sizeof(ip->ip_dst));
1067                CC_MD5_Update(&ctx, (char *)&zero_proto, sizeof(zero_proto));
1068                CC_MD5_Update(&ctx, (char *)&ip->ip_p, sizeof(ip->ip_p));
1069                tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4;
1070                tlen = htons(tlen);
1071                CC_MD5_Update(&ctx, (char *)&tlen, sizeof(tlen));
1072#ifdef INET6
1073        } else if (IP_V(ip) == 6) {
1074                ip6 = (struct ip6_hdr *)ip;
1075                CC_MD5_Update(&ctx, (char *)&ip6->ip6_src, sizeof(ip6->ip6_src));
1076                CC_MD5_Update(&ctx, (char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst));
1077                len32 = htonl(EXTRACT_16BITS(&ip6->ip6_plen));
1078                CC_MD5_Update(&ctx, (char *)&len32, sizeof(len32));
1079                nxt = 0;
1080                CC_MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
1081                CC_MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
1082                CC_MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
1083                nxt = IPPROTO_TCP;
1084                CC_MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
1085#endif
1086        } else {
1087#ifdef INET6
1088		printf("IP version not 4 or 6, ");
1089#else
1090		printf("IP version not 4, ");
1091#endif
1092                return (CANT_CHECK_SIGNATURE);
1093        }
1094
1095        /*
1096         * Step 2: Update MD5 hash with TCP header, excluding options.
1097         * The TCP checksum must be set to zero.
1098         */
1099        savecsum = tp1.th_sum;
1100        tp1.th_sum = 0;
1101        CC_MD5_Update(&ctx, (char *)&tp1, sizeof(struct tcphdr));
1102        tp1.th_sum = savecsum;
1103        /*
1104         * Step 3: Update MD5 hash with TCP segment data, if present.
1105         */
1106        if (length > 0)
1107                CC_MD5_Update(&ctx, data, length);
1108        /*
1109         * Step 4: Update MD5 hash with shared secret.
1110         */
1111        CC_MD5_Update(&ctx, sigsecret, strlen(sigsecret));
1112        CC_MD5_Final(sig, &ctx);
1113
1114        if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0)
1115                return (SIGNATURE_VALID);
1116        else
1117                return (SIGNATURE_INVALID);
1118}
1119#endif /* HAVE_LIBCRYPTO */
1120
1121/*
1122 * Local Variables:
1123 * c-style: whitesmith
1124 * c-basic-offset: 8
1125 * End:
1126 */
1127