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

📄 pcap-dos.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  This file is part of DOS-libpcap *  Ported to DOS/DOSX by G. Vanem <giva@bgnett.no> * *  pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode *              network drivers. * * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1.2.1 2005/05/03 18:54:35 guy Exp $ (LBL) */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <float.h>#include <fcntl.h>#include <io.h>#if defined(USE_32BIT_DRIVERS)  #include "msdos/pm_drvr/pmdrvr.h"  #include "msdos/pm_drvr/pci.h"  #include "msdos/pm_drvr/bios32.h"  #include "msdos/pm_drvr/module.h"  #include "msdos/pm_drvr/3c501.h"  #include "msdos/pm_drvr/3c503.h"  #include "msdos/pm_drvr/3c509.h"  #include "msdos/pm_drvr/3c59x.h"  #include "msdos/pm_drvr/3c515.h"  #include "msdos/pm_drvr/3c90x.h"  #include "msdos/pm_drvr/3c575_cb.h"  #include "msdos/pm_drvr/ne.h"  #include "msdos/pm_drvr/wd.h"  #include "msdos/pm_drvr/accton.h"  #include "msdos/pm_drvr/cs89x0.h"  #include "msdos/pm_drvr/rtl8139.h"  #include "msdos/pm_drvr/ne2k-pci.h"#endif#include "pcap.h"#include "pcap-dos.h"#include "pcap-int.h"#include "msdos/pktdrvr.h"#ifdef USE_NDIS2#include "msdos/ndis2.h"#endif#include <arpa/inet.h>#include <net/if.h>#include <net/if_arp.h>#include <net/if_ether.h>#include <net/if_packe.h>#include <tcp.h>#if defined(USE_32BIT_DRIVERS)  #define FLUSHK()       do { _printk_safe = 1; _printk_flush(); } while (0)  #define NDIS_NEXT_DEV  &rtl8139_dev  static char *rx_pool = NULL;  static void init_32bit (void);  static int  pktq_init     (struct rx_ringbuf *q, int size, int num, char *pool);  static int  pktq_check    (struct rx_ringbuf *q);  static int  pktq_inc_out  (struct rx_ringbuf *q);  static int  pktq_in_index (struct rx_ringbuf *q) LOCKED_FUNC;  static void pktq_clear    (struct rx_ringbuf *q) LOCKED_FUNC;  static struct rx_elem *pktq_in_elem  (struct rx_ringbuf *q) LOCKED_FUNC;  static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q);#else  #define FLUSHK()      ((void)0)  #define NDIS_NEXT_DEV  NULL#endif/* * Internal variables/functions in Watt-32 */extern WORD  _pktdevclass;extern BOOL  _eth_is_init;extern int   _w32_dynamic_host;extern int   _watt_do_exit;extern int   _watt_is_init;extern int   _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req;extern void (*_w32_usr_post_init) (void);extern void (*_w32_print_hook)();extern void dbug_write (const char *);  /* Watt-32 lib, pcdbug.c */extern int  pkt_get_mtu (void);static int ref_count = 0;static u_long mac_count    = 0;static u_long filter_count = 0;static volatile BOOL exc_occured = 0;static struct device *handle_to_device [20];static int  pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,                           u_char *data);static void pcap_close_dos (pcap_t *p);static int  pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);static int  pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);static int  pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);static int  ndis_probe (struct device *dev);static int  pkt_probe  (struct device *dev);static void close_driver (void);static int  init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf);static int  first_init (const char *name, char *ebuf, int promisc);static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,                              const u_char *buf);/* * These are the device we always support */static struct device ndis_dev = {              "ndis",              "NDIS2 LanManager",              0,              0,0,0,0,0,0,              NDIS_NEXT_DEV,  /* NULL or a 32-bit device */              ndis_probe            };static struct device pkt_dev = {              "pkt",              "Packet-Driver",              0,              0,0,0,0,0,0,              &ndis_dev,              pkt_probe            };static struct device *get_device (int fd){  if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0]))     return (NULL);  return handle_to_device [fd-1];}/* * Open MAC-driver with name 'device_name' for live capture of * network packets. */pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc,                        int timeout_ms, char *errbuf){   struct pcap *pcap;  if (snaplen < ETH_MIN)      snaplen = ETH_MIN;  if (snaplen > ETH_MAX)   /* silently accept and truncate large MTUs */      snaplen = ETH_MAX;  pcap = calloc (sizeof(*pcap), 1);  if (!pcap)  {    strcpy (errbuf, "Not enough memory (pcap)");    return (NULL);  }  pcap->snapshot          = max (ETH_MIN+8, snaplen);  pcap->linktype          = DLT_EN10MB;  /* !! */  pcap->inter_packet_wait = timeout_ms;  pcap->close_op          = pcap_close_dos;  pcap->read_op           = pcap_read_dos;  pcap->stats_op          = pcap_stats_dos;  pcap->inject_op         = pcap_sendpacket_dos;  pcap->setfilter_op      = pcap_setfilter_dos;	pcap->setdirection_op   = NULL; /* Not implemented.*/  pcap->fd                = ++ref_count;  if (pcap->fd == 1)  /* first time we're called */  {    if (!init_watt32(pcap, device_name, errbuf) ||        !first_init(device_name, errbuf, promisc))    {      free (pcap);      return (NULL);    }     atexit (close_driver);  }  else if (stricmp(active_dev->name,device_name))  {    snprintf (errbuf, PCAP_ERRBUF_SIZE,              "Cannot use different devices simultaneously "              "(`%s' vs. `%s')", active_dev->name, device_name);    free (pcap);    pcap = NULL;  }  handle_to_device [pcap->fd-1] = active_dev;  return (pcap);}/* * Poll the receiver queue and call the pcap callback-handler * with the packet. */static intpcap_read_one (pcap_t *p, pcap_handler callback, u_char *data){  struct pcap_pkthdr pcap;  struct bpf_insn   *fcode = p->fcode.bf_insns;  struct timeval     now, expiry;  BYTE  *rx_buf;  int    rx_len = 0;  if (p->inter_packet_wait > 0)  {    gettimeofday2 (&now, NULL);    expiry.tv_usec = now.tv_usec + 1000UL * p->inter_packet_wait;    expiry.tv_sec  = now.tv_sec;    while (expiry.tv_usec >= 1000000L)    {      expiry.tv_usec -= 1000000L;      expiry.tv_sec++;    }  }  while (!exc_occured)  {    volatile struct device *dev; /* might be reset by sig_handler */    dev = get_device (p->fd);    if (!dev)       break;    PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf);    FLUSHK();    /* If driver has a zero-copy receive facility, peek at the queue,     * filter it, do the callback and release the buffer.     */    if (dev->peek_rx_buf)    {      PCAP_ASSERT (dev->release_rx_buf);      rx_len = (*dev->peek_rx_buf) (&rx_buf);    }    else    {      BYTE buf [ETH_MAX+100]; /* add some margin */      rx_len = (*dev->copy_rx_buf) (buf, p->snapshot);      rx_buf = buf;    }    if (rx_len > 0)  /* got a packet */    {      mac_count++;      FLUSHK();      pcap.caplen = min (rx_len, p->snapshot);      pcap.len    = rx_len;      if (callback &&          (!fcode || bpf_filter(fcode, rx_buf, pcap.len, pcap.caplen)))      {        filter_count++;        /* Fix-me!! Should be time of arrival. Not time of         * capture.         */        gettimeofday2 (&pcap.ts, NULL);        (*callback) (data, &pcap, rx_buf);      }      if (dev->release_rx_buf)        (*dev->release_rx_buf) (rx_buf);      if (pcap_pkt_debug > 0)      {        if (callback == watt32_recv_hook)             dbug_write ("pcap_recv_hook\n");        else dbug_write ("pcap_read_op\n");      }      FLUSHK();      return (1);    }    /* If not to wait for a packet or pcap_close() called from     * e.g. SIGINT handler, exit loop now.     */    if (p->inter_packet_wait <= 0 || (volatile int)p->fd <= 0)       break;    gettimeofday2 (&now, NULL);    if (timercmp(&now, &expiry, >))       break;#ifndef DJGPP    kbhit();    /* a real CPU hog */#endif    if (p->wait_proc)      (*p->wait_proc)();     /* call yield func */  }  if (rx_len < 0)            /* receive error */  {    p->md.stat.ps_drop++;#ifdef USE_32BIT_DRIVERS    if (pcap_pkt_debug > 1)       printk ("pkt-err %s\n", pktInfo.error);#endif    return (-1);  }  return (0);}static intpcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data){  int rc, num = 0;  while (num <= cnt || (cnt < 0))  {    if (p->fd <= 0)       return (-1);    rc = pcap_read_one (p, callback, data);    if (rc > 0)       num++;    if (rc < 0)       break;    _w32_os_yield();  /* allow SIGINT generation, yield to Win95/NT */  }  return (num);}/* * Return network statistics */static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps){  struct net_device_stats *stats;  struct device           *dev = p ? get_device(p->fd) : NULL;  if (!dev)  {    strcpy (p->errbuf, "illegal pcap handle");    return (-1);  }  if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL)  {    strcpy (p->errbuf, "device statistics not available");    return (-1);  }  FLUSHK();  p->md.stat.ps_recv   = stats->rx_packets;  p->md.stat.ps_drop  += stats->rx_missed_errors;  p->md.stat.ps_ifdrop = stats->rx_dropped +  /* queue full */                         stats->rx_errors;    /* HW errors */  if (ps)     *ps = p->md.stat;  return (0);}/* * Return detailed network/device statistics. * May be called after 'dev->close' is called. */int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se){  struct device *dev = p ? get_device (p->fd) : NULL;  if (!dev || !dev->get_stats)  {    strlcpy (p->errbuf, "detailed device statistics not available",             PCAP_ERRBUF_SIZE);    return (-1);  }  if (!strnicmp(dev->name,"pkt",3))  {    strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",             PCAP_ERRBUF_SIZE);    return (-1);  }               memcpy (se, (*dev->get_stats)(dev), sizeof(*se));  return (0);}/* * Simply store the filter-code for the pcap_read_dos() callback * Some day the filter-code could be handed down to the active * device (pkt_rx1.s or 32-bit device interrupt handler). */static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp){  if (!p)     return (-1);  p->fcode = *fp;  return (0);}/* * Return # of packets received in pcap_read_dos() */u_long pcap_mac_packets (void){  return (mac_count);}/* * Return # of packets passed through filter in pcap_read_dos() */u_long pcap_filter_packets (void){  return (filter_count);}/* * Close pcap device. Not called for offline captures. */static void pcap_close_dos (pcap_t *p){  if (p && !exc_occured)  {    if (pcap_stats(p,NULL) < 0)       p->md.stat.ps_drop = 0;    if (!get_device(p->fd))       return;    handle_to_device [p->fd-1] = NULL;    p->fd = 0;    if (ref_count > 0)        ref_count--;    if (ref_count > 0)       return;  }  close_driver();}/* * Return the name of the 1st network interface, * or NULL if none can be found. */char *pcap_lookupdev (char *ebuf){  struct device *dev;#ifdef USE_32BIT_DRIVERS  init_32bit();#endif  for (dev = (struct device*)dev_base; dev; dev = dev->next)  {    PCAP_ASSERT (dev->probe);    if ((*dev->probe)(dev))    {      FLUSHK();      probed_dev = (struct device*) dev; /* remember last probed device */      return (char*) dev->name;    }  }  if (ebuf)     strcpy (ebuf, "No driver found");  return (NULL);}/* * Gets localnet & netmask from Watt-32. */int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,                    bpf_u_int32 *netmask, char *errbuf){  if (!_watt_is_init)  {    strcpy (errbuf, "pcap_open_offline() or pcap_open_live() must be "                    "called first");    return (-1);  }  *netmask  = _w32_sin_mask;  *localnet = my_ip_addr & *netmask;  if (*localnet == 0)  {    if (IN_CLASSA(*netmask))       *localnet = IN_CLASSA_NET;    else if (IN_CLASSB(*netmask))       *localnet = IN_CLASSB_NET;

⌨️ 快捷键说明

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