⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _tcp.c

📁 This directory contains source code for tcpdump, a tool for network monitoring and data acquisition
💻 C
📖 第 1 页 / 共 2 页
字号:
      }
      else
      {
        *(struct in_addr *) &tha.dst = ip->ip_dst;
        *(struct in_addr *) &tha.src = ip->ip_src;
        tha.port = sport << 16 | dport;
      }
    }
#else
    if (sport < dport || (sport == dport && ip->ip_src.s_addr < ip->ip_dst.s_addr))
    {
      tha.src = ip->ip_src, tha.dst = ip->ip_dst;
      tha.port = sport << 16 | dport;
      rev = 0;
    }
    else
    {
      tha.src = ip->ip_dst, tha.dst = ip->ip_src;
      tha.port = dport << 16 | sport;
      rev = 1;
    }
#endif

    threv = rev;

    for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
         th->nxt; th = th->nxt)
    {
      if (!memcmp(&tha,&th->addr,sizeof(th->addr)))
         break;
    }

    if (!th->nxt || (flags & TH_SYN))
    {
      /* didn't find it or new conversation
       */
      if (!th->nxt)
      {
        th->nxt = calloc (1, sizeof(*th));
        if (!th->nxt)
           PERROR (("tcp_print: calloc"));
      }
      th->addr = tha;
      if (rev)
           th->ack = seq, th->seq = ack - 1;
      else th->seq = seq, th->ack = ack - 1;
    }
    else
    {
      thseq = th->seq;
      thack = th->ack;

      if (rev)
           seq -= th->ack, ack -= th->seq;
      else seq -= th->seq, ack -= th->ack;
    }
  }
  else
  {
    /* fool gcc */
    thseq = thack = threv = 0;
  }

  if (hlen > length)
  {
    PUTS (" [bad hdr length]");
    return;
  }

  if (IP_V (ip) == 4 && vflag && !fragmented)
  {
    int sum;

    if (TTEST2 (tp->th_sport, length))
    {
      sum = tcp_cksum (ip, tp, length);
      if (sum != 0)
           PRINTF (" [bad tcp cksum %x!]", sum);
      else PUTS (" [tcp sum ok]");
    }
  }
#ifdef USE_INET6
  if (IP_V (ip) == 6 && ip6->ip6_plen && vflag && !fragmented)
  {
    int sum;

    if (TTEST2 (tp->th_sport, length))
    {
      sum = tcp6_cksum (ip6, tp, length);
      if (sum != 0)
           PRINTF (" [bad tcp cksum %x!]", sum);
      else PUTS (" [tcp sum ok]");
    }
  }
#endif

  length -= hlen;
  if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST))
     PRINTF (" %u:%u(%d)", seq, seq + length, length);
  if (flags & TH_ACK)
     PRINTF (" ack %u", ack);

  PRINTF (" win %d", win);

  if (flags & TH_URG)
    PRINTF (" urg %d", urp);

  /*
   * Handle any options.
   */
  hlen -= sizeof(*tp);
  if (hlen > 0)
  {
    const u_char *cp;
    int   i, opt, len, datalen;

    cp = (const u_char*)tp + sizeof(*tp);
    PUTCHAR (' ');
    ch = '<';

    while (hlen > 0)
    {
      PUTCHAR (ch);
      TCHECK (*cp);
      opt = *cp++;
      if (ZEROLENOPT (opt))
        len = 1;
      else
      {
        TCHECK (*cp);
        len = *cp++;
        if (len < 2 || len > hlen)
          goto bad;
        --hlen;                    /* account for length byte */
      }
      --hlen;                      /* account for type byte */
      datalen = 0;
/*
 * Bail if "l" bytes of data are not left or were not captured
 */
#define LENCHECK(l) { if ((l) > hlen)  \
                         goto bad;     \
                      TCHECK2(*cp, l); \
                    }

      switch (opt)
      {
        case TCPOPT_MAXSEG:
             PUTS ("mss");
             datalen = 2;
             LENCHECK (datalen);
             PRINTF (" %u", EXTRACT_16BITS (cp));
             break;

        case TCPOPT_EOL:
             PUTS ("eol");
             break;

        case TCPOPT_NOP:
             PUTS ("nop");
             break;

        case TCPOPT_WSCALE:
             PUTS ("wscale");
             datalen = 1;
             LENCHECK (datalen);
             PRINTF (" %u", *cp);
             break;

        case TCPOPT_SACKOK:
             PUTS ("sackOK");
             break;

        case TCPOPT_SACK:
             {
               u_int32_t s, e;

               datalen = len - 2;
               if (datalen % 8)
                  PUTS (" malformed sack ");
               else
               {
                 PRINTF (" sack %d ", datalen / 8);
                 for (i = 0; i < datalen; i += 8)
                 {
                   LENCHECK(i + 4);
                   s = EXTRACT_32BITS(cp + i);
                   LENCHECK(i + 8);
                   e = EXTRACT_32BITS(cp + i + 4);
                   if (threv)
                   {
                     s -= thseq;
                     e -= thseq;
                   }
                   else
                   {
                     s -= thack;
                     e -= thack;
                   }
                   PRINTF ("{%u:%u}", s, e);
                 }
                 PUTCHAR (' ');
               }
               break;
             }

        case TCPOPT_ECHO:
             PUTS ("echo");
             datalen = 4;
             LENCHECK (datalen);
             PRINTF (" %lu", EXTRACT_32BITS (cp));
             break;

        case TCPOPT_ECHOREPLY:
             PUTS ("echoreply");
             datalen = 4;
             LENCHECK (datalen);
             PRINTF (" %lu", EXTRACT_32BITS (cp));
             break;

        case TCPOPT_TIMESTAMP:
             PUTS ("timestamp");
             datalen = 8;
             LENCHECK (4);
             PRINTF (" %lu", EXTRACT_32BITS (cp));
             LENCHECK (datalen);
             PRINTF (" %lu", EXTRACT_32BITS (cp + 4));
             break;

        case TCPOPT_CC:
             PUTS ("cc");
             datalen = 4;
             LENCHECK (datalen);
             PRINTF (" %lu", EXTRACT_32BITS (cp));
             break;

        case TCPOPT_CCNEW:
             PUTS ("ccnew");
             datalen = 4;
             LENCHECK (datalen);
             PRINTF (" %lu", EXTRACT_32BITS (cp));
             break;

        case TCPOPT_CCECHO:
             PUTS ("ccecho");
             datalen = 4;
             LENCHECK (datalen);
             PRINTF (" %lu", EXTRACT_32BITS (cp));
             break;

        default:
             PRINTF ("opt-%d:", opt);
             datalen = len - 2;
             for (i = 0; i < datalen; ++i)
             {
               LENCHECK (i);
               PRINTF ("%02x", cp[i]);
             }
             break;
      }

      /* Account for data printed */
      cp   += datalen;
      hlen -= datalen;

      /* Check specification against observed length */
      ++datalen;                 /* option octet */
      if (!ZEROLENOPT (opt))
         ++datalen;              /* size octet */
      if (datalen != len)
         PRINTF ("[len %d]", len);
      ch = ',';
      if (opt == TCPOPT_EOL)
        break;
    }
    PUTCHAR ('>');
  }

  /* check for specific tcp-based protocols. This will never be
   * perfect because of the stream nature of tcp but in practice
   * it does pretty well
   */
  if (!qflag)
  {
#define ISPORT(p) (dport == (p) || sport == (p))

    u_char *data = (u_char *)(tp + 1);
    u_char *data_end;

    if (length < snaplen - sizeof(*tp))
         data_end = data + length;
    else data_end = data + snaplen - sizeof(*tp);

#ifdef PRINT_NETBIOS_DETAILS
    if (ISPORT(NETBIOS_SSN_PORT))
    {
      /* netbios-ssn packets, as used for file
       * sharing by SMB (in for example, windows)
       */
      nbt_tcp_print (data, data_end);
    }
    else
#endif
    if (vflag && length > 0 && flags & TH_RST)
        print_tcp_rst_data (bp, length);
  }
  return;

bad:
  PUTS ("[bad opt]");
  if (ch)
     PUTCHAR ('>');

 /* check for specific tcp-based protocols. This will never be
  * perfect because of the stream nature of tcp but in practice
  * it does pretty well
  */
  if (!qflag)
  {
#define ISPORT(p) (dport == (p) || sport == (p))

    u_char *data = (u_char *)(tp + 1);
    u_char *data_end;

    if (length < snaplen - sizeof(*tp))
         data_end = data + length;
    else data_end = data + snaplen - sizeof(*tp);

#ifdef PRINT_NETBIOS_DETAILS
    if (ISPORT(NETBIOS_SSN_PORT))
    {
     /* netbios-ssn packets, as used for file
      * sharing by SMB (in for example, windows)
      */
      nbt_tcp_print (data, data_end);
    }
#endif
  }

  if (packettype)
  {
    switch (packettype)
    {
      case PT_SUNRPCRM:
           sunrpcrm_print ((void*)(tp+1), length, (const u_char*)ip, (const u_char*)tp);
           break;

      case PT_W3MUX:
           w3mux_print ((void*)(tp+1), length, (const u_char*)ip, (const u_char*)tp);
           break;

      case PT_IIOP:
           iiop_print ((void*)(tp+1), length, (const u_char*)ip, (const u_char*)tp);
           break;
    }
  }
  return;

trunc:
  PUTS ("[|tcp]");
  if (ch)
     PUTCHAR ('>');
}

/*
 *
 * RFC1122 says the following on data in RST segments:
 *
 *         4.2.2.12  RST Segment: RFC-793 Section 3.4
 *
 *            A TCP SHOULD allow a received RST segment to include data.
 *
 *            DISCUSSION
 *                 It has been suggested that a RST segment could contain
 *                 ASCII text that encoded and explained the cause of the
 *                 RST.  No standard has yet been established for such
 *                 data.
 *
 */
static void print_tcp_rst_data (const u_char *sp, u_int length)
{
  int c;

  if (TTEST2(*sp, length))
       PUTS (" [RST");
  else PUTS (" [!RST");

  if (length > MAX_RST_DATA_LEN)
  {
    length = MAX_RST_DATA_LEN;      /* can use -X for longer */
    PUTCHAR ('+');                  /* indicate we truncate */
  }
  PUTCHAR (' ');
  while (length-- && sp <= snapend)
  {
    c = *sp++;
    if (isgraph(c) || c == ' ')
         PUTCHAR (c);
    else PUTCHAR ('.');
  }
  PUTCHAR (']');
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -