1) Add the sysctl(9) manual page from FreeBSD with the following
[dragonfly.git] / contrib / tcpdump-3.8.3 / print-tcp.c
1 /*
2  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21
22 #ifndef lint
23 static const char rcsid[] _U_ =
24     "@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.107.2.3 2003/11/19 00:17:02 guy Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <tcpdump-stdinc.h>
32
33 #include <rpc/rpc.h>
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "interface.h"
40 #include "addrtoname.h"
41 #include "extract.h"
42
43 #include "tcp.h"
44
45 #include "ip.h"
46 #ifdef INET6
47 #include "ip6.h"
48 #endif
49 #include "ipproto.h"
50
51 #include "nameser.h"
52
53 static void print_tcp_rst_data(register const u_char *sp, u_int length);
54
55 #define MAX_RST_DATA_LEN        30
56
57
58 struct tha {
59 #ifndef INET6
60         struct in_addr src;
61         struct in_addr dst;
62 #else
63         struct in6_addr src;
64         struct in6_addr dst;
65 #endif /*INET6*/
66         u_int port;
67 };
68
69 struct tcp_seq_hash {
70         struct tcp_seq_hash *nxt;
71         struct tha addr;
72         tcp_seq seq;
73         tcp_seq ack;
74 };
75
76 #define TSEQ_HASHSIZE 919
77
78 /* These tcp optinos do not have the size octet */
79 #define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP)
80
81 static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
82
83
84 #ifndef TELNET_PORT
85 #define TELNET_PORT     23
86 #endif
87 #ifndef BGP_PORT
88 #define BGP_PORT        179
89 #endif
90 #define NETBIOS_SSN_PORT 139
91 #ifndef PPTP_PORT
92 #define PPTP_PORT       1723
93 #endif
94 #define BEEP_PORT        10288
95 #ifndef NFS_PORT
96 #define NFS_PORT        2049
97 #endif
98 #define MSDP_PORT       639
99 #define LDP_PORT        646
100
101 static int tcp_cksum(register const struct ip *ip,
102                      register const struct tcphdr *tp,
103                      register u_int len)
104 {
105         union phu {
106                 struct phdr {
107                         u_int32_t src;
108                         u_int32_t dst;
109                         u_char mbz;
110                         u_char proto;
111                         u_int16_t len;
112                 } ph;
113                 u_int16_t pa[6];
114         } phu;
115         const u_int16_t *sp;
116
117         /* pseudo-header.. */
118         phu.ph.len = htons((u_int16_t)len);
119         phu.ph.mbz = 0;
120         phu.ph.proto = IPPROTO_TCP;
121         memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
122         if (IP_HL(ip) == 5)
123                 memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
124         else
125                 phu.ph.dst = ip_finddst(ip);
126
127         sp = &phu.pa[0];
128         return in_cksum((u_short *)tp, len,
129                         sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);
130 }
131
132 #ifdef INET6
133 static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp,
134         u_int len)
135 {
136         size_t i;
137         register const u_int16_t *sp;
138         u_int32_t sum;
139         union {
140                 struct {
141                         struct in6_addr ph_src;
142                         struct in6_addr ph_dst;
143                         u_int32_t       ph_len;
144                         u_int8_t        ph_zero[3];
145                         u_int8_t        ph_nxt;
146                 } ph;
147                 u_int16_t pa[20];
148         } phu;
149
150         /* pseudo-header */
151         memset(&phu, 0, sizeof(phu));
152         phu.ph.ph_src = ip6->ip6_src;
153         phu.ph.ph_dst = ip6->ip6_dst;
154         phu.ph.ph_len = htonl(len);
155         phu.ph.ph_nxt = IPPROTO_TCP;
156
157         sum = 0;
158         for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
159                 sum += phu.pa[i];
160
161         sp = (const u_int16_t *)tp;
162
163         for (i = 0; i < (len & ~1); i += 2)
164                 sum += *sp++;
165
166         if (len & 1)
167                 sum += htons((*(const u_int8_t *)sp) << 8);
168
169         while (sum > 0xffff)
170                 sum = (sum & 0xffff) + (sum >> 16);
171         sum = ~sum & 0xffff;
172
173         return (sum);
174 }
175 #endif
176
177 void
178 tcp_print(register const u_char *bp, register u_int length,
179           register const u_char *bp2, int fragmented)
180 {
181         register const struct tcphdr *tp;
182         register const struct ip *ip;
183         register u_char flags;
184         register u_int hlen;
185         register char ch;
186         u_int16_t sport, dport, win, urp;
187         u_int32_t seq, ack, thseq, thack;
188         int threv;
189 #ifdef INET6
190         register const struct ip6_hdr *ip6;
191 #endif
192
193         tp = (struct tcphdr *)bp;
194         ip = (struct ip *)bp2;
195 #ifdef INET6
196         if (IP_V(ip) == 6)
197                 ip6 = (struct ip6_hdr *)bp2;
198         else
199                 ip6 = NULL;
200 #endif /*INET6*/
201         ch = '\0';
202         if (!TTEST(tp->th_dport)) {
203                 (void)printf("%s > %s: [|tcp]",
204                         ipaddr_string(&ip->ip_src),
205                         ipaddr_string(&ip->ip_dst));
206                 return;
207         }
208
209         sport = EXTRACT_16BITS(&tp->th_sport);
210         dport = EXTRACT_16BITS(&tp->th_dport);
211
212         hlen = TH_OFF(tp) * 4;
213
214         /*
215          * If data present and NFS port used, assume NFS.
216          * Pass offset of data plus 4 bytes for RPC TCP msg length
217          * to NFS print routines.
218          */
219         if (!qflag) {
220                 if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend &&
221                     dport == NFS_PORT) {
222                         nfsreq_print((u_char *)tp + hlen + 4, length - hlen,
223                                      (u_char *)ip);
224                         return;
225                 } else if ((u_char *)tp + 4 + sizeof(struct rpc_msg)
226                            <= snapend &&
227                            sport == NFS_PORT) {
228                         nfsreply_print((u_char *)tp + hlen + 4, length - hlen,
229                                        (u_char *)ip);
230                         return;
231                 }
232         }
233 #ifdef INET6
234         if (ip6) {
235                 if (ip6->ip6_nxt == IPPROTO_TCP) {
236                         (void)printf("%s.%s > %s.%s: ",
237                                 ip6addr_string(&ip6->ip6_src),
238                                 tcpport_string(sport),
239                                 ip6addr_string(&ip6->ip6_dst),
240                                 tcpport_string(dport));
241                 } else {
242                         (void)printf("%s > %s: ",
243                                 tcpport_string(sport), tcpport_string(dport));
244                 }
245         } else
246 #endif /*INET6*/
247         {
248                 if (ip->ip_p == IPPROTO_TCP) {
249                         (void)printf("%s.%s > %s.%s: ",
250                                 ipaddr_string(&ip->ip_src),
251                                 tcpport_string(sport),
252                                 ipaddr_string(&ip->ip_dst),
253                                 tcpport_string(dport));
254                 } else {
255                         (void)printf("%s > %s: ",
256                                 tcpport_string(sport), tcpport_string(dport));
257                 }
258         }
259
260         TCHECK(*tp);
261
262         seq = EXTRACT_32BITS(&tp->th_seq);
263         ack = EXTRACT_32BITS(&tp->th_ack);
264         win = EXTRACT_16BITS(&tp->th_win);
265         urp = EXTRACT_16BITS(&tp->th_urp);
266
267         if (qflag) {
268                 (void)printf("tcp %d", length - TH_OFF(tp) * 4);
269                 return;
270         }
271         if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH|
272                                       TH_ECNECHO|TH_CWR)) {
273                 if (flags & TH_SYN)
274                         putchar('S');
275                 if (flags & TH_FIN)
276                         putchar('F');
277                 if (flags & TH_RST)
278                         putchar('R');
279                 if (flags & TH_PUSH)
280                         putchar('P');
281                 if (flags & TH_CWR)
282                         putchar('W');   /* congestion _W_indow reduced (ECN) */
283                 if (flags & TH_ECNECHO)
284                         putchar('E');   /* ecn _E_cho sent (ECN) */
285         } else
286                 putchar('.');
287
288         if (!Sflag && (flags & TH_ACK)) {
289                 register struct tcp_seq_hash *th;
290                 const void *src, *dst;
291                 register int rev;
292                 struct tha tha;
293                 /*
294                  * Find (or record) the initial sequence numbers for
295                  * this conversation.  (we pick an arbitrary
296                  * collating order so there's only one entry for
297                  * both directions).
298                  */
299 #ifdef INET6
300                 memset(&tha, 0, sizeof(tha));
301                 rev = 0;
302                 if (ip6) {
303                         src = &ip6->ip6_src;
304                         dst = &ip6->ip6_dst;
305                         if (sport > dport)
306                                 rev = 1;
307                         else if (sport == dport) {
308                                 if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0)
309                                         rev = 1;
310                         }
311                         if (rev) {
312                                 memcpy(&tha.src, dst, sizeof ip6->ip6_dst);
313                                 memcpy(&tha.dst, src, sizeof ip6->ip6_src);
314                                 tha.port = dport << 16 | sport;
315                         } else {
316                                 memcpy(&tha.dst, dst, sizeof ip6->ip6_dst);
317                                 memcpy(&tha.src, src, sizeof ip6->ip6_src);
318                                 tha.port = sport << 16 | dport;
319                         }
320                 } else {
321                         src = &ip->ip_src;
322                         dst = &ip->ip_dst;
323                         if (sport > dport)
324                                 rev = 1;
325                         else if (sport == dport) {
326                                 if (memcmp(src, dst, sizeof ip->ip_dst) > 0)
327                                         rev = 1;
328                         }
329                         if (rev) {
330                                 memcpy(&tha.src, dst, sizeof ip->ip_dst);
331                                 memcpy(&tha.dst, src, sizeof ip->ip_src);
332                                 tha.port = dport << 16 | sport;
333                         } else {
334                                 memcpy(&tha.dst, dst, sizeof ip->ip_dst);
335                                 memcpy(&tha.src, src, sizeof ip->ip_src);
336                                 tha.port = sport << 16 | dport;
337                         }
338                 }
339 #else
340                 rev = 0;
341                 src = &ip->ip_src;
342                 dst = &ip->ip_dst;
343                 if (sport > dport)
344                         rev = 1;
345                 else if (sport == dport) {
346                         if (memcmp(src, dst, sizeof ip->ip_dst) > 0)
347                                 rev = 1;
348                 }
349                 if (rev) {
350                         memcpy(&tha.src, dst, sizeof ip->ip_dst);
351                         memcpy(&tha.dst, src, sizeof ip->ip_src);
352                         tha.port = dport << 16 | sport;
353                 } else {
354                         memcpy(&tha.dst, dst, sizeof ip->ip_dst);
355                         memcpy(&tha.src, src, sizeof ip->ip_src);
356                         tha.port = sport << 16 | dport;
357                 }
358 #endif
359
360                 threv = rev;
361                 for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
362                      th->nxt; th = th->nxt)
363                         if (memcmp((char *)&tha, (char *)&th->addr,
364                                   sizeof(th->addr)) == 0)
365                                 break;
366
367                 if (!th->nxt || (flags & TH_SYN)) {
368                         /* didn't find it or new conversation */
369                         if (th->nxt == NULL) {
370                                 th->nxt = (struct tcp_seq_hash *)
371                                         calloc(1, sizeof(*th));
372                                 if (th->nxt == NULL)
373                                         error("tcp_print: calloc");
374                         }
375                         th->addr = tha;
376                         if (rev)
377                                 th->ack = seq, th->seq = ack - 1;
378                         else
379                                 th->seq = seq, th->ack = ack - 1;
380                 } else {
381                         if (rev)
382                                 seq -= th->ack, ack -= th->seq;
383                         else
384                                 seq -= th->seq, ack -= th->ack;
385                 }
386
387                 thseq = th->seq;
388                 thack = th->ack;
389         } else {
390                 /*fool gcc*/
391                 thseq = thack = threv = 0;
392         }
393         if (hlen > length) {
394                 (void)printf(" [bad hdr length]");
395                 return;
396         }
397
398         if (IP_V(ip) == 4 && vflag && !fragmented) {
399                 u_int16_t sum, tcp_sum;
400                 if (TTEST2(tp->th_sport, length)) {
401                         sum = tcp_cksum(ip, tp, length);
402                         if (sum != 0) {
403                                 tcp_sum = EXTRACT_16BITS(&tp->th_sum);
404                                 (void)printf(" [bad tcp cksum %x (->%x)!]",
405                                     tcp_sum, in_cksum_shouldbe(tcp_sum, sum));
406                         } else
407                                 (void)printf(" [tcp sum ok]");
408                 }
409         }
410 #ifdef INET6
411         if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !fragmented) {
412                 int sum;
413                 if (TTEST2(tp->th_sport, length)) {
414                         sum = tcp6_cksum(ip6, tp, length);
415                         if (sum != 0)
416                                 (void)printf(" [bad tcp cksum %x!]", sum);
417                         else
418                                 (void)printf(" [tcp sum ok]");
419                 }
420         }
421 #endif
422
423         length -= hlen;
424         if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST))
425                 (void)printf(" %u:%u(%u)", seq, seq + length, length);
426         if (flags & TH_ACK)
427                 (void)printf(" ack %u", ack);
428
429         (void)printf(" win %d", win);
430
431         if (flags & TH_URG)
432                 (void)printf(" urg %d", urp);
433         /*
434          * Handle any options.
435          */
436         if (hlen > sizeof(*tp)) {
437                 register const u_char *cp;
438                 register u_int i, opt, datalen;
439                 register u_int len;
440
441                 hlen -= sizeof(*tp);
442                 cp = (const u_char *)tp + sizeof(*tp);
443                 putchar(' ');
444                 ch = '<';
445                 while (hlen > 0) {
446                         putchar(ch);
447                         TCHECK(*cp);
448                         opt = *cp++;
449                         if (ZEROLENOPT(opt))
450                                 len = 1;
451                         else {
452                                 TCHECK(*cp);
453                                 len = *cp++;    /* total including type, len */
454                                 if (len < 2 || len > hlen)
455                                         goto bad;
456                                 --hlen;         /* account for length byte */
457                         }
458                         --hlen;                 /* account for type byte */
459                         datalen = 0;
460
461 /* Bail if "l" bytes of data are not left or were not captured  */
462 #define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); }
463
464                         switch (opt) {
465
466                         case TCPOPT_MAXSEG:
467                                 (void)printf("mss");
468                                 datalen = 2;
469                                 LENCHECK(datalen);
470                                 (void)printf(" %u", EXTRACT_16BITS(cp));
471
472                                 break;
473
474                         case TCPOPT_EOL:
475                                 (void)printf("eol");
476                                 break;
477
478                         case TCPOPT_NOP:
479                                 (void)printf("nop");
480                                 break;
481
482                         case TCPOPT_WSCALE:
483                                 (void)printf("wscale");
484                                 datalen = 1;
485                                 LENCHECK(datalen);
486                                 (void)printf(" %u", *cp);
487                                 break;
488
489                         case TCPOPT_SACKOK:
490                                 (void)printf("sackOK");
491                                 break;
492
493                         case TCPOPT_SACK:
494                                 (void)printf("sack");
495                                 datalen = len - 2;
496                                 if (datalen % 8 != 0) {
497                                         (void)printf(" malformed sack ");
498                                 } else {
499                                         u_int32_t s, e;
500
501                                         (void)printf(" sack %d ", datalen / 8);
502                                         for (i = 0; i < datalen; i += 8) {
503                                                 LENCHECK(i + 4);
504                                                 s = EXTRACT_32BITS(cp + i);
505                                                 LENCHECK(i + 8);
506                                                 e = EXTRACT_32BITS(cp + i + 4);
507                                                 if (threv) {
508                                                         s -= thseq;
509                                                         e -= thseq;
510                                                 } else {
511                                                         s -= thack;
512                                                         e -= thack;
513                                                 }
514                                                 (void)printf("{%u:%u}", s, e);
515                                         }
516                                         (void)printf(" ");
517                                 }
518                                 break;
519
520                         case TCPOPT_ECHO:
521                                 (void)printf("echo");
522                                 datalen = 4;
523                                 LENCHECK(datalen);
524                                 (void)printf(" %u", EXTRACT_32BITS(cp));
525                                 break;
526
527                         case TCPOPT_ECHOREPLY:
528                                 (void)printf("echoreply");
529                                 datalen = 4;
530                                 LENCHECK(datalen);
531                                 (void)printf(" %u", EXTRACT_32BITS(cp));
532                                 break;
533
534                         case TCPOPT_TIMESTAMP:
535                                 (void)printf("timestamp");
536                                 datalen = 8;
537                                 LENCHECK(4);
538                                 (void)printf(" %u", EXTRACT_32BITS(cp));
539                                 LENCHECK(datalen);
540                                 (void)printf(" %u", EXTRACT_32BITS(cp + 4));
541                                 break;
542
543                         case TCPOPT_CC:
544                                 (void)printf("cc");
545                                 datalen = 4;
546                                 LENCHECK(datalen);
547                                 (void)printf(" %u", EXTRACT_32BITS(cp));
548                                 break;
549
550                         case TCPOPT_CCNEW:
551                                 (void)printf("ccnew");
552                                 datalen = 4;
553                                 LENCHECK(datalen);
554                                 (void)printf(" %u", EXTRACT_32BITS(cp));
555                                 break;
556
557                         case TCPOPT_CCECHO:
558                                 (void)printf("ccecho");
559                                 datalen = 4;
560                                 LENCHECK(datalen);
561                                 (void)printf(" %u", EXTRACT_32BITS(cp));
562                                 break;
563
564                         default:
565                                 (void)printf("opt-%u:", opt);
566                                 datalen = len - 2;
567                                 for (i = 0; i < datalen; ++i) {
568                                         LENCHECK(i);
569                                         (void)printf("%02x", cp[i]);
570                                 }
571                                 break;
572                         }
573
574                         /* Account for data printed */
575                         cp += datalen;
576                         hlen -= datalen;
577
578                         /* Check specification against observed length */
579                         ++datalen;                      /* option octet */
580                         if (!ZEROLENOPT(opt))
581                                 ++datalen;              /* size octet */
582                         if (datalen != len)
583                                 (void)printf("[len %d]", len);
584                         ch = ',';
585                         if (opt == TCPOPT_EOL)
586                                 break;
587                 }
588                 putchar('>');
589         }
590
591         if (length <= 0)
592                 return;
593
594         /*
595          * Decode payload if necessary.
596          */
597         bp += TH_OFF(tp) * 4;
598         if (flags & TH_RST) {
599                 if (vflag)
600                         print_tcp_rst_data(bp, length);
601         } else {
602                 if (sport == TELNET_PORT || dport == TELNET_PORT) {
603                         if (!qflag && vflag)
604                                 telnet_print(bp, length);
605                 } else if (sport == BGP_PORT || dport == BGP_PORT)
606                         bgp_print(bp, length);
607                 else if (sport == PPTP_PORT || dport == PPTP_PORT)
608                         pptp_print(bp);
609 #ifdef TCPDUMP_DO_SMB
610                 else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT)
611                         nbt_tcp_print(bp, length);
612 #endif
613                 else if (sport == BEEP_PORT || dport == BEEP_PORT)
614                         beep_print(bp, length);
615                 else if (length > 2 &&
616                     (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT ||
617                      sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) {
618                         /*
619                          * TCP DNS query has 2byte length at the head.
620                          * XXX packet could be unaligned, it can go strange
621                          */
622                         ns_print(bp + 2, length - 2, 0);
623                 } else if (sport == MSDP_PORT || dport == MSDP_PORT) {
624                         msdp_print(bp, length);
625                 }
626                 else if (sport == LDP_PORT || dport == LDP_PORT)
627                         printf(": LDP, length: %u", length);
628         }
629         return;
630 bad:
631         fputs("[bad opt]", stdout);
632         if (ch != '\0')
633                 putchar('>');
634         return;
635 trunc:
636         fputs("[|tcp]", stdout);
637         if (ch != '\0')
638                 putchar('>');
639 }
640
641 /*
642  * RFC1122 says the following on data in RST segments:
643  *
644  *         4.2.2.12  RST Segment: RFC-793 Section 3.4
645  *
646  *            A TCP SHOULD allow a received RST segment to include data.
647  *
648  *            DISCUSSION
649  *                 It has been suggested that a RST segment could contain
650  *                 ASCII text that encoded and explained the cause of the
651  *                 RST.  No standard has yet been established for such
652  *                 data.
653  *
654  */
655
656 static void
657 print_tcp_rst_data(register const u_char *sp, u_int length)
658 {
659         int c;
660
661         if (TTEST2(*sp, length))
662                 printf(" [RST");
663         else
664                 printf(" [!RST");
665         if (length > MAX_RST_DATA_LEN) {
666                 length = MAX_RST_DATA_LEN;      /* can use -X for longer */
667                 putchar('+');                   /* indicate we truncate */
668         }
669         putchar(' ');
670         while (length-- && sp <= snapend) {
671                 c = *sp++;
672                 safeputchar(c);
673         }
674         putchar(']');
675 }