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

📄 tcpdump.c

📁 This directory contains source code for tcpdump, a tool for network monitoring and data acquisition
💻 C
📖 第 1 页 / 共 2 页
字号:
      if (!pcap_device)
         PERROR ((ebuf));
    }

    pd = pcap_open_live (pcap_device, snaplen, !pflag, 0, ebuf);
    if (!pd)
       PERROR ((ebuf));
    if (!pd)
       WARNING ((ebuf));

    if (Lflag)
       show_dlts_and_exit (pd);

    if (dlt >= 0)
    {
      if (pcap_set_datalink(pd, dlt) < 0)
         PERROR (("%s", pcap_geterr(pd)));
      fprintf (stderr, "%s: data link type %s\n", program_name, dlt_name);
    }

    i = pcap_snapshot (pd);
    if (snaplen < i)
    {
      WARNING (("snaplen raised from %d to %d", snaplen, i));
      snaplen = i;
    }
    if (pcap_lookupnet (pcap_device, (bpf_u_int32*)&localnet,
                        (bpf_u_int32*)&netmask, ebuf) < 0)
    {
      localnet = 0;
      netmask  = 0;
      WARNING ((ebuf));
    }
  }

  /* Hook handlers for SIGINT, SIGBREAK and SIGQUIT
   */
  init_handlers();

  if (infile)
       cmdbuf = read_infile (infile);
  else cmdbuf = copy_argv (&argv[optind]);

  if (pcap_compile (pd, &fcode, cmdbuf, Oflag, netmask) < 0)
  {
    program_end (0);
    PERROR ((pcap_geterr(pd)));
  }

  if (snaplen < 102 && fcode.bf_insns[3].k == 36)
     WARNING (("snaplen < 102, XTP headers will be truncated"));

  if (dflag)
  {
    program_end (1);
    bpf_dump (&fcode, dflag);
    return (0);
  }

  init_addrtoname (nflag, localnet, netmask);

  if (pcap_setfilter(pd,&fcode) < 0)
  {
    program_end (0);
    PERROR ((pcap_geterr(pd)));
  }

  if (WFileName)
  {
    pcap_dumper_t *p = pcap_dump_open (pd, WFileName);

    if (!p)
    {
      program_end (0);
      PERROR ((pcap_geterr(pd)));
    }
    printer = pcap_dump;
    pcap_userdata = (u_char*)p;
    if (vflag)
       pcap_verbose (1);
  }
  else
  {
    printer = lookup_printer (pcap_datalink(pd));
    pcap_userdata = 0;
  }

  if (use_conio)
  {
#ifdef USE_CONIO
    set_conio();
#else
    program_end (1);
    PERROR (("`-C' option not supported in this version."));
#endif
  }

  if (!RFileName)
  {
    char buf[50];
    sprintf (buf, "%s: listening on %s\n",
             program_name, pcap_device ? pcap_device : "all devices");

#ifdef USE_CONIO
    if (use_conio)
         PRINTF (buf);
    else fprintf (stderr, buf);
#else
    fprintf (stderr, buf);
#endif
  }

  if (pcap_loop(pd,count,printer,pcap_userdata) < 0)
  {
    fprintf (stderr, "%s: pcap_loop: %s\n", program_name, pcap_geterr(pd));
    rc = 1;
  }

  dump_stats();
  program_end (1);

  if (Hflag && !RFileName)
     dump_hostnames();

  return (rc);
}

static void program_end (int free_mem)
{
  static int done = 0;

  if (!done)
  {
    pcap_close (pd);
    if (free_mem)
    {
      free (pd);
      pd = NULL;
    }
    done = 1;
  }
}

/*
 * Can't print the summary if reading from a savefile
 */
static void dump_stats (void)
{
  struct pcap_stat    stat;
  struct pcap_stat_ex stat_ex;

  if (!pd || pcap_file(pd))
     return;

  if (pcap_stats(pd,&stat) < 0)
     fprintf (stderr, "pcap_stats: %s\n", pcap_geterr(pd));
  else
  {
    fprintf (stderr, "packets received by filter: %-6lu\n", stat.ps_recv);
    fprintf (stderr, "packets passed thru filter: %-6lu\n", pcap_filter_packets());
     
    if (stat.ps_recv)
    {
      fprintf (stderr, "packets dropped by kernel/pcap: %-6lu (%.1f%%)\n",
               stat.ps_drop,
               100.0 * (double)stat.ps_drop / (double)stat.ps_recv);
      fprintf (stderr, "packets dropped by driver/hw:   %-6lu (%.1f%%)\n",
               stat.ps_ifdrop,
               100.0 * (double)stat.ps_ifdrop / (double)stat.ps_recv);
    }
  }

  if (pcap_stats_ex (pd,&stat_ex) >= 0)    /* extended statistics */
  {
    fprintf (stderr,
      "details: packets  %lu, bytes %lu, dropped %lu, errors %lu, collisions %lu\n"
      "         FIFO err %lu, overruns %lu, framing %lu, len err %lu, CRC err %lu\n",
      stat_ex.rx_packets, stat_ex.rx_bytes, stat_ex.rx_dropped,
      stat_ex.rx_errors, stat_ex.collisions, stat_ex.rx_fifo_errors,
      stat_ex.rx_over_errors, stat_ex.rx_frame_errors,
      stat_ex.rx_length_errors, stat_ex.rx_crc_errors);
  }
}

