?? pcap-dos.c
字號:
/* * 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;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -