source: rtems-libbsd/freebsd/contrib/tcpdump/print-tcp.c @ 8440506

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 8440506 was 8440506, checked in by Chris Johns <chrisj@…>, on 06/15/15 at 07:42:23

Add tcpdump and libpcap.

  • Update the file builder generator to handle generator specific cflags and includes. The tcpdump and libpcap have localised headers and need specific headers paths to see them. There are also module specific flags and these need to be passed to the lex and yacc generators.
  • Add the tcpdump support.
  • Property mode set to 100644
File size: 29.3 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*      $NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky Exp $     */
4
5/*
6 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
7 *      The Regents of the University of California.  All rights reserved.
8 *
9 * Copyright (c) 1999-2004 The tcpdump.org project
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that: (1) source code distributions
13 * retain the above copyright notice and this paragraph in its entirety, (2)
14 * distributions including binary code include the above copyright notice and
15 * this paragraph in its entirety in the documentation or other materials
16 * provided with the distribution, and (3) all advertising materials mentioning
17 * features or use of this software display the following acknowledgement:
18 * ``This product includes software developed by the University of California,
19 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
20 * the University nor the names of its contributors may be used to endorse
21 * or promote products derived from this software without specific prior
22 * written permission.
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26 */
27
28#ifndef lint
29static const char rcsid[] _U_ =
30"@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.135 2008-11-09 23:35:03 mcr Exp $ (LBL)";
31#else
32__RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $");
33#endif
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include <tcpdump-stdinc.h>
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44
45#include "interface.h"
46#include "addrtoname.h"
47#include "extract.h"
48
49#include "tcp.h"
50
51#include "ip.h"
52#ifdef INET6
53#include "ip6.h"
54#endif
55#include "ipproto.h"
56#include "rpc_auth.h"
57#include "rpc_msg.h"
58
59#include "nameser.h"
60
61#ifdef HAVE_LIBCRYPTO
62#include <openssl/md5.h>
63#include <signature.h>
64
65static int tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp,
66                                const u_char *data, int length, const u_char *rcvsig);
67#endif
68
69static void print_tcp_rst_data(register const u_char *sp, u_int length);
70
71#define MAX_RST_DATA_LEN        30
72
73
74struct tha {
75#ifndef INET6
76        struct in_addr src;
77        struct in_addr dst;
78#else
79        struct in6_addr src;
80        struct in6_addr dst;
81#endif /*INET6*/
82        u_int port;
83};
84
85struct tcp_seq_hash {
86        struct tcp_seq_hash *nxt;
87        struct tha addr;
88        tcp_seq seq;
89        tcp_seq ack;
90};
91
92#define TSEQ_HASHSIZE 919
93
94/* These tcp optinos do not have the size octet */
95#define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP)
96
97static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
98
99struct tok tcp_flag_values[] = {
100        { TH_FIN, "F" },
101        { TH_SYN, "S" },
102        { TH_RST, "R" },
103        { TH_PUSH, "P" },
104        { TH_ACK, "." },
105        { TH_URG, "U" },
106        { TH_ECNECHO, "E" },
107        { TH_CWR, "W" },
108        { 0, NULL }
109};
110
111struct tok tcp_option_values[] = {
112        { TCPOPT_EOL, "eol" },
113        { TCPOPT_NOP, "nop" },
114        { TCPOPT_MAXSEG, "mss" },
115        { TCPOPT_WSCALE, "wscale" },
116        { TCPOPT_SACKOK, "sackOK" },
117        { TCPOPT_SACK, "sack" },
118        { TCPOPT_ECHO, "echo" },
119        { TCPOPT_ECHOREPLY, "echoreply" },
120        { TCPOPT_TIMESTAMP, "TS" },
121        { TCPOPT_CC, "cc" },
122        { TCPOPT_CCNEW, "ccnew" },
123        { TCPOPT_CCECHO, "" },
124        { TCPOPT_SIGNATURE, "md5" },
125        { TCPOPT_AUTH, "enhanced auth" },
126        { TCPOPT_UTO, "uto" },
127        { 0, NULL }
128};
129
130static int tcp_cksum(register const struct ip *ip,
131                     register const struct tcphdr *tp,
132                     register u_int len)
133{
134        return (nextproto4_cksum(ip, (const u_int8_t *)tp, len,
135            IPPROTO_TCP));
136}
137
138void
139tcp_print(register const u_char *bp, register u_int length,
140          register const u_char *bp2, int fragmented)
141{
142        register const struct tcphdr *tp;
143        register const struct ip *ip;
144        register u_char flags;
145        register u_int hlen;
146        register char ch;
147        u_int16_t sport, dport, win, urp;
148        u_int32_t seq, ack, thseq, thack;
149        u_int utoval;
150        int threv;
151#ifdef INET6
152        register const struct ip6_hdr *ip6;
153#endif
154
155        tp = (struct tcphdr *)bp;
156        ip = (struct ip *)bp2;
157#ifdef INET6
158        if (IP_V(ip) == 6)
159                ip6 = (struct ip6_hdr *)bp2;
160        else
161                ip6 = NULL;
162#endif /*INET6*/
163        ch = '\0';
164        if (!TTEST(tp->th_dport)) {
165                (void)printf("%s > %s: [|tcp]",
166                             ipaddr_string(&ip->ip_src),
167                             ipaddr_string(&ip->ip_dst));
168                return;
169        }
170
171        sport = EXTRACT_16BITS(&tp->th_sport);
172        dport = EXTRACT_16BITS(&tp->th_dport);
173
174        hlen = TH_OFF(tp) * 4;
175
176        /*
177         * If data present, header length valid, and NFS port used,
178         * assume NFS.
179         * Pass offset of data plus 4 bytes for RPC TCP msg length
180         * to NFS print routines.
181         */
182        if (!qflag && hlen >= sizeof(*tp) && hlen <= length &&
183            (length - hlen) >= 4) {
184                u_char *fraglenp;
185                u_int32_t fraglen;
186                register struct sunrpc_msg *rp;
187                enum sunrpc_msg_type direction;
188
189                fraglenp = (u_char *)tp + hlen;
190                if (TTEST2(*fraglenp, 4)) {
191                        fraglen = EXTRACT_32BITS(fraglenp) & 0x7FFFFFFF;
192                        if (fraglen > (length - hlen) - 4)
193                                fraglen = (length - hlen) - 4;
194                        rp = (struct sunrpc_msg *)(fraglenp + 4);
195                        if (TTEST(rp->rm_direction)) {
196                                direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction);
197                                if (dport == NFS_PORT &&
198                                    direction == SUNRPC_CALL) {
199                                        nfsreq_print((u_char *)rp, fraglen,
200                                            (u_char *)ip);
201                                        return;
202                                }
203                                if (sport == NFS_PORT &&
204                                    direction == SUNRPC_REPLY) {
205                                        nfsreply_print((u_char *)rp, fraglen,
206                                            (u_char *)ip);
207                                        return;
208                                }
209                        }
210                }
211        }
212#ifdef INET6
213        if (ip6) {
214                if (ip6->ip6_nxt == IPPROTO_TCP) {
215                        (void)printf("%s.%s > %s.%s: ",
216                                     ip6addr_string(&ip6->ip6_src),
217                                     tcpport_string(sport),
218                                     ip6addr_string(&ip6->ip6_dst),
219                                     tcpport_string(dport));
220                } else {
221                        (void)printf("%s > %s: ",
222                                     tcpport_string(sport), tcpport_string(dport));
223                }
224        } else
225#endif /*INET6*/
226        {
227                if (ip->ip_p == IPPROTO_TCP) {
228                        (void)printf("%s.%s > %s.%s: ",
229                                     ipaddr_string(&ip->ip_src),
230                                     tcpport_string(sport),
231                                     ipaddr_string(&ip->ip_dst),
232                                     tcpport_string(dport));
233                } else {
234                        (void)printf("%s > %s: ",
235                                     tcpport_string(sport), tcpport_string(dport));
236                }
237        }
238
239        if (hlen < sizeof(*tp)) {
240                (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]",
241                             length - hlen, hlen, (unsigned long)sizeof(*tp));
242                return;
243        }
244
245        TCHECK(*tp);
246
247        seq = EXTRACT_32BITS(&tp->th_seq);
248        ack = EXTRACT_32BITS(&tp->th_ack);
249        win = EXTRACT_16BITS(&tp->th_win);
250        urp = EXTRACT_16BITS(&tp->th_urp);
251
252        if (qflag) {
253                (void)printf("tcp %d", length - hlen);
254                if (hlen > length) {
255                        (void)printf(" [bad hdr length %u - too long, > %u]",
256                                     hlen, length);
257                }
258                return;
259        }
260
261        flags = tp->th_flags;
262        printf("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags));
263
264        if (!Sflag && (flags & TH_ACK)) {
265                register struct tcp_seq_hash *th;
266                const void *src, *dst;
267                register int rev;
268                struct tha tha;
269                /*
270                 * Find (or record) the initial sequence numbers for
271                 * this conversation.  (we pick an arbitrary
272                 * collating order so there's only one entry for
273                 * both directions).
274                 */
275#ifdef INET6
276                rev = 0;
277                if (ip6) {
278                        src = &ip6->ip6_src;
279                        dst = &ip6->ip6_dst;
280                        if (sport > dport)
281                                rev = 1;
282                        else if (sport == dport) {
283                                if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0)
284                                        rev = 1;
285                        }
286                        if (rev) {
287                                memcpy(&tha.src, dst, sizeof ip6->ip6_dst);
288                                memcpy(&tha.dst, src, sizeof ip6->ip6_src);
289                                tha.port = dport << 16 | sport;
290                        } else {
291                                memcpy(&tha.dst, dst, sizeof ip6->ip6_dst);
292                                memcpy(&tha.src, src, sizeof ip6->ip6_src);
293                                tha.port = sport << 16 | dport;
294                        }
295                } else {
296                        /*
297                         * Zero out the tha structure; the src and dst
298                         * fields are big enough to hold an IPv6
299                         * address, but we only have IPv4 addresses
300                         * and thus must clear out the remaining 124
301                         * bits.
302                         *
303                         * XXX - should we just clear those bytes after
304                         * copying the IPv4 addresses, rather than
305                         * zeroing out the entire structure and then
306                         * overwriting some of the zeroes?
307                         *
308                         * XXX - this could fail if we see TCP packets
309                         * with an IPv6 address with the lower 124 bits
310                         * all zero and also see TCP packes with an
311                         * IPv4 address with the same 32 bits as the
312                         * upper 32 bits of the IPv6 address in question.
313                         * Can that happen?  Is it likely enough to be
314                         * an issue?
315                         */
316                        memset(&tha, 0, sizeof(tha));
317                        src = &ip->ip_src;
318                        dst = &ip->ip_dst;
319                        if (sport > dport)
320                                rev = 1;
321                        else if (sport == dport) {
322                                if (memcmp(src, dst, sizeof ip->ip_dst) > 0)
323                                        rev = 1;
324                        }
325                        if (rev) {
326                                memcpy(&tha.src, dst, sizeof ip->ip_dst);
327                                memcpy(&tha.dst, src, sizeof ip->ip_src);
328                                tha.port = dport << 16 | sport;
329                        } else {
330                                memcpy(&tha.dst, dst, sizeof ip->ip_dst);
331                                memcpy(&tha.src, src, sizeof ip->ip_src);
332                                tha.port = sport << 16 | dport;
333                        }
334                }
335#else
336                rev = 0;
337                src = &ip->ip_src;
338                dst = &ip->ip_dst;
339                if (sport > dport)
340                        rev = 1;
341                else if (sport == dport) {
342                        if (memcmp(src, dst, sizeof ip->ip_dst) > 0)
343                                rev = 1;
344                }
345                if (rev) {
346                        memcpy(&tha.src, dst, sizeof ip->ip_dst);
347                        memcpy(&tha.dst, src, sizeof ip->ip_src);
348                        tha.port = dport << 16 | sport;
349                } else {
350                        memcpy(&tha.dst, dst, sizeof ip->ip_dst);
351                        memcpy(&tha.src, src, sizeof ip->ip_src);
352                        tha.port = sport << 16 | dport;
353                }
354#endif
355
356                threv = rev;
357                for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
358                     th->nxt; th = th->nxt)
359                        if (memcmp((char *)&tha, (char *)&th->addr,
360                                   sizeof(th->addr)) == 0)
361                                break;
362
363                if (!th->nxt || (flags & TH_SYN)) {
364                        /* didn't find it or new conversation */
365                        if (th->nxt == NULL) {
366                                th->nxt = (struct tcp_seq_hash *)
367                                        calloc(1, sizeof(*th));
368                                if (th->nxt == NULL)
369                                        error("tcp_print: calloc");
370                        }
371                        th->addr = tha;
372                        if (rev)
373                                th->ack = seq, th->seq = ack - 1;
374                        else
375                                th->seq = seq, th->ack = ack - 1;
376                } else {
377                        if (rev)
378                                seq -= th->ack, ack -= th->seq;
379                        else
380                                seq -= th->seq, ack -= th->ack;
381                }
382
383                thseq = th->seq;
384                thack = th->ack;
385        } else {
386                /*fool gcc*/
387                thseq = thack = threv = 0;
388        }
389        if (hlen > length) {
390                (void)printf(" [bad hdr length %u - too long, > %u]",
391                             hlen, length);
392                return;
393        }
394
395        if (vflag && !Kflag && !fragmented) {
396                /* Check the checksum, if possible. */
397                u_int16_t sum, tcp_sum;
398
399                if (IP_V(ip) == 4) {
400                        if (TTEST2(tp->th_sport, length)) {
401                                sum = tcp_cksum(ip, tp, length);
402                                tcp_sum = EXTRACT_16BITS(&tp->th_sum);
403
404                                (void)printf(", cksum 0x%04x", tcp_sum);
405                                if (sum != 0)
406                                        (void)printf(" (incorrect -> 0x%04x)",
407                                            in_cksum_shouldbe(tcp_sum, sum));
408                                else
409                                        (void)printf(" (correct)");
410                        }
411                }
412#ifdef INET6
413                else if (IP_V(ip) == 6 && ip6->ip6_plen) {
414                        if (TTEST2(tp->th_sport, length)) {
415                                sum = nextproto6_cksum(ip6, (const u_int8_t *)tp, length, IPPROTO_TCP);
416                                tcp_sum = EXTRACT_16BITS(&tp->th_sum);
417
418                                (void)printf(", cksum 0x%04x", tcp_sum);
419                                if (sum != 0)
420                                        (void)printf(" (incorrect -> 0x%04x)",
421                                            in_cksum_shouldbe(tcp_sum, sum));
422                                else
423                                        (void)printf(" (correct)");
424
425                        }
426                }
427#endif
428        }
429
430        length -= hlen;
431        if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) {
432                (void)printf(", seq %u", seq);
433
434                if (length > 0) {
435                        (void)printf(":%u", seq + length);
436                }
437        }
438
439        if (flags & TH_ACK) {
440                (void)printf(", ack %u", ack);
441        }
442
443        (void)printf(", win %d", win);
444
445        if (flags & TH_URG)
446                (void)printf(", urg %d", urp);
447        /*
448         * Handle any options.
449         */
450        if (hlen > sizeof(*tp)) {
451                register const u_char *cp;
452                register u_int i, opt, datalen;
453                register u_int len;
454
455                hlen -= sizeof(*tp);
456                cp = (const u_char *)tp + sizeof(*tp);
457                printf(", options [");
458                while (hlen > 0) {
459                        if (ch != '\0')
460                                putchar(ch);
461                        TCHECK(*cp);
462                        opt = *cp++;
463                        if (ZEROLENOPT(opt))
464                                len = 1;
465                        else {
466                                TCHECK(*cp);
467                                len = *cp++;    /* total including type, len */
468                                if (len < 2 || len > hlen)
469                                        goto bad;
470                                --hlen;         /* account for length byte */
471                        }
472                        --hlen;                 /* account for type byte */
473                        datalen = 0;
474
475/* Bail if "l" bytes of data are not left or were not captured  */
476#define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); }
477
478
479                        printf("%s", tok2str(tcp_option_values, "Unknown Option %u", opt));
480
481                        switch (opt) {
482
483                        case TCPOPT_MAXSEG:
484                                datalen = 2;
485                                LENCHECK(datalen);
486                                (void)printf(" %u", EXTRACT_16BITS(cp));
487                                break;
488
489                        case TCPOPT_WSCALE:
490                                datalen = 1;
491                                LENCHECK(datalen);
492                                (void)printf(" %u", *cp);
493                                break;
494
495                        case TCPOPT_SACK:
496                                datalen = len - 2;
497                                if (datalen % 8 != 0) {
498                                        (void)printf("malformed sack");
499                                } else {
500                                        u_int32_t s, e;
501
502                                        (void)printf(" %d ", datalen / 8);
503                                        for (i = 0; i < datalen; i += 8) {
504                                                LENCHECK(i + 4);
505                                                s = EXTRACT_32BITS(cp + i);
506                                                LENCHECK(i + 8);
507                                                e = EXTRACT_32BITS(cp + i + 4);
508                                                if (threv) {
509                                                        s -= thseq;
510                                                        e -= thseq;
511                                                } else {
512                                                        s -= thack;
513                                                        e -= thack;
514                                                }
515                                                (void)printf("{%u:%u}", s, e);
516                                        }
517                                }
518                                break;
519
520                        case TCPOPT_CC:
521                        case TCPOPT_CCNEW:
522                        case TCPOPT_CCECHO:
523                        case TCPOPT_ECHO:
524                        case TCPOPT_ECHOREPLY:
525
526                                /*
527                                 * those options share their semantics.
528                                 * fall through
529                                 */
530                                datalen = 4;
531                                LENCHECK(datalen);
532                                (void)printf(" %u", EXTRACT_32BITS(cp));
533                                break;
534
535                        case TCPOPT_TIMESTAMP:
536                                datalen = 8;
537                                LENCHECK(datalen);
538                                (void)printf(" val %u ecr %u",
539                                             EXTRACT_32BITS(cp),
540                                             EXTRACT_32BITS(cp + 4));
541                                break;
542
543                        case TCPOPT_SIGNATURE:
544                                datalen = TCP_SIGLEN;
545                                LENCHECK(datalen);
546#ifdef HAVE_LIBCRYPTO
547                                switch (tcp_verify_signature(ip, tp,
548                                                             bp + TH_OFF(tp) * 4, length, cp)) {
549
550                                case SIGNATURE_VALID:
551                                        (void)printf("valid");
552                                        break;
553
554                                case SIGNATURE_INVALID:
555                                        (void)printf("invalid");
556                                        break;
557
558                                case CANT_CHECK_SIGNATURE:
559                                        (void)printf("can't check - ");
560                                        for (i = 0; i < TCP_SIGLEN; ++i)
561                                                (void)printf("%02x", cp[i]);
562                                        break;
563                                }
564#else
565                                for (i = 0; i < TCP_SIGLEN; ++i)
566                                        (void)printf("%02x", cp[i]);
567#endif
568                                break;
569
570                        case TCPOPT_AUTH:
571                                (void)printf("keyid %d", *cp++);
572                                datalen = len - 3;
573                                for (i = 0; i < datalen; ++i) {
574                                        LENCHECK(i);
575                                        (void)printf("%02x", cp[i]);
576                                }
577                                break;
578
579
580                        case TCPOPT_EOL:
581                        case TCPOPT_NOP:
582                        case TCPOPT_SACKOK:
583                                /*
584                                 * Nothing interesting.
585                                 * fall through
586                                 */
587                                break;
588
589                        case TCPOPT_UTO:
590                                datalen = 2;
591                                LENCHECK(datalen);
592                                utoval = EXTRACT_16BITS(cp);
593                                (void)printf("0x%x", utoval);
594                                if (utoval & 0x0001)
595                                        utoval = (utoval >> 1) * 60;
596                                else
597                                        utoval >>= 1;
598                                (void)printf(" %u", utoval);
599                                break;
600
601                        default:
602                                datalen = len - 2;
603                                for (i = 0; i < datalen; ++i) {
604                                        LENCHECK(i);
605                                        (void)printf("%02x", cp[i]);
606                                }
607                                break;
608                        }
609
610                        /* Account for data printed */
611                        cp += datalen;
612                        hlen -= datalen;
613
614                        /* Check specification against observed length */
615                        ++datalen;                      /* option octet */
616                        if (!ZEROLENOPT(opt))
617                                ++datalen;              /* size octet */
618                        if (datalen != len)
619                                (void)printf("[len %d]", len);
620                        ch = ',';
621                        if (opt == TCPOPT_EOL)
622                                break;
623                }
624                putchar(']');
625        }
626
627        /*
628         * Print length field before crawling down the stack.
629         */
630        printf(", length %u", length);
631
632        if (length <= 0)
633                return;
634
635        /*
636         * Decode payload if necessary.
637         */
638        bp += TH_OFF(tp) * 4;
639        if ((flags & TH_RST) && vflag) {
640                print_tcp_rst_data(bp, length);
641                return;
642        }
643
644        if (packettype) {
645                switch (packettype) {
646                case PT_ZMTP1:
647                        zmtp1_print(bp, length);
648                        break;
649                }
650                return;
651        }
652
653        if (sport == TELNET_PORT || dport == TELNET_PORT) {
654                if (!qflag && vflag)
655                        telnet_print(bp, length);
656        } else if (sport == BGP_PORT || dport == BGP_PORT)
657                bgp_print(bp, length);
658        else if (sport == PPTP_PORT || dport == PPTP_PORT)
659                pptp_print(bp);
660#ifdef TCPDUMP_DO_SMB
661        else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT)
662                nbt_tcp_print(bp, length);
663        else if (sport == SMB_PORT || dport == SMB_PORT)
664                smb_tcp_print(bp, length);
665#endif
666        else if (sport == BEEP_PORT || dport == BEEP_PORT)
667                beep_print(bp, length);
668        else if (length > 2 &&
669                 (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT ||
670                  sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) {
671                /*
672                 * TCP DNS query has 2byte length at the head.
673                 * XXX packet could be unaligned, it can go strange
674                 */
675                ns_print(bp + 2, length - 2, 0);
676        } else if (sport == MSDP_PORT || dport == MSDP_PORT) {
677                msdp_print(bp, length);
678        } else if (sport == RPKI_RTR_PORT || dport == RPKI_RTR_PORT) {
679                rpki_rtr_print(bp, length);
680        }
681        else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) {
682                ldp_print(bp, length);
683        }
684
685        return;
686 bad:
687        fputs("[bad opt]", stdout);
688        if (ch != '\0')
689                putchar('>');
690        return;
691 trunc:
692        fputs("[|tcp]", stdout);
693        if (ch != '\0')
694                putchar('>');
695}
696
697/*
698 * RFC1122 says the following on data in RST segments:
699 *
700 *         4.2.2.12  RST Segment: RFC-793 Section 3.4
701 *
702 *            A TCP SHOULD allow a received RST segment to include data.
703 *
704 *            DISCUSSION
705 *                 It has been suggested that a RST segment could contain
706 *                 ASCII text that encoded and explained the cause of the
707 *                 RST.  No standard has yet been established for such
708 *                 data.
709 *
710 */
711
712static void
713print_tcp_rst_data(register const u_char *sp, u_int length)
714{
715        int c;
716
717        if (TTEST2(*sp, length))
718                printf(" [RST");
719        else
720                printf(" [!RST");
721        if (length > MAX_RST_DATA_LEN) {
722                length = MAX_RST_DATA_LEN;      /* can use -X for longer */
723                putchar('+');                   /* indicate we truncate */
724        }
725        putchar(' ');
726        while (length-- && sp <= snapend) {
727                c = *sp++;
728                safeputchar(c);
729        }
730        putchar(']');
731}
732
733#ifdef HAVE_LIBCRYPTO
734static int
735tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp,
736                     const u_char *data, int length, const u_char *rcvsig)
737{
738        struct tcphdr tp1;
739        u_char sig[TCP_SIGLEN];
740        char zero_proto = 0;
741        MD5_CTX ctx;
742        u_int16_t savecsum, tlen;
743#ifdef INET6
744        struct ip6_hdr *ip6;
745        u_int32_t len32;
746        u_int8_t nxt;
747#endif
748
749        if (data + length > snapend) {
750                printf("snaplen too short, ");
751                return (CANT_CHECK_SIGNATURE);
752        }
753
754        tp1 = *tp;
755
756        if (sigsecret == NULL) {
757                printf("shared secret not supplied with -M, ");
758                return (CANT_CHECK_SIGNATURE);
759        }
760
761        MD5_Init(&ctx);
762        /*
763         * Step 1: Update MD5 hash with IP pseudo-header.
764         */
765        if (IP_V(ip) == 4) {
766                MD5_Update(&ctx, (char *)&ip->ip_src, sizeof(ip->ip_src));
767                MD5_Update(&ctx, (char *)&ip->ip_dst, sizeof(ip->ip_dst));
768                MD5_Update(&ctx, (char *)&zero_proto, sizeof(zero_proto));
769                MD5_Update(&ctx, (char *)&ip->ip_p, sizeof(ip->ip_p));
770                tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4;
771                tlen = htons(tlen);
772                MD5_Update(&ctx, (char *)&tlen, sizeof(tlen));
773#ifdef INET6
774        } else if (IP_V(ip) == 6) {
775                ip6 = (struct ip6_hdr *)ip;
776                MD5_Update(&ctx, (char *)&ip6->ip6_src, sizeof(ip6->ip6_src));
777                MD5_Update(&ctx, (char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst));
778                len32 = htonl(EXTRACT_16BITS(&ip6->ip6_plen));
779                MD5_Update(&ctx, (char *)&len32, sizeof(len32));
780                nxt = 0;
781                MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
782                MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
783                MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
784                nxt = IPPROTO_TCP;
785                MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
786#endif
787        } else {
788#ifdef INET6
789                printf("IP version not 4 or 6, ");
790#else
791                printf("IP version not 4, ");
792#endif
793                return (CANT_CHECK_SIGNATURE);
794        }
795
796        /*
797         * Step 2: Update MD5 hash with TCP header, excluding options.
798         * The TCP checksum must be set to zero.
799         */
800        savecsum = tp1.th_sum;
801        tp1.th_sum = 0;
802        MD5_Update(&ctx, (char *)&tp1, sizeof(struct tcphdr));
803        tp1.th_sum = savecsum;
804        /*
805         * Step 3: Update MD5 hash with TCP segment data, if present.
806         */
807        if (length > 0)
808                MD5_Update(&ctx, data, length);
809        /*
810         * Step 4: Update MD5 hash with shared secret.
811         */
812        MD5_Update(&ctx, sigsecret, strlen(sigsecret));
813        MD5_Final(sig, &ctx);
814
815        if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0)
816                return (SIGNATURE_VALID);
817        else
818                return (SIGNATURE_INVALID);
819}
820#endif /* HAVE_LIBCRYPTO */
821
822/*
823 * Local Variables:
824 * c-style: whitesmith
825 * c-basic-offset: 8
826 * End:
827 */
Note: See TracBrowser for help on using the repository browser.