/* 
 * Like default_print() but data need not be aligned
 */
void default_print_unaligned (const u_char *cp, u_int length)
{
  int   nshorts = length / sizeof(u_short);
  u_int s, i = 0;

  if (xaflag)
  {
    dump_hex_ascii (cp,length);
    return;
  }
  if (Aflag)
  {
    dump_ascii (cp,length);
    return;
  }

  while (--nshorts >= 0)
  {
    if ((i++ % 8) == 0)
       PUTS ("\n\t\t\t");
    s = *cp++;
    PRINTF (" %02x%02x", s, *cp++);
  }
  if (length & 1)
  {
    if ((i % 8) == 0)
       PUTS ("\n\t\t\t");
    PRINTF (" %02x", *cp);
  }
}

void default_print (const u_char *bp, u_int length)
{
  const u_short *sp;
  u_int i;
  int   nshorts;

  if (xaflag)
  {
    dump_hex_ascii (bp,length);
    return;
  }
  if (Aflag)
  {
    dump_ascii (bp,length);
    return;
  }

#if 0
  if (!xflag)
  {
    PUTCHAR ('\n');
    print_data (bp, length);
    return;
  }
#endif

  if ((unsigned)bp & 1)
  {
    default_print_unaligned (bp, length);
    return;
  }
  sp = (u_short *) bp;
  nshorts = (u_int) length / sizeof(u_short);
  i = 0;
  while (--nshorts >= 0)
  {
    if ((i++ % 8) == 0)
       PUTS ("\n\t\t\t");
    PRINTF (" %04x", ntohs (*sp++));
  }
  if (length & 1)
  {
    if ((i % 8) == 0)
       PUTS ("\n\t\t\t");
    PRINTF (" %02x", *(u_char*)sp);
  }
}

static void dump_ascii (const u_char *bp, u_int length)
{
  char  buf [5000];
  char *ptr = buf;

  *ptr++ = '\n';

  while ((int)length-- > 0)
  {
    if (*bp > 0x7E || isprint(*bp))
       *ptr++ = *bp++;
    else
    {
     /* Convert control characters, e.g. 13 -> "\r", 0 -> "^@"
      */
      switch (*bp)
      {
        case '\r':
             strcpy (ptr,"\\r");
             break;
        case '\n':
             strcpy (ptr,"\\n\n");
             ptr++;
             break;
        case '\t':
             strcpy (ptr,"\\t");
             break;
        default:
             ptr[0] = '^';
             ptr[1] = *bp + '@';
      }
      ptr += 2;
      bp++;
    }
  }
  if (ptr > buf+1)
  {
    *ptr = '\0';
    PUTS (buf);
  }
}

static void dump_hex_ascii (const u_char *bp, u_int length)
{
  u_int ofs, j;

  for (ofs = 0; ofs < length; ofs += 16)
  {
    char buf [80];

    PRINTF ("\n\t%04X: ", ofs);
    for (j = 0; j < 16 && j+ofs < length; j++)
        PRINTF ("%02X ", (unsigned)bp[j+ofs]);

    if (j < 16)
       PRINTF ("%*s", 3*(16-j), "");

    for (j = 0; j < 16 && j+ofs < length; j++)
    {
      u_char ch = bp[j+ofs];
      if (ch < ' ')
          ch = '.';
      buf[j] = ch;
    }
    PRINTF ("%.*s", (int)j, buf);
  }
}


/*
 *  Print a usage message, optionally full details
 */
static void program_usage (int details)
{
  char features[80] = { '\0' };

#if defined (__HIGHC__)
  static char *builder = "HighC/Pharlap";

#elif defined (__DJGPP__)
  static char *builder = "GNU-C/djgpp2";

#elif defined (__WATCOMC__)
  static char *builder = "Watcom-C";

#else
  static char *builder = "??";
#endif

  printf ("Version %s (%s). pcap v%d.%d\n"
          "Usage: %s%s [-?adDeEfhLlnNOpPqRStuvxXC] [-c count] [-F file]\n"
          "               [-i interface] [-M type] [-r file] [-s snaplen]\n"
          "               [-E espkey] [m module] [-T type] [-w file] [filter-expression]\n\n",
          TCPDUMP_VERSION, builder, PCAP_VERSION_MAJOR, PCAP_VERSION_MINOR,
          program_path, program_name);

  if (details)
  {
    printf (
          "options: -a    translate network/broadcast addresses to names\n"
          "         -b    parse only link-layer protocol <p>\n"
          "         -c    stop after receiving count packets\n"
          "         -d    dump compiled filter expression and stop\n"
          "         -D    dump info on supported devices\n"
          "         -e    print link-level header on each line\n"
          "         -E    secret for decrypting ESP packets\n"
          "         -f    print foreign ip-addresses numerically\n"
          "         -F    read filter expression from file\n"
          "         -h    write resolved host names to `hosts.add' file\n"
          "         -i    select interface. Use `-i?' for supported drivers\n"
          "         -L    list available data link types and exit\n"
          "         -l    make stdout line buffered\n"
          "         -M    specify message type for SunRPC protocols (-M? for list)\n"
          "         -m    load SMI MIB module definitions from file\n"
          "         -n    print addresses numerically\n"
          "         -N    don't print domain of host names\n"
          "         -O    don't run packet-matching optimiser\n"
          "         -p    don't set network driver in promiscuous mode\n"
          "         -P    print details for some SunRPC protocols\n"
          "         -q    quick output; prints short packet-trace\n"
          "         -r    read packet data from file\n"
          "         -R    print packets read from file at real pace\n"
          "         -s    truncate the packets to snaplen (%d)\n"
          "         -S    print absolute TCP sequence numbers\n"
          "         -t    don't print a timestamp on each dump line\n"
          "         -tt   print timestamp in Unix style\n"
          "         -ttt  print times in time-deltas\n"
          "         -tttt print time and date (MM/DD/YYYY)\n"
          "         -T    force interpretion to specified type (-T? for list)\n"
          "         -u    print undecoded NFS handles\n"
          "         -v    verbose output; prints IP-tos/ttl etc.\n"
          "         -w    write packet data to file (see -r)\n"
          "         -A    print packet contents in ascii (without headers)\n"
          "         -x    print packet contents in hex\n"
          "         -X    print packet contents in hex and ascii\n"
          "         -C    print using direct screen write\n", DEFAULT_SNAPLEN);

#ifdef USE_INET6
     strcat (features, "IPv6, ");
#endif

#ifdef PRINT_NETBIOS_DETAILS
     strcat (features, "NetBIOS details, ");
#endif

#ifdef PRINT_DECNET_DETAILS
     strcat (features, "DEC-Net details, ");
#endif

#ifdef USE_RSVP
     strcat (features, "RSVP decoding, ");
#endif

#ifdef USE_SSL
     strcat (features, "SSL decoding, ");
#endif

#ifdef LIBSMI
     strcat (features, "MIB modules, ");
#endif

    *strrchr (features, ',') = '.';
    printf ("Built-in features: %s\n", features);
  }
  exit (-1);
}

#ifdef __DJGPP__
/*
 * Disable wildcard expansion on command-line
 */
char **__crt0_glob_function (char *arg)  
{
  return (char**)0;
}

static int old_sigquit = -1;
#endif

/*
 * called on a interrupt signal
 */
static void sigint_task (void)
{
#ifdef __DJGPP__
  if (old_sigquit != -1)
     __djgpp_set_sigquit_key (old_sigquit);
#endif

#ifdef __HIGHC__
  _dx_reset_data();
#endif

#ifdef USE_CONIO
  if (use_conio)
     unset_conio();
  else
#endif
    putc ('\n', stderr);

  dump_stats();
  program_end (1);

  if (Hflag && !RFileName)
     dump_hostnames();

  exit (0);
}

/*
 * Signal handler for SIGINT/SIGBREAK (^C/^Break).
 */
static void sig_handler (int sig)
{
  signal (sig, sig_handler);

  if (sig == SIGINT)
     sigint_task();

#ifdef SIGBREAK
  if (sig == SIGBREAK)
     sigint_task();
#endif

#ifdef SIGQUIT
  if (sig == SIGQUIT)
     sigint_task();
#endif

  fprintf (stderr, "Illegal signal %d\n", sig);
}

/*
 * Setup handlers for SIGINT,SIGBREAK and SIGQUIT.
 * SIGSEGV, SIGILL and SIGFPE handlers are already installed
 * in pcap_open_live(). Should maybe reset them here.
 */
static void init_handlers (void)
{
#if defined(__DJGPP__)
  old_sigquit = __djgpp_set_sigquit_key (1);  /* Make-code for ESC */
  set_cbreak (break_mode);
#endif

#ifdef SIGBREAK
  signal (SIGBREAK, sig_handler);
#endif

#ifdef SIGQUIT
  signal (SIGQUIT, sig_handler);
#endif

  signal (SIGINT, sig_handler);

#if defined(__HIGHC__)
  InstallExcHandler (NULL);
#endif
}

⌨️ 快捷键说明

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