home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / tcpdumpb.zip / print-tcp.c < prev    next >
C/C++ Source or Header  |  1997-02-14  |  15KB  |  389 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
  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 char rcsid[] =
  24.     "@(#) $Header: print-tcp.c,v 1.46 96/07/23 14:17:27 leres Exp $ (LBL)";
  25. #endif
  26.  
  27. #include <sys/param.h>
  28. #include <sys/time.h>
  29.  
  30. #include <netinet/in.h>
  31. #include <netinet/in_systm.h>
  32. #include <netinet/ip.h>
  33. #ifndef __EMX__
  34. #include <netinet/ip_var.h>
  35. #endif
  36. #include <netinet/tcp.h>
  37. #ifndef __EMX__
  38. #include <netinet/tcpip.h>
  39. #endif
  40.  
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <unistd.h>
  45.  
  46. #include "interface.h"
  47. #include "addrtoname.h"
  48. #include "extract.h"
  49.  
  50. /* Compatibility */
  51. #ifndef TCPOPT_WSCALE
  52. #define TCPOPT_WSCALE           3       /* window scale factor (rfc1072) */
  53. #endif
  54. #ifndef TCPOPT_SACKOK
  55. #define TCPOPT_SACKOK           4       /* selective ack ok (rfc1072) */
  56. #endif
  57. #ifndef TCPOPT_SACK
  58. #define TCPOPT_SACK             5       /* selective ack (rfc1072) */
  59. #endif
  60. #ifndef TCPOPT_ECHO
  61. #define TCPOPT_ECHO             6       /* echo (rfc1072) */
  62. #endif
  63. #ifndef TCPOPT_ECHOREPLY
  64. #define TCPOPT_ECHOREPLY        7       /* echo (rfc1072) */
  65. #endif
  66. #ifndef TCPOPT_TIMESTAMP
  67. #define TCPOPT_TIMESTAMP        8       /* timestamps (rfc1323) */
  68. #endif
  69. #ifndef TCPOPT_CC
  70. #define TCPOPT_CC               11      /* T/TCP CC options (rfc1644) */
  71. #endif
  72. #ifndef TCPOPT_CCNEW
  73. #define TCPOPT_CCNEW            12      /* T/TCP CC options (rfc1644) */
  74. #endif
  75. #ifndef TCPOPT_CCECHO
  76. #define TCPOPT_CCECHO           13      /* T/TCP CC options (rfc1644) */
  77. #endif
  78.  
  79. struct tha {
  80.         struct in_addr src;
  81.         struct in_addr dst;
  82.         u_int port;
  83. };
  84.  
  85. struct 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.  
  97. static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
  98.  
  99.  
  100. #define NETBIOS_SSN_PORT 139
  101.  
  102. void
  103. tcp_print(register const u_char *bp, register u_int length,
  104.           register const u_char *bp2)
  105. {
  106.         register const struct tcphdr *tp;
  107.         register const struct ip *ip;
  108.         register u_char flags;
  109.         register u_int hlen;
  110.         register char ch;
  111.         u_short sport, dport, win, urp;
  112.         u_int32_t seq, ack;
  113.  
  114.         tp = (struct tcphdr *)bp;
  115.         ip = (struct ip *)bp2;
  116.         ch = '\0';
  117.         TCHECK(*tp);
  118.         if (length < sizeof(*tp)) {
  119.                 (void)printf("truncated-tcp %d", length);
  120.                 return;
  121.         }
  122.  
  123.         sport = ntohs(tp->th_sport);
  124.         dport = ntohs(tp->th_dport);
  125.         seq = ntohl(tp->th_seq);
  126.         ack = ntohl(tp->th_ack);
  127.         win = ntohs(tp->th_win);
  128.         urp = ntohs(tp->th_urp);
  129.  
  130.         (void)printf("%s.%s > %s.%s: ",
  131.                 ipaddr_string(&ip->ip_src), tcpport_string(sport),
  132.                 ipaddr_string(&ip->ip_dst), tcpport_string(dport));
  133.  
  134.         if (qflag) {
  135.                 (void)printf("tcp %d", length - tp->th_off * 4);
  136.                 return;
  137.         }
  138.         if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH)) {
  139.                 if (flags & TH_SYN)
  140.                         putchar('S');
  141.                 if (flags & TH_FIN)
  142.                         putchar('F');
  143.                 if (flags & TH_RST)
  144.                         putchar('R');
  145.                 if (flags & TH_PUSH)
  146.                         putchar('P');
  147.         } else
  148.                 putchar('.');
  149.  
  150.         if (!Sflag && (flags & TH_ACK)) {
  151.                 register struct tcp_seq_hash *th;
  152.                 register int rev;
  153.                 struct tha tha;
  154.                 /*
  155.                  * Find (or record) the initial sequence numbers for
  156.                  * this conversation.  (we pick an arbitrary
  157.                  * collating order so there's only one entry for
  158.                  * both directions).
  159.                  */
  160.                 if (sport < dport ||
  161.                     (sport == dport &&
  162.                      ip->ip_src.s_addr < ip->ip_dst.s_addr)) {
  163.                         tha.src = ip->ip_src, tha.dst = ip->ip_dst;
  164.                         tha.port = sport << 16 | dport;
  165.                         rev = 0;
  166.                 } else {
  167.                         tha.src = ip->ip_dst, tha.dst = ip->ip_src;
  168.                         tha.port = dport << 16 | sport;
  169.                         rev = 1;
  170.                 }
  171.  
  172.                 for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
  173.                      th->nxt; th = th->nxt)
  174.                         if (!memcmp((char *)&tha, (char *)&th->addr,
  175.                                   sizeof(th->addr)))
  176.                                 break;
  177.  
  178.                 if (!th->nxt || flags & TH_SYN) {
  179.                         /* didn't find it or new conversation */
  180.                         if (th->nxt == NULL) {
  181.                                 th->nxt = (struct tcp_seq_hash *)
  182.                                         calloc(1, sizeof(*th));
  183.                                 if (th->nxt == NULL)
  184.                                         error("tcp_print: calloc");
  185.                         }
  186.                         th->addr = tha;
  187.                         if (rev)
  188.                                 th->ack = seq, th->seq = ack - 1;
  189.                         else
  190.                                 th->seq = seq, th->ack = ack - 1;
  191.                 } else {
  192.                         if (rev)
  193.                                 seq -= th->ack, ack -= th->seq;
  194.                         else
  195.                                 seq -= th->seq, ack -= th->ack;
  196.                 }
  197.         }
  198.         hlen = tp->th_off * 4;
  199.         length -= hlen;
  200.         if (length > 0 || flags & (TH_SYN | TH_FIN | TH_RST))
  201.                 (void)printf(" %u:%u(%d)", seq, seq + length, length);
  202.         if (flags & TH_ACK)
  203.                 (void)printf(" ack %u", ack);
  204.  
  205.         (void)printf(" win %d", win);
  206.  
  207.         if (flags & TH_URG)
  208.                 (void)printf(" urg %d", urp);
  209.         /*
  210.          * Handle any options.
  211.          */
  212.         if ((hlen -= sizeof(*tp)) > 0) {
  213.                 register const u_char *cp;
  214.                 register int i, opt, len, datalen;
  215.  
  216.                 cp = (const u_char *)tp + sizeof(*tp);
  217.                 putchar(' ');
  218.                 ch = '<';
  219.                 while (hlen > 0) {
  220.                         --hlen;
  221.                         putchar(ch);
  222.                         if (cp > snapend)
  223.                                 goto trunc;
  224.                         opt = *cp++;
  225.                         if (ZEROLENOPT(opt))
  226.                                 len = 1;
  227.                         else {
  228.                                 if (cp > snapend)
  229.                                         goto trunc;
  230.                                 len = *cp++;
  231.                                 --hlen;
  232.                         }
  233.                         datalen = 0;
  234.                         switch (opt) {
  235.  
  236.                         case TCPOPT_MAXSEG:
  237.                                 (void)printf("mss");
  238.                                 datalen = 2;
  239.                                 if (cp + datalen > snapend)
  240.                                         goto trunc;
  241.                                 (void)printf(" %u", EXTRACT_16BITS(cp));
  242.  
  243.                                 break;
  244.  
  245.                         case TCPOPT_EOL:
  246.                                 (void)printf("eol");
  247.                                 break;
  248.  
  249.                         case TCPOPT_NOP:
  250.                                 (void)printf("nop");
  251.                                 break;
  252.  
  253.                         case TCPOPT_WSCALE:
  254.                                 (void)printf("wscale");
  255.                                 datalen = 1;
  256.                                 if (cp + datalen > snapend)
  257.                                         goto trunc;
  258.                                 (void)printf(" %u", *cp);
  259.                                 break;
  260.  
  261.                         case TCPOPT_SACKOK:
  262.                                 (void)printf("sackOK");
  263.                                 break;
  264.  
  265.                         case TCPOPT_SACK:
  266.                                 (void)printf("sack");
  267.                                 datalen = len - 2;
  268.                                 i = datalen;
  269.                                 for (i = datalen; i > 0; i -= 4) {
  270.                                         if (cp + i + 4 > snapend)
  271.                                                 goto trunc;
  272.                                         /* block-size@relative-origin */
  273.                                         (void)printf(" %u@%u",
  274.                                             EXTRACT_16BITS(cp + 2),
  275.                                             EXTRACT_16BITS(cp));
  276.                                 }
  277.                                 if (datalen % 4)
  278.                                         (void)printf("[len %d]", len);
  279.                                 break;
  280.  
  281.                         case TCPOPT_ECHO:
  282.                                 (void)printf("echo");
  283.                                 datalen = 4;
  284.                                 if (cp + datalen > snapend)
  285.                                         goto trunc;
  286.                                 (void)printf(" %u", EXTRACT_32BITS(cp));
  287.                                 break;
  288.  
  289.                         case TCPOPT_ECHOREPLY:
  290.                                 (void)printf("echoreply");
  291.                                 datalen = 4;
  292.                                 if (cp + datalen > snapend)
  293.                                         goto trunc;
  294.                                 (void)printf(" %u", EXTRACT_32BITS(cp));
  295.                                 break;
  296.  
  297.                         case TCPOPT_TIMESTAMP:
  298.                                 (void)printf("timestamp");
  299.                                 datalen = 4;
  300.                                 if (cp + datalen > snapend)
  301.                                         goto trunc;
  302.                                 (void)printf(" %u", EXTRACT_32BITS(cp));
  303.                                 datalen += 4;
  304.                                 if (cp + datalen > snapend)
  305.                                         goto trunc;
  306.                                 (void)printf(" %u", EXTRACT_32BITS(cp + 4));
  307.                                 break;
  308.  
  309.                         case TCPOPT_CC:
  310.                                 (void)printf("cc");
  311.                                 datalen = 4;
  312.                                 if (cp + datalen > snapend)
  313.                                         goto trunc;
  314.                                 (void)printf(" %u", EXTRACT_32BITS(cp));
  315.                                 break;
  316.  
  317.                         case TCPOPT_CCNEW:
  318.                                 (void)printf("ccnew");
  319.                                 datalen = 4;
  320.                                 if (cp + datalen > snapend)
  321.                                         goto trunc;
  322.                                 (void)printf(" %u", EXTRACT_32BITS(cp));
  323.                                 break;
  324.  
  325.                         case TCPOPT_CCECHO:
  326.                                 (void)printf("ccecho");
  327.                                 datalen = 4;
  328.                                 if (cp + datalen > snapend)
  329.                                         goto trunc;
  330.                                 (void)printf(" %u", EXTRACT_32BITS(cp));
  331.                                 break;
  332.  
  333.                         default:
  334.                                 (void)printf("opt-%d:", opt);
  335.                                 datalen = len - 2;
  336.                                 if  (datalen < 0)
  337.                                         datalen = 0;
  338.                                 for (i = 0; i < datalen; ++i) {
  339.                                         if (cp + i > snapend)
  340.                                                 goto trunc;
  341.                                         (void)printf("%02x", cp[i]);
  342.                                 }
  343.                                 break;
  344.                         }
  345.  
  346.                         /* Account for data printed */
  347.                         cp += datalen;
  348.                         hlen -= datalen;
  349.  
  350.                         /* Check specification against observed length */
  351.                         ++datalen;                      /* option octet */
  352.                         if (!ZEROLENOPT(opt))
  353.                                 ++datalen;              /* size octet */
  354.                         if (datalen != len)
  355.                                 (void)printf("[len %d]", len);
  356.                         ch = ',';
  357.                 }
  358.                 putchar('>');
  359.         }
  360.  
  361.         /* check for specific tcp-based protocols. This will never be
  362.          perfect because of the stream nature of tcp but in practice
  363.          it does pretty well */
  364.         if (!qflag) {
  365. #define ISPORT(p) (dport == (p) || sport == (p))
  366.  
  367.           u_char *data = (u_char *)(tp + 1);
  368.           u_char *data_end;
  369.  
  370.           if (length < snaplen - sizeof(*tp))
  371.             data_end = data + length;
  372.           else
  373.             data_end = data + snaplen - sizeof(*tp);
  374.  
  375.           if (ISPORT(NETBIOS_SSN_PORT)) {
  376.             /* netbios-ssn packets, as used for file
  377.                sharing by SMB (in for example, windows) */
  378.             nbt_tcp_print(data, data_end);
  379.           }
  380.         }
  381.  
  382.         return;
  383. trunc:
  384.         fputs("[|tcp]", stdout);
  385.         if (ch != '\0')
  386.                 putchar('>');
  387. }
  388.  
  389.