Home | History | Annotate | Line # | Download | only in dist
      1  1.8  christos /*	$NetBSD: pcap-dos.c,v 1.8 2024/09/02 15:33:37 christos Exp $	*/
      2  1.2  christos 
      3  1.1  christos /*
      4  1.1  christos  *  This file is part of DOS-libpcap
      5  1.4  christos  *  Ported to DOS/DOSX by G. Vanem <gvanem (at) yahoo.no>
      6  1.1  christos  *
      7  1.1  christos  *  pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
      8  1.1  christos  *              network drivers.
      9  1.1  christos  */
     10  1.1  christos 
     11  1.1  christos #include <stdio.h>
     12  1.1  christos #include <stdlib.h>
     13  1.1  christos #include <string.h>
     14  1.1  christos #include <signal.h>
     15  1.1  christos #include <float.h>
     16  1.1  christos #include <fcntl.h>
     17  1.7  christos #include <limits.h> /* for INT_MAX */
     18  1.1  christos #include <io.h>
     19  1.1  christos 
     20  1.1  christos #if defined(USE_32BIT_DRIVERS)
     21  1.1  christos   #include "msdos/pm_drvr/pmdrvr.h"
     22  1.1  christos   #include "msdos/pm_drvr/pci.h"
     23  1.1  christos   #include "msdos/pm_drvr/bios32.h"
     24  1.1  christos   #include "msdos/pm_drvr/module.h"
     25  1.1  christos   #include "msdos/pm_drvr/3c501.h"
     26  1.1  christos   #include "msdos/pm_drvr/3c503.h"
     27  1.1  christos   #include "msdos/pm_drvr/3c509.h"
     28  1.1  christos   #include "msdos/pm_drvr/3c59x.h"
     29  1.1  christos   #include "msdos/pm_drvr/3c515.h"
     30  1.1  christos   #include "msdos/pm_drvr/3c90x.h"
     31  1.1  christos   #include "msdos/pm_drvr/3c575_cb.h"
     32  1.1  christos   #include "msdos/pm_drvr/ne.h"
     33  1.1  christos   #include "msdos/pm_drvr/wd.h"
     34  1.1  christos   #include "msdos/pm_drvr/accton.h"
     35  1.1  christos   #include "msdos/pm_drvr/cs89x0.h"
     36  1.1  christos   #include "msdos/pm_drvr/rtl8139.h"
     37  1.1  christos   #include "msdos/pm_drvr/ne2k-pci.h"
     38  1.1  christos #endif
     39  1.1  christos 
     40  1.1  christos #include "pcap.h"
     41  1.1  christos #include "pcap-dos.h"
     42  1.1  christos #include "pcap-int.h"
     43  1.1  christos #include "msdos/pktdrvr.h"
     44  1.1  christos 
     45  1.1  christos #ifdef USE_NDIS2
     46  1.1  christos #include "msdos/ndis2.h"
     47  1.1  christos #endif
     48  1.1  christos 
     49  1.1  christos #include <arpa/inet.h>
     50  1.1  christos #include <net/if.h>
     51  1.1  christos #include <net/if_arp.h>
     52  1.1  christos #include <net/if_ether.h>
     53  1.1  christos #include <net/if_packe.h>
     54  1.1  christos #include <tcp.h>
     55  1.1  christos 
     56  1.1  christos #if defined(USE_32BIT_DRIVERS)
     57  1.1  christos   #define FLUSHK()       do { _printk_safe = 1; _printk_flush(); } while (0)
     58  1.1  christos   #define NDIS_NEXT_DEV  &rtl8139_dev
     59  1.1  christos 
     60  1.1  christos   static char *rx_pool = NULL;
     61  1.1  christos   static void init_32bit (void);
     62  1.1  christos 
     63  1.1  christos   static int  pktq_init     (struct rx_ringbuf *q, int size, int num, char *pool);
     64  1.1  christos   static int  pktq_check    (struct rx_ringbuf *q);
     65  1.1  christos   static int  pktq_inc_out  (struct rx_ringbuf *q);
     66  1.1  christos   static int  pktq_in_index (struct rx_ringbuf *q) LOCKED_FUNC;
     67  1.1  christos   static void pktq_clear    (struct rx_ringbuf *q) LOCKED_FUNC;
     68  1.1  christos 
     69  1.1  christos   static struct rx_elem *pktq_in_elem  (struct rx_ringbuf *q) LOCKED_FUNC;
     70  1.1  christos   static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q);
     71  1.1  christos 
     72  1.1  christos #else
     73  1.1  christos   #define FLUSHK()      ((void)0)
     74  1.1  christos   #define NDIS_NEXT_DEV  NULL
     75  1.1  christos #endif
     76  1.1  christos 
     77  1.1  christos /*
     78  1.1  christos  * Internal variables/functions in Watt-32
     79  1.1  christos  */
     80  1.1  christos extern WORD  _pktdevclass;
     81  1.1  christos extern BOOL  _eth_is_init;
     82  1.1  christos extern int   _w32_dynamic_host;
     83  1.1  christos extern int   _watt_do_exit;
     84  1.1  christos extern int   _watt_is_init;
     85  1.1  christos extern int   _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req;
     86  1.1  christos extern void (*_w32_usr_post_init) (void);
     87  1.1  christos extern void (*_w32_print_hook)();
     88  1.1  christos 
     89  1.1  christos extern void dbug_write (const char *);  /* Watt-32 lib, pcdbug.c */
     90  1.1  christos extern int  pkt_get_mtu (void);
     91  1.1  christos 
     92  1.1  christos static int ref_count = 0;
     93  1.1  christos 
     94  1.1  christos static u_long mac_count    = 0;
     95  1.1  christos static u_long filter_count = 0;
     96  1.1  christos 
     97  1.8  christos static volatile BOOL exc_occurred = 0;
     98  1.1  christos 
     99  1.1  christos static struct device *handle_to_device [20];
    100  1.1  christos 
    101  1.1  christos static int  pcap_activate_dos (pcap_t *p);
    102  1.1  christos static int  pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,
    103  1.1  christos                            u_char *data);
    104  1.1  christos static void pcap_cleanup_dos (pcap_t *p);
    105  1.1  christos static int  pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);
    106  1.1  christos static int  pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);
    107  1.1  christos static int  pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);
    108  1.1  christos 
    109  1.1  christos static int  ndis_probe (struct device *dev);
    110  1.1  christos static int  pkt_probe  (struct device *dev);
    111  1.1  christos 
    112  1.1  christos static void close_driver (void);
    113  1.1  christos static int  init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf);
    114  1.1  christos static int  first_init (const char *name, char *ebuf, int promisc);
    115  1.1  christos 
    116  1.1  christos static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
    117  1.1  christos                               const u_char *buf);
    118  1.1  christos 
    119  1.1  christos /*
    120  1.1  christos  * These are the device we always support
    121  1.1  christos  */
    122  1.1  christos static struct device ndis_dev = {
    123  1.1  christos               "ndis",
    124  1.1  christos               "NDIS2 LanManager",
    125  1.1  christos               0,
    126  1.1  christos               0,0,0,0,0,0,
    127  1.1  christos               NDIS_NEXT_DEV,  /* NULL or a 32-bit device */
    128  1.1  christos               ndis_probe
    129  1.1  christos             };
    130  1.1  christos 
    131  1.1  christos static struct device pkt_dev = {
    132  1.1  christos               "pkt",
    133  1.1  christos               "Packet-Driver",
    134  1.1  christos               0,
    135  1.1  christos               0,0,0,0,0,0,
    136  1.1  christos               &ndis_dev,
    137  1.1  christos               pkt_probe
    138  1.1  christos             };
    139  1.1  christos 
    140  1.1  christos static struct device *get_device (int fd)
    141  1.1  christos {
    142  1.1  christos   if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0]))
    143  1.1  christos      return (NULL);
    144  1.1  christos   return handle_to_device [fd-1];
    145  1.1  christos }
    146  1.1  christos 
    147  1.2  christos /*
    148  1.2  christos  * Private data for capturing on MS-DOS.
    149  1.2  christos  */
    150  1.2  christos struct pcap_dos {
    151  1.4  christos 	void (*wait_proc)(void); /* call proc while waiting */
    152  1.2  christos 	struct pcap_stat stat;
    153  1.2  christos };
    154  1.2  christos 
    155  1.4  christos pcap_t *pcap_create_interface (const char *device _U_, char *ebuf)
    156  1.1  christos {
    157  1.1  christos 	pcap_t *p;
    158  1.1  christos 
    159  1.7  christos 	p = PCAP_CREATE_COMMON(ebuf, struct pcap_dos);
    160  1.1  christos 	if (p == NULL)
    161  1.1  christos 		return (NULL);
    162  1.1  christos 
    163  1.1  christos 	p->activate_op = pcap_activate_dos;
    164  1.1  christos 	return (p);
    165  1.1  christos }
    166  1.1  christos 
    167  1.1  christos /*
    168  1.1  christos  * Open MAC-driver with name 'device_name' for live capture of
    169  1.1  christos  * network packets.
    170  1.1  christos  */
    171  1.1  christos static int pcap_activate_dos (pcap_t *pcap)
    172  1.3  christos {
    173  1.1  christos   if (pcap->opt.rfmon) {
    174  1.1  christos     /*
    175  1.1  christos      * No monitor mode on DOS.
    176  1.1  christos      */
    177  1.1  christos     return (PCAP_ERROR_RFMON_NOTSUP);
    178  1.1  christos   }
    179  1.1  christos 
    180  1.5  christos   /*
    181  1.5  christos    * Turn a negative snapshot value (invalid), a snapshot value of
    182  1.5  christos    * 0 (unspecified), or a value bigger than the normal maximum
    183  1.5  christos    * value, into the maximum allowed value.
    184  1.5  christos    *
    185  1.5  christos    * If some application really *needs* a bigger snapshot
    186  1.5  christos    * length, we should just increase MAXIMUM_SNAPLEN.
    187  1.5  christos    */
    188  1.5  christos   if (pcap->snapshot <= 0 || pcap->snapshot > MAXIMUM_SNAPLEN)
    189  1.5  christos     pcap->snapshot = MAXIMUM_SNAPLEN;
    190  1.5  christos 
    191  1.1  christos   if (pcap->snapshot < ETH_MIN+8)
    192  1.1  christos       pcap->snapshot = ETH_MIN+8;
    193  1.1  christos 
    194  1.1  christos   if (pcap->snapshot > ETH_MAX)   /* silently accept and truncate large MTUs */
    195  1.1  christos       pcap->snapshot = ETH_MAX;
    196  1.1  christos 
    197  1.1  christos   pcap->linktype          = DLT_EN10MB;  /* !! */
    198  1.1  christos   pcap->cleanup_op        = pcap_cleanup_dos;
    199  1.1  christos   pcap->read_op           = pcap_read_dos;
    200  1.1  christos   pcap->stats_op          = pcap_stats_dos;
    201  1.1  christos   pcap->inject_op         = pcap_sendpacket_dos;
    202  1.1  christos   pcap->setfilter_op      = pcap_setfilter_dos;
    203  1.4  christos   pcap->setdirection_op   = NULL;  /* Not implemented.*/
    204  1.1  christos   pcap->fd                = ++ref_count;
    205  1.1  christos 
    206  1.4  christos   pcap->bufsize = ETH_MAX+100;     /* add some margin */
    207  1.4  christos   pcap->buffer = calloc (pcap->bufsize, 1);
    208  1.4  christos 
    209  1.1  christos   if (pcap->fd == 1)  /* first time we're called */
    210  1.1  christos   {
    211  1.4  christos     if (!init_watt32(pcap, pcap->opt.device, pcap->errbuf) ||
    212  1.4  christos         !first_init(pcap->opt.device, pcap->errbuf, pcap->opt.promisc))
    213  1.1  christos     {
    214  1.5  christos       /* XXX - free pcap->buffer? */
    215  1.1  christos       return (PCAP_ERROR);
    216  1.3  christos     }
    217  1.1  christos     atexit (close_driver);
    218  1.1  christos   }
    219  1.4  christos   else if (stricmp(active_dev->name,pcap->opt.device))
    220  1.1  christos   {
    221  1.7  christos     snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
    222  1.4  christos                    "Cannot use different devices simultaneously "
    223  1.4  christos                    "(`%s' vs. `%s')", active_dev->name, pcap->opt.device);
    224  1.5  christos     /* XXX - free pcap->buffer? */
    225  1.1  christos     return (PCAP_ERROR);
    226  1.1  christos   }
    227  1.1  christos   handle_to_device [pcap->fd-1] = active_dev;
    228  1.1  christos   return (0);
    229  1.1  christos }
    230  1.1  christos 
    231  1.1  christos /*
    232  1.1  christos  * Poll the receiver queue and call the pcap callback-handler
    233  1.1  christos  * with the packet.
    234  1.1  christos  */
    235  1.1  christos static int
    236  1.1  christos pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
    237  1.1  christos {
    238  1.2  christos   struct pcap_dos *pd = p->priv;
    239  1.1  christos   struct pcap_pkthdr pcap;
    240  1.2  christos   struct timeval     now, expiry = { 0,0 };
    241  1.1  christos   int    rx_len = 0;
    242  1.1  christos 
    243  1.2  christos   if (p->opt.timeout > 0)
    244  1.1  christos   {
    245  1.1  christos     gettimeofday2 (&now, NULL);
    246  1.2  christos     expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout;
    247  1.1  christos     expiry.tv_sec  = now.tv_sec;
    248  1.1  christos     while (expiry.tv_usec >= 1000000L)
    249  1.1  christos     {
    250  1.1  christos       expiry.tv_usec -= 1000000L;
    251  1.1  christos       expiry.tv_sec++;
    252  1.1  christos     }
    253  1.1  christos   }
    254  1.1  christos 
    255  1.8  christos   while (!exc_occurred)
    256  1.1  christos   {
    257  1.1  christos     volatile struct device *dev; /* might be reset by sig_handler */
    258  1.1  christos 
    259  1.1  christos     dev = get_device (p->fd);
    260  1.1  christos     if (!dev)
    261  1.1  christos        break;
    262  1.1  christos 
    263  1.1  christos     PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf);
    264  1.1  christos     FLUSHK();
    265  1.1  christos 
    266  1.1  christos     /* If driver has a zero-copy receive facility, peek at the queue,
    267  1.1  christos      * filter it, do the callback and release the buffer.
    268  1.1  christos      */
    269  1.1  christos     if (dev->peek_rx_buf)
    270  1.1  christos     {
    271  1.1  christos       PCAP_ASSERT (dev->release_rx_buf);
    272  1.4  christos       rx_len = (*dev->peek_rx_buf) (&p->buffer);
    273  1.1  christos     }
    274  1.1  christos     else
    275  1.1  christos     {
    276  1.4  christos       rx_len = (*dev->copy_rx_buf) (p->buffer, p->snapshot);
    277  1.1  christos     }
    278  1.1  christos 
    279  1.1  christos     if (rx_len > 0)  /* got a packet */
    280  1.1  christos     {
    281  1.1  christos       mac_count++;
    282  1.1  christos 
    283  1.1  christos       FLUSHK();
    284  1.1  christos 
    285  1.1  christos       pcap.caplen = min (rx_len, p->snapshot);
    286  1.1  christos       pcap.len    = rx_len;
    287  1.1  christos 
    288  1.1  christos       if (callback &&
    289  1.7  christos           (!p->fcode.bf_insns || pcap_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen)))
    290  1.1  christos       {
    291  1.1  christos         filter_count++;
    292  1.1  christos 
    293  1.1  christos         /* Fix-me!! Should be time of arrival. Not time of
    294  1.1  christos          * capture.
    295  1.1  christos          */
    296  1.1  christos         gettimeofday2 (&pcap.ts, NULL);
    297  1.4  christos         (*callback) (data, &pcap, p->buffer);
    298  1.1  christos       }
    299  1.1  christos 
    300  1.1  christos       if (dev->release_rx_buf)
    301  1.4  christos         (*dev->release_rx_buf) (p->buffer);
    302  1.1  christos 
    303  1.1  christos       if (pcap_pkt_debug > 0)
    304  1.1  christos       {
    305  1.1  christos         if (callback == watt32_recv_hook)
    306  1.1  christos              dbug_write ("pcap_recv_hook\n");
    307  1.1  christos         else dbug_write ("pcap_read_op\n");
    308  1.1  christos       }
    309  1.1  christos       FLUSHK();
    310  1.1  christos       return (1);
    311  1.1  christos     }
    312  1.1  christos 
    313  1.4  christos     /* Has "pcap_breakloop()" been called?
    314  1.4  christos      */
    315  1.4  christos     if (p->break_loop) {
    316  1.4  christos       /*
    317  1.4  christos        * Yes - clear the flag that indicates that it
    318  1.4  christos        * has, and return -2 to indicate that we were
    319  1.4  christos        * told to break out of the loop.
    320  1.4  christos        */
    321  1.4  christos       p->break_loop = 0;
    322  1.4  christos       return (-2);
    323  1.4  christos     }
    324  1.4  christos 
    325  1.2  christos     /* If not to wait for a packet or pcap_cleanup_dos() called from
    326  1.1  christos      * e.g. SIGINT handler, exit loop now.
    327  1.1  christos      */
    328  1.2  christos     if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0)
    329  1.1  christos        break;
    330  1.1  christos 
    331  1.1  christos     gettimeofday2 (&now, NULL);
    332  1.1  christos 
    333  1.1  christos     if (timercmp(&now, &expiry, >))
    334  1.1  christos        break;
    335  1.1  christos 
    336  1.1  christos #ifndef DJGPP
    337  1.1  christos     kbhit();    /* a real CPU hog */
    338  1.1  christos #endif
    339  1.1  christos 
    340  1.4  christos     if (pd->wait_proc)
    341  1.4  christos       (*pd->wait_proc)();     /* call yield func */
    342  1.1  christos   }
    343  1.1  christos 
    344  1.1  christos   if (rx_len < 0)            /* receive error */
    345  1.1  christos   {
    346  1.2  christos     pd->stat.ps_drop++;
    347  1.1  christos #ifdef USE_32BIT_DRIVERS
    348  1.1  christos     if (pcap_pkt_debug > 1)
    349  1.1  christos        printk ("pkt-err %s\n", pktInfo.error);
    350  1.1  christos #endif
    351  1.1  christos     return (-1);
    352  1.1  christos   }
    353  1.1  christos   return (0);
    354  1.1  christos }
    355  1.1  christos 
    356  1.1  christos static int
    357  1.1  christos pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
    358  1.1  christos {
    359  1.1  christos   int rc, num = 0;
    360  1.1  christos 
    361  1.7  christos   /*
    362  1.7  christos    * This can conceivably process more than INT_MAX packets,
    363  1.7  christos    * which would overflow the packet count, causing it either
    364  1.7  christos    * to look like a negative number, and thus cause us to
    365  1.7  christos    * return a value that looks like an error, or overflow
    366  1.7  christos    * back into positive territory, and thus cause us to
    367  1.7  christos    * return a too-low count.
    368  1.7  christos    *
    369  1.7  christos    * Therefore, if the packet count is unlimited, we clip
    370  1.7  christos    * it at INT_MAX; this routine is not expected to
    371  1.7  christos    * process packets indefinitely, so that's not an issue.
    372  1.7  christos    */
    373  1.7  christos   if (PACKET_COUNT_IS_UNLIMITED(cnt))
    374  1.7  christos     cnt = INT_MAX;
    375  1.7  christos 
    376  1.7  christos   while (num <= cnt)
    377  1.1  christos   {
    378  1.1  christos     if (p->fd <= 0)
    379  1.1  christos        return (-1);
    380  1.1  christos     rc = pcap_read_one (p, callback, data);
    381  1.1  christos     if (rc > 0)
    382  1.1  christos        num++;
    383  1.1  christos     if (rc < 0)
    384  1.1  christos        break;
    385  1.1  christos     _w32_os_yield();  /* allow SIGINT generation, yield to Win95/NT */
    386  1.1  christos   }
    387  1.1  christos   return (num);
    388  1.1  christos }
    389  1.1  christos 
    390  1.1  christos /*
    391  1.1  christos  * Return network statistics
    392  1.1  christos  */
    393  1.1  christos static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
    394  1.1  christos {
    395  1.1  christos   struct net_device_stats *stats;
    396  1.2  christos   struct pcap_dos         *pd;
    397  1.1  christos   struct device           *dev = p ? get_device(p->fd) : NULL;
    398  1.1  christos 
    399  1.1  christos   if (!dev)
    400  1.1  christos   {
    401  1.1  christos     strcpy (p->errbuf, "illegal pcap handle");
    402  1.1  christos     return (-1);
    403  1.1  christos   }
    404  1.1  christos 
    405  1.1  christos   if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL)
    406  1.1  christos   {
    407  1.1  christos     strcpy (p->errbuf, "device statistics not available");
    408  1.1  christos     return (-1);
    409  1.1  christos   }
    410  1.1  christos 
    411  1.1  christos   FLUSHK();
    412  1.1  christos 
    413  1.2  christos   pd = p->priv;
    414  1.2  christos   pd->stat.ps_recv   = stats->rx_packets;
    415  1.2  christos   pd->stat.ps_drop  += stats->rx_missed_errors;
    416  1.2  christos   pd->stat.ps_ifdrop = stats->rx_dropped +  /* queue full */
    417  1.1  christos                          stats->rx_errors;    /* HW errors */
    418  1.1  christos   if (ps)
    419  1.2  christos      *ps = pd->stat;
    420  1.1  christos 
    421  1.1  christos   return (0);
    422  1.1  christos }
    423  1.1  christos 
    424  1.1  christos /*
    425  1.1  christos  * Return detailed network/device statistics.
    426  1.1  christos  * May be called after 'dev->close' is called.
    427  1.1  christos  */
    428  1.1  christos int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se)
    429  1.1  christos {
    430  1.1  christos   struct device *dev = p ? get_device (p->fd) : NULL;
    431  1.1  christos 
    432  1.1  christos   if (!dev || !dev->get_stats)
    433  1.1  christos   {
    434  1.6  christos     pcap_strlcpy (p->errbuf, "detailed device statistics not available",
    435  1.1  christos              PCAP_ERRBUF_SIZE);
    436  1.1  christos     return (-1);
    437  1.1  christos   }
    438  1.1  christos 
    439  1.1  christos   if (!strnicmp(dev->name,"pkt",3))
    440  1.1  christos   {
    441  1.6  christos     pcap_strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
    442  1.1  christos              PCAP_ERRBUF_SIZE);
    443  1.1  christos     return (-1);
    444  1.3  christos   }
    445  1.1  christos   memcpy (se, (*dev->get_stats)(dev), sizeof(*se));
    446  1.1  christos   return (0);
    447  1.1  christos }
    448  1.1  christos 
    449  1.1  christos /*
    450  1.1  christos  * Simply store the filter-code for the pcap_read_dos() callback
    451  1.1  christos  * Some day the filter-code could be handed down to the active
    452  1.1  christos  * device (pkt_rx1.s or 32-bit device interrupt handler).
    453  1.1  christos  */
    454  1.1  christos static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp)
    455  1.1  christos {
    456  1.1  christos   if (!p)
    457  1.1  christos      return (-1);
    458  1.1  christos   p->fcode = *fp;
    459  1.1  christos   return (0);
    460  1.1  christos }
    461  1.1  christos 
    462  1.1  christos /*
    463  1.1  christos  * Return # of packets received in pcap_read_dos()
    464  1.1  christos  */
    465  1.1  christos u_long pcap_mac_packets (void)
    466  1.1  christos {
    467  1.1  christos   return (mac_count);
    468  1.1  christos }
    469  1.1  christos 
    470  1.1  christos /*
    471  1.1  christos  * Return # of packets passed through filter in pcap_read_dos()
    472  1.1  christos  */
    473  1.1  christos u_long pcap_filter_packets (void)
    474  1.1  christos {
    475  1.1  christos   return (filter_count);
    476  1.1  christos }
    477  1.1  christos 
    478  1.1  christos /*
    479  1.1  christos  * Close pcap device. Not called for offline captures.
    480  1.1  christos  */
    481  1.1  christos static void pcap_cleanup_dos (pcap_t *p)
    482  1.1  christos {
    483  1.2  christos   struct pcap_dos *pd;
    484  1.2  christos 
    485  1.8  christos   if (!exc_occurred)
    486  1.1  christos   {
    487  1.2  christos     pd = p->priv;
    488  1.1  christos     if (pcap_stats(p,NULL) < 0)
    489  1.2  christos        pd->stat.ps_drop = 0;
    490  1.1  christos     if (!get_device(p->fd))
    491  1.1  christos        return;
    492  1.1  christos 
    493  1.1  christos     handle_to_device [p->fd-1] = NULL;
    494  1.1  christos     p->fd = 0;
    495  1.1  christos     if (ref_count > 0)
    496  1.1  christos         ref_count--;
    497  1.1  christos     if (ref_count > 0)
    498  1.1  christos        return;
    499  1.1  christos   }
    500  1.1  christos   close_driver();
    501  1.5  christos   /* XXX - call pcap_cleanup_live_common? */
    502  1.1  christos }
    503  1.1  christos 
    504  1.1  christos /*
    505  1.1  christos  * Return the name of the 1st network interface,
    506  1.1  christos  * or NULL if none can be found.
    507  1.1  christos  */
    508  1.1  christos char *pcap_lookupdev (char *ebuf)
    509  1.1  christos {
    510  1.1  christos   struct device *dev;
    511  1.1  christos 
    512  1.1  christos #ifdef USE_32BIT_DRIVERS
    513  1.1  christos   init_32bit();
    514  1.1  christos #endif
    515  1.1  christos 
    516  1.1  christos   for (dev = (struct device*)dev_base; dev; dev = dev->next)
    517  1.1  christos   {
    518  1.1  christos     PCAP_ASSERT (dev->probe);
    519  1.1  christos 
    520  1.1  christos     if ((*dev->probe)(dev))
    521  1.1  christos     {
    522  1.1  christos       FLUSHK();
    523  1.1  christos       probed_dev = (struct device*) dev; /* remember last probed device */
    524  1.1  christos       return (char*) dev->name;
    525  1.1  christos     }
    526  1.1  christos   }
    527  1.1  christos 
    528  1.1  christos   if (ebuf)
    529  1.1  christos      strcpy (ebuf, "No driver found");
    530  1.1  christos   return (NULL);
    531  1.1  christos }
    532  1.1  christos 
    533  1.1  christos /*
    534  1.1  christos  * Gets localnet & netmask from Watt-32.
    535  1.1  christos  */
    536  1.1  christos int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
    537  1.1  christos                     bpf_u_int32 *netmask, char *errbuf)
    538  1.1  christos {
    539  1.4  christos   DWORD mask, net;
    540  1.4  christos 
    541  1.1  christos   if (!_watt_is_init)
    542  1.1  christos   {
    543  1.1  christos     strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
    544  1.1  christos                     "called first");
    545  1.1  christos     return (-1);
    546  1.1  christos   }
    547  1.1  christos 
    548  1.4  christos   mask  = _w32_sin_mask;
    549  1.4  christos   net = my_ip_addr & mask;
    550  1.4  christos   if (net == 0)
    551  1.1  christos   {
    552  1.1  christos     if (IN_CLASSA(*netmask))
    553  1.4  christos        net = IN_CLASSA_NET;
    554  1.1  christos     else if (IN_CLASSB(*netmask))
    555  1.4  christos        net = IN_CLASSB_NET;
    556  1.1  christos     else if (IN_CLASSC(*netmask))
    557  1.4  christos        net = IN_CLASSC_NET;
    558  1.1  christos     else
    559  1.1  christos     {
    560  1.7  christos       snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask);
    561  1.1  christos       return (-1);
    562  1.1  christos     }
    563  1.1  christos   }
    564  1.4  christos   *localnet = htonl (net);
    565  1.4  christos   *netmask = htonl (mask);
    566  1.4  christos 
    567  1.1  christos   ARGSUSED (device);
    568  1.1  christos   return (0);
    569  1.3  christos }
    570  1.1  christos 
    571  1.1  christos /*
    572  1.1  christos  * Get a list of all interfaces that are present and that we probe okay.
    573  1.1  christos  * Returns -1 on error, 0 otherwise.
    574  1.7  christos  * The list may be NULL empty if no interfaces were up and could be opened.
    575  1.1  christos  */
    576  1.5  christos int pcap_platform_finddevs  (pcap_if_list_t *devlistp, char *errbuf)
    577  1.1  christos {
    578  1.1  christos   struct device     *dev;
    579  1.5  christos   pcap_if_t *curdev;
    580  1.5  christos #if 0   /* Pkt drivers should have no addresses */
    581  1.4  christos   struct sockaddr_in sa_ll_1, sa_ll_2;
    582  1.1  christos   struct sockaddr   *addr, *netmask, *broadaddr, *dstaddr;
    583  1.5  christos #endif
    584  1.1  christos   int       ret = 0;
    585  1.5  christos   int       found = 0;
    586  1.1  christos 
    587  1.1  christos   for (dev = (struct device*)dev_base; dev; dev = dev->next)
    588  1.1  christos   {
    589  1.1  christos     PCAP_ASSERT (dev->probe);
    590  1.1  christos 
    591  1.1  christos     if (!(*dev->probe)(dev))
    592  1.1  christos        continue;
    593  1.1  christos 
    594  1.1  christos     PCAP_ASSERT (dev->close);  /* set by probe routine */
    595  1.1  christos     FLUSHK();
    596  1.1  christos     (*dev->close) (dev);
    597  1.1  christos 
    598  1.5  christos     /*
    599  1.5  christos      * XXX - find out whether it's up or running?  Does that apply here?
    600  1.5  christos      * Can we find out if anything's plugged into the adapter, if it's
    601  1.5  christos      * a wired device, and set PCAP_IF_CONNECTION_STATUS_CONNECTED
    602  1.5  christos      * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
    603  1.5  christos      */
    604  1.8  christos     if ((curdev = pcap_add_dev(devlistp, dev->name, 0,
    605  1.5  christos                 dev->long_name, errbuf)) == NULL)
    606  1.5  christos     {
    607  1.5  christos       ret = -1;
    608  1.5  christos       break;
    609  1.5  christos     }
    610  1.5  christos     found = 1;
    611  1.5  christos #if 0   /* Pkt drivers should have no addresses */
    612  1.1  christos     memset (&sa_ll_1, 0, sizeof(sa_ll_1));
    613  1.1  christos     memset (&sa_ll_2, 0, sizeof(sa_ll_2));
    614  1.4  christos     sa_ll_1.sin_family = AF_INET;
    615  1.4  christos     sa_ll_2.sin_family = AF_INET;
    616  1.1  christos 
    617  1.1  christos     addr      = (struct sockaddr*) &sa_ll_1;
    618  1.1  christos     netmask   = (struct sockaddr*) &sa_ll_1;
    619  1.1  christos     dstaddr   = (struct sockaddr*) &sa_ll_1;
    620  1.1  christos     broadaddr = (struct sockaddr*) &sa_ll_2;
    621  1.4  christos     memset (&sa_ll_2.sin_addr, 0xFF, sizeof(sa_ll_2.sin_addr));
    622  1.1  christos 
    623  1.8  christos     if (pcap_add_addr_to_dev(curdev, addr, sizeof(*addr),
    624  1.5  christos                         netmask, sizeof(*netmask),
    625  1.5  christos                         broadaddr, sizeof(*broadaddr),
    626  1.5  christos                         dstaddr, sizeof(*dstaddr), errbuf) < 0)
    627  1.1  christos     {
    628  1.1  christos       ret = -1;
    629  1.1  christos       break;
    630  1.1  christos     }
    631  1.4  christos #endif
    632  1.1  christos   }
    633  1.1  christos 
    634  1.5  christos   if (ret == 0 && !found)
    635  1.1  christos      strcpy (errbuf, "No drivers found");
    636  1.1  christos 
    637  1.1  christos   return (ret);
    638  1.1  christos }
    639  1.1  christos 
    640  1.1  christos /*
    641  1.1  christos  * pcap_assert() is mainly used for debugging
    642  1.1  christos  */
    643  1.1  christos void pcap_assert (const char *what, const char *file, unsigned line)
    644  1.1  christos {
    645  1.1  christos   FLUSHK();
    646  1.1  christos   fprintf (stderr, "%s (%u): Assertion \"%s\" failed\n",
    647  1.1  christos            file, line, what);
    648  1.1  christos   close_driver();
    649  1.1  christos   _exit (-1);
    650  1.1  christos }
    651  1.1  christos 
    652  1.1  christos /*
    653  1.1  christos  * For pcap_offline_read(): wait and yield between printing packets
    654  1.1  christos  * to simulate the pace packets where actually recorded.
    655  1.1  christos  */
    656  1.1  christos void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
    657  1.1  christos {
    658  1.1  christos   if (p)
    659  1.1  christos   {
    660  1.4  christos     struct pcap_dos *pd = p->priv;
    661  1.4  christos 
    662  1.4  christos     pd->wait_proc  = yield;
    663  1.4  christos     p->opt.timeout = wait;
    664  1.1  christos   }
    665  1.1  christos }
    666  1.1  christos 
    667  1.1  christos /*
    668  1.8  christos  * Initialize a named network device.
    669  1.1  christos  */
    670  1.1  christos static struct device *
    671  1.1  christos open_driver (const char *dev_name, char *ebuf, int promisc)
    672  1.1  christos {
    673  1.1  christos   struct device *dev;
    674  1.1  christos 
    675  1.1  christos   for (dev = (struct device*)dev_base; dev; dev = dev->next)
    676  1.1  christos   {
    677  1.1  christos     PCAP_ASSERT (dev->name);
    678  1.1  christos 
    679  1.1  christos     if (strcmp (dev_name,dev->name))
    680  1.1  christos        continue;
    681  1.1  christos 
    682  1.1  christos     if (!probed_dev)   /* user didn't call pcap_lookupdev() first */
    683  1.1  christos     {
    684  1.1  christos       PCAP_ASSERT (dev->probe);
    685  1.1  christos 
    686  1.1  christos       if (!(*dev->probe)(dev))    /* call the xx_probe() function */
    687  1.1  christos       {
    688  1.7  christos         snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to detect device `%s'", dev_name);
    689  1.1  christos         return (NULL);
    690  1.1  christos       }
    691  1.1  christos       probed_dev = dev;  /* device is probed okay and may be used */
    692  1.1  christos     }
    693  1.1  christos     else if (dev != probed_dev)
    694  1.1  christos     {
    695  1.1  christos       goto not_probed;
    696  1.1  christos     }
    697  1.1  christos 
    698  1.1  christos     FLUSHK();
    699  1.1  christos 
    700  1.1  christos     /* Select what traffic to receive
    701  1.1  christos      */
    702  1.1  christos     if (promisc)
    703  1.1  christos          dev->flags |=  (IFF_ALLMULTI | IFF_PROMISC);
    704  1.1  christos     else dev->flags &= ~(IFF_ALLMULTI | IFF_PROMISC);
    705  1.1  christos 
    706  1.1  christos     PCAP_ASSERT (dev->open);
    707  1.1  christos 
    708  1.1  christos     if (!(*dev->open)(dev))
    709  1.1  christos     {
    710  1.7  christos       snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name);
    711  1.1  christos       if (pktInfo.error && !strncmp(dev->name,"pkt",3))
    712  1.1  christos       {
    713  1.1  christos         strcat (ebuf, ": ");
    714  1.1  christos         strcat (ebuf, pktInfo.error);
    715  1.1  christos       }
    716  1.1  christos       return (NULL);
    717  1.1  christos     }
    718  1.1  christos 
    719  1.7  christos     /* Some devices need this to operate in promiscuous mode
    720  1.1  christos      */
    721  1.1  christos     if (promisc && dev->set_multicast_list)
    722  1.1  christos        (*dev->set_multicast_list) (dev);
    723  1.1  christos 
    724  1.1  christos     active_dev = dev;   /* remember our active device */
    725  1.1  christos     break;
    726  1.1  christos   }
    727  1.1  christos 
    728  1.1  christos   /* 'dev_name' not matched in 'dev_base' list.
    729  1.1  christos    */
    730  1.1  christos   if (!dev)
    731  1.1  christos   {
    732  1.7  christos     snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name);
    733  1.1  christos     return (NULL);
    734  1.1  christos   }
    735  1.1  christos 
    736  1.1  christos not_probed:
    737  1.1  christos   if (!probed_dev)
    738  1.1  christos   {
    739  1.7  christos     snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name);
    740  1.1  christos     return (NULL);
    741  1.1  christos   }
    742  1.1  christos   return (dev);
    743  1.1  christos }
    744  1.1  christos 
    745  1.1  christos /*
    746  1.8  christos  * Deinitialize MAC driver.
    747  1.1  christos  * Set receive mode back to default mode.
    748  1.1  christos  */
    749  1.1  christos static void close_driver (void)
    750  1.1  christos {
    751  1.1  christos   /* !!todo: loop over all 'handle_to_device[]' ? */
    752  1.1  christos   struct device *dev = active_dev;
    753  1.1  christos 
    754  1.1  christos   if (dev && dev->close)
    755  1.1  christos   {
    756  1.1  christos     (*dev->close) (dev);
    757  1.1  christos     FLUSHK();
    758  1.1  christos   }
    759  1.1  christos 
    760  1.1  christos   active_dev = NULL;
    761  1.1  christos 
    762  1.1  christos #ifdef USE_32BIT_DRIVERS
    763  1.1  christos   if (rx_pool)
    764  1.1  christos   {
    765  1.1  christos     k_free (rx_pool);
    766  1.1  christos     rx_pool = NULL;
    767  1.1  christos   }
    768  1.1  christos   if (dev)
    769  1.1  christos      pcibios_exit();
    770  1.1  christos #endif
    771  1.1  christos }
    772  1.1  christos 
    773  1.1  christos 
    774  1.1  christos #ifdef __DJGPP__
    775  1.1  christos static void setup_signals (void (*handler)(int))
    776  1.1  christos {
    777  1.1  christos   signal (SIGSEGV,handler);
    778  1.1  christos   signal (SIGILL, handler);
    779  1.1  christos   signal (SIGFPE, handler);
    780  1.1  christos }
    781  1.1  christos 
    782  1.1  christos static void exc_handler (int sig)
    783  1.1  christos {
    784  1.1  christos #ifdef USE_32BIT_DRIVERS
    785  1.1  christos   if (active_dev->irq > 0)    /* excludes IRQ 0 */
    786  1.1  christos   {
    787  1.1  christos     disable_irq (active_dev->irq);
    788  1.1  christos     irq_eoi_cmd (active_dev->irq);
    789  1.1  christos     _printk_safe = 1;
    790  1.1  christos   }
    791  1.1  christos #endif
    792  1.1  christos 
    793  1.1  christos   switch (sig)
    794  1.1  christos   {
    795  1.1  christos     case SIGSEGV:
    796  1.1  christos          fputs ("Catching SIGSEGV.\n", stderr);
    797  1.1  christos          break;
    798  1.1  christos     case SIGILL:
    799  1.1  christos          fputs ("Catching SIGILL.\n", stderr);
    800  1.1  christos          break;
    801  1.1  christos     case SIGFPE:
    802  1.1  christos          _fpreset();
    803  1.1  christos          fputs ("Catching SIGFPE.\n", stderr);
    804  1.1  christos          break;
    805  1.1  christos     default:
    806  1.1  christos          fprintf (stderr, "Catching signal %d.\n", sig);
    807  1.1  christos   }
    808  1.8  christos   exc_occurred = 1;
    809  1.4  christos   close_driver();
    810  1.1  christos }
    811  1.1  christos #endif  /* __DJGPP__ */
    812  1.1  christos 
    813  1.1  christos 
    814  1.1  christos /*
    815  1.1  christos  * Open the pcap device for the first client calling pcap_activate()
    816  1.1  christos  */
    817  1.1  christos static int first_init (const char *name, char *ebuf, int promisc)
    818  1.1  christos {
    819  1.1  christos   struct device *dev;
    820  1.1  christos 
    821  1.1  christos #ifdef USE_32BIT_DRIVERS
    822  1.1  christos   rx_pool = k_calloc (RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE);
    823  1.1  christos   if (!rx_pool)
    824  1.1  christos   {
    825  1.1  christos     strcpy (ebuf, "Not enough memory (Rx pool)");
    826  1.1  christos     return (0);
    827  1.1  christos   }
    828  1.1  christos #endif
    829  1.1  christos 
    830  1.1  christos #ifdef __DJGPP__
    831  1.1  christos   setup_signals (exc_handler);
    832  1.1  christos #endif
    833  1.1  christos 
    834  1.1  christos #ifdef USE_32BIT_DRIVERS
    835  1.1  christos   init_32bit();
    836  1.1  christos #endif
    837  1.1  christos 
    838  1.1  christos   dev = open_driver (name, ebuf, promisc);
    839  1.1  christos   if (!dev)
    840  1.1  christos   {
    841  1.1  christos #ifdef USE_32BIT_DRIVERS
    842  1.1  christos     k_free (rx_pool);
    843  1.1  christos     rx_pool = NULL;
    844  1.1  christos #endif
    845  1.1  christos 
    846  1.1  christos #ifdef __DJGPP__
    847  1.1  christos     setup_signals (SIG_DFL);
    848  1.1  christos #endif
    849  1.1  christos     return (0);
    850  1.1  christos   }
    851  1.1  christos 
    852  1.1  christos #ifdef USE_32BIT_DRIVERS
    853  1.1  christos   /*
    854  1.1  christos    * If driver is NOT a 16-bit "pkt/ndis" driver (having a 'copy_rx_buf'
    855  1.8  christos    * set in it's probe handler), initialize near-memory ring-buffer for
    856  1.1  christos    * the 32-bit device.
    857  1.1  christos    */
    858  1.1  christos   if (dev->copy_rx_buf == NULL)
    859  1.1  christos   {
    860  1.1  christos     dev->get_rx_buf     = get_rxbuf;
    861  1.1  christos     dev->peek_rx_buf    = peek_rxbuf;
    862  1.1  christos     dev->release_rx_buf = release_rxbuf;
    863  1.1  christos     pktq_init (&dev->queue, RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE, rx_pool);
    864  1.1  christos   }
    865  1.1  christos #endif
    866  1.1  christos   return (1);
    867  1.1  christos }
    868  1.1  christos 
    869  1.1  christos #ifdef USE_32BIT_DRIVERS
    870  1.1  christos static void init_32bit (void)
    871  1.1  christos {
    872  1.1  christos   static int init_pci = 0;
    873  1.1  christos 
    874  1.1  christos   if (!_printk_file)
    875  1.1  christos      _printk_init (64*1024, NULL); /* calls atexit(printk_exit) */
    876  1.1  christos 
    877  1.1  christos   if (!init_pci)
    878  1.1  christos      (void)pci_init();             /* init BIOS32+PCI interface */
    879  1.1  christos   init_pci = 1;
    880  1.1  christos }
    881  1.1  christos #endif
    882  1.1  christos 
    883  1.1  christos 
    884  1.1  christos /*
    885  1.1  christos  * Hook functions for using Watt-32 together with pcap
    886  1.1  christos  */
    887  1.1  christos static char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */
    888  1.1  christos static WORD etype;
    889  1.1  christos static pcap_t pcap_save;
    890  1.1  christos 
    891  1.1  christos static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
    892  1.1  christos                               const u_char *buf)
    893  1.1  christos {
    894  1.1  christos   /* Fix me: assumes Ethernet II only */
    895  1.1  christos   struct ether_header *ep = (struct ether_header*) buf;
    896  1.1  christos 
    897  1.1  christos   memcpy (rxbuf, buf, pcap->caplen);
    898  1.1  christos   etype = ep->ether_type;
    899  1.1  christos   ARGSUSED (dummy);
    900  1.1  christos }
    901  1.1  christos 
    902  1.1  christos #if (WATTCP_VER >= 0x0224)
    903  1.1  christos /*
    904  1.1  christos  * This function is used by Watt-32 to poll for a packet.
    905  1.1  christos  * i.e. it's set to bypass _eth_arrived()
    906  1.1  christos  */
    907  1.1  christos static void *pcap_recv_hook (WORD *type)
    908  1.1  christos {
    909  1.1  christos   int len = pcap_read_dos (&pcap_save, 1, watt32_recv_hook, NULL);
    910  1.1  christos 
    911  1.1  christos   if (len < 0)
    912  1.1  christos      return (NULL);
    913  1.1  christos 
    914  1.1  christos   *type = etype;
    915  1.1  christos   return (void*) &rxbuf;
    916  1.1  christos }
    917  1.1  christos 
    918  1.1  christos /*
    919  1.1  christos  * This function is called by Watt-32 (via _eth_xmit_hook).
    920  1.1  christos  * If dbug_init() was called, we should trace packets sent.
    921  1.1  christos  */
    922  1.1  christos static int pcap_xmit_hook (const void *buf, unsigned len)
    923  1.1  christos {
    924  1.1  christos   int rc = 0;
    925  1.1  christos 
    926  1.1  christos   if (pcap_pkt_debug > 0)
    927  1.1  christos      dbug_write ("pcap_xmit_hook: ");
    928  1.1  christos 
    929  1.1  christos   if (active_dev && active_dev->xmit)
    930  1.1  christos      if ((*active_dev->xmit) (active_dev, buf, len) > 0)
    931  1.1  christos         rc = len;
    932  1.1  christos 
    933  1.1  christos   if (pcap_pkt_debug > 0)
    934  1.1  christos      dbug_write (rc ? "ok\n" : "fail\n");
    935  1.1  christos   return (rc);
    936  1.1  christos }
    937  1.1  christos #endif
    938  1.1  christos 
    939  1.1  christos static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len)
    940  1.1  christos {
    941  1.1  christos   struct device *dev = p ? get_device(p->fd) : NULL;
    942  1.1  christos 
    943  1.1  christos   if (!dev || !dev->xmit)
    944  1.1  christos      return (-1);
    945  1.1  christos   return (*dev->xmit) (dev, buf, len);
    946  1.1  christos }
    947  1.1  christos 
    948  1.1  christos /*
    949  1.1  christos  * This function is called by Watt-32 in tcp_post_init().
    950  1.1  christos  * We should prevent Watt-32 from using BOOTP/DHCP/RARP etc.
    951  1.1  christos  */
    952  1.1  christos static void (*prev_post_hook) (void);
    953  1.1  christos 
    954  1.1  christos static void pcap_init_hook (void)
    955  1.1  christos {
    956  1.1  christos   _w32__bootp_on = _w32__dhcp_on = _w32__rarp_on = 0;
    957  1.1  christos   _w32__do_mask_req = 0;
    958  1.1  christos   _w32_dynamic_host = 0;
    959  1.1  christos   if (prev_post_hook)
    960  1.1  christos     (*prev_post_hook)();
    961  1.1  christos }
    962  1.1  christos 
    963  1.1  christos /*
    964  1.7  christos  * Suppress PRINT message from Watt-32's sock_init()
    965  1.1  christos  */
    966  1.1  christos static void null_print (void) {}
    967  1.1  christos 
    968  1.1  christos /*
    969  1.1  christos  * To use features of Watt-32 (netdb functions and socket etc.)
    970  1.1  christos  * we must call sock_init(). But we set various hooks to prevent
    971  1.1  christos  * using normal PKTDRVR functions in pcpkt.c. This should hopefully
    972  1.1  christos  * make Watt-32 and pcap co-operate.
    973  1.1  christos  */
    974  1.1  christos static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
    975  1.1  christos {
    976  1.1  christos   char *env;
    977  1.1  christos   int   rc, MTU, has_ip_addr;
    978  1.1  christos   int   using_pktdrv = 1;
    979  1.1  christos 
    980  1.1  christos   /* If user called sock_init() first, we need to reinit in
    981  1.1  christos    * order to open debug/trace-file properly
    982  1.1  christos    */
    983  1.1  christos   if (_watt_is_init)
    984  1.1  christos      sock_exit();
    985  1.1  christos 
    986  1.4  christos   env = getenv ("PCAP_TRACE");
    987  1.1  christos   if (env && atoi(env) > 0 &&
    988  1.1  christos       pcap_pkt_debug < 0)   /* if not already set */
    989  1.1  christos   {
    990  1.1  christos     dbug_init();
    991  1.1  christos     pcap_pkt_debug = atoi (env);
    992  1.1  christos   }
    993  1.1  christos 
    994  1.1  christos   _watt_do_exit      = 0;    /* prevent sock_init() calling exit() */
    995  1.1  christos   prev_post_hook     = _w32_usr_post_init;
    996  1.1  christos   _w32_usr_post_init = pcap_init_hook;
    997  1.1  christos   _w32_print_hook    = null_print;
    998  1.1  christos 
    999  1.1  christos   if (dev_name && strncmp(dev_name,"pkt",3))
   1000  1.1  christos      using_pktdrv = FALSE;
   1001  1.1  christos 
   1002  1.1  christos   rc = sock_init();
   1003  1.1  christos   has_ip_addr = (rc != 8);  /* IP-address assignment failed */
   1004  1.1  christos 
   1005  1.1  christos   /* if pcap is using a 32-bit driver w/o a pktdrvr loaded, we
   1006  1.8  christos    * just pretend Watt-32 is initialized okay.
   1007  1.1  christos    *
   1008  1.1  christos    * !! fix-me: The Watt-32 config isn't done if no pktdrvr
   1009  1.1  christos    *            was found. In that case my_ip_addr + sin_mask
   1010  1.1  christos    *            have default values. Should be taken from another
   1011  1.1  christos    *            ini-file/environment in any case (ref. tcpdump.ini)
   1012  1.1  christos    */
   1013  1.3  christos   _watt_is_init = 1;
   1014  1.1  christos 
   1015  1.1  christos   if (!using_pktdrv || !has_ip_addr)  /* for now .... */
   1016  1.1  christos   {
   1017  1.1  christos     static const char myip[] = "192.168.0.1";
   1018  1.1  christos     static const char mask[] = "255.255.255.0";
   1019  1.1  christos 
   1020  1.1  christos     printf ("Just guessing, using IP %s and netmask %s\n", myip, mask);
   1021  1.1  christos     my_ip_addr    = aton (myip);
   1022  1.1  christos     _w32_sin_mask = aton (mask);
   1023  1.1  christos   }
   1024  1.1  christos   else if (rc && using_pktdrv)
   1025  1.1  christos   {
   1026  1.7  christos     snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc);
   1027  1.1  christos     return (0);
   1028  1.1  christos   }
   1029  1.1  christos 
   1030  1.1  christos   /* Set recv-hook for peeking in _eth_arrived().
   1031  1.1  christos    */
   1032  1.1  christos #if (WATTCP_VER >= 0x0224)
   1033  1.1  christos   _eth_recv_hook = pcap_recv_hook;
   1034  1.1  christos   _eth_xmit_hook = pcap_xmit_hook;
   1035  1.1  christos #endif
   1036  1.1  christos 
   1037  1.1  christos   /* Free the pkt-drvr handle allocated in pkt_init().
   1038  1.1  christos    * The above hooks should thus use the handle reopened in open_driver()
   1039  1.1  christos    */
   1040  1.1  christos   if (using_pktdrv)
   1041  1.1  christos   {
   1042  1.1  christos     _eth_release();
   1043  1.1  christos /*  _eth_is_init = 1; */  /* hack to get Rx/Tx-hooks in Watt-32 working */
   1044  1.1  christos   }
   1045  1.1  christos 
   1046  1.1  christos   memcpy (&pcap_save, pcap, sizeof(pcap_save));
   1047  1.1  christos   MTU = pkt_get_mtu();
   1048  1.1  christos   pcap_save.fcode.bf_insns = NULL;
   1049  1.1  christos   pcap_save.linktype       = _eth_get_hwtype (NULL, NULL);
   1050  1.1  christos   pcap_save.snapshot       = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */
   1051  1.1  christos 
   1052  1.1  christos   /* prevent use of resolve() and resolve_ip()
   1053  1.1  christos    */
   1054  1.1  christos   last_nameserver = 0;
   1055  1.1  christos   return (1);
   1056  1.1  christos }
   1057  1.1  christos 
   1058  1.1  christos int EISA_bus = 0;  /* Where is natural place for this? */
   1059  1.1  christos 
   1060  1.1  christos /*
   1061  1.1  christos  * Application config hooks to set various driver parameters.
   1062  1.1  christos  */
   1063  1.1  christos 
   1064  1.1  christos static const struct config_table debug_tab[] = {
   1065  1.1  christos             { "PKT.DEBUG",       ARG_ATOI,   &pcap_pkt_debug    },
   1066  1.1  christos             { "PKT.VECTOR",      ARG_ATOX_W, NULL               },
   1067  1.1  christos             { "NDIS.DEBUG",      ARG_ATOI,   NULL               },
   1068  1.1  christos #ifdef USE_32BIT_DRIVERS
   1069  1.1  christos             { "3C503.DEBUG",     ARG_ATOI,   &ei_debug          },
   1070  1.1  christos             { "3C503.IO_BASE",   ARG_ATOX_W, &el2_dev.base_addr },
   1071  1.1  christos             { "3C503.MEMORY",    ARG_ATOX_W, &el2_dev.mem_start },
   1072  1.1  christos             { "3C503.IRQ",       ARG_ATOI,   &el2_dev.irq       },
   1073  1.1  christos             { "3C505.DEBUG",     ARG_ATOI,   NULL               },
   1074  1.1  christos             { "3C505.BASE",      ARG_ATOX_W, NULL               },
   1075  1.1  christos             { "3C507.DEBUG",     ARG_ATOI,   NULL               },
   1076  1.1  christos             { "3C509.DEBUG",     ARG_ATOI,   &el3_debug         },
   1077  1.1  christos             { "3C509.ILOOP",     ARG_ATOI,   &el3_max_loop      },
   1078  1.1  christos             { "3C529.DEBUG",     ARG_ATOI,   NULL               },
   1079  1.1  christos             { "3C575.DEBUG",     ARG_ATOI,   &debug_3c575       },
   1080  1.1  christos             { "3C59X.DEBUG",     ARG_ATOI,   &vortex_debug      },
   1081  1.1  christos             { "3C59X.IFACE0",    ARG_ATOI,   &vortex_options[0] },
   1082  1.1  christos             { "3C59X.IFACE1",    ARG_ATOI,   &vortex_options[1] },
   1083  1.1  christos             { "3C59X.IFACE2",    ARG_ATOI,   &vortex_options[2] },
   1084  1.1  christos             { "3C59X.IFACE3",    ARG_ATOI,   &vortex_options[3] },
   1085  1.1  christos             { "3C90X.DEBUG",     ARG_ATOX_W, &tc90xbc_debug     },
   1086  1.1  christos             { "ACCT.DEBUG",      ARG_ATOI,   &ethpk_debug       },
   1087  1.1  christos             { "CS89.DEBUG",      ARG_ATOI,   &cs89_debug        },
   1088  1.1  christos             { "RTL8139.DEBUG",   ARG_ATOI,   &rtl8139_debug     },
   1089  1.1  christos         /*  { "RTL8139.FDUPLEX", ARG_ATOI,   &rtl8139_options   }, */
   1090  1.1  christos             { "SMC.DEBUG",       ARG_ATOI,   &ei_debug          },
   1091  1.1  christos         /*  { "E100.DEBUG",      ARG_ATOI,   &e100_debug        }, */
   1092  1.1  christos             { "PCI.DEBUG",       ARG_ATOI,   &pci_debug         },
   1093  1.1  christos             { "BIOS32.DEBUG",    ARG_ATOI,   &bios32_debug      },
   1094  1.1  christos             { "IRQ.DEBUG",       ARG_ATOI,   &irq_debug         },
   1095  1.1  christos             { "TIMER.IRQ",       ARG_ATOI,   &timer_irq         },
   1096  1.1  christos #endif
   1097  1.1  christos             { NULL }
   1098  1.1  christos           };
   1099  1.1  christos 
   1100  1.1  christos /*
   1101  1.1  christos  * pcap_config_hook() is an extension to application's config
   1102  1.1  christos  * handling. Uses Watt-32's config-table function.
   1103  1.1  christos  */
   1104  1.4  christos int pcap_config_hook (const char *keyword, const char *value)
   1105  1.1  christos {
   1106  1.4  christos   return parse_config_table (debug_tab, NULL, keyword, value);
   1107  1.1  christos }
   1108  1.1  christos 
   1109  1.1  christos /*
   1110  1.1  christos  * Linked list of supported devices
   1111  1.1  christos  */
   1112  1.1  christos struct device       *active_dev = NULL;      /* the device we have opened */
   1113  1.1  christos struct device       *probed_dev = NULL;      /* the device we have probed */
   1114  1.1  christos const struct device *dev_base   = &pkt_dev;  /* list of network devices */
   1115  1.1  christos 
   1116  1.1  christos /*
   1117  1.1  christos  * PKTDRVR device functions
   1118  1.1  christos  */
   1119  1.1  christos int pcap_pkt_debug = -1;
   1120  1.1  christos 
   1121  1.1  christos static void pkt_close (struct device *dev)
   1122  1.1  christos {
   1123  1.1  christos   BOOL okay = PktExitDriver();
   1124  1.1  christos 
   1125  1.1  christos   if (pcap_pkt_debug > 1)
   1126  1.1  christos      fprintf (stderr, "pkt_close(): %d\n", okay);
   1127  1.1  christos 
   1128  1.1  christos   if (dev->priv)
   1129  1.1  christos      free (dev->priv);
   1130  1.1  christos   dev->priv = NULL;
   1131  1.1  christos }
   1132  1.1  christos 
   1133  1.1  christos static int pkt_open (struct device *dev)
   1134  1.1  christos {
   1135  1.1  christos   PKT_RX_MODE mode;
   1136  1.1  christos 
   1137  1.1  christos   if (dev->flags & IFF_PROMISC)
   1138  1.1  christos        mode = PDRX_ALL_PACKETS;
   1139  1.1  christos   else mode = PDRX_BROADCAST;
   1140  1.1  christos 
   1141  1.1  christos   if (!PktInitDriver(mode))
   1142  1.1  christos      return (0);
   1143  1.3  christos 
   1144  1.1  christos   PktResetStatistics (pktInfo.handle);
   1145  1.1  christos   PktQueueBusy (FALSE);
   1146  1.1  christos   return (1);
   1147  1.1  christos }
   1148  1.1  christos 
   1149  1.1  christos static int pkt_xmit (struct device *dev, const void *buf, int len)
   1150  1.1  christos {
   1151  1.1  christos   struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
   1152  1.1  christos 
   1153  1.1  christos   if (pcap_pkt_debug > 0)
   1154  1.1  christos      dbug_write ("pcap_xmit\n");
   1155  1.1  christos 
   1156  1.1  christos   if (!PktTransmit(buf,len))
   1157  1.1  christos   {
   1158  1.1  christos     stats->tx_errors++;
   1159  1.1  christos     return (0);
   1160  1.1  christos   }
   1161  1.1  christos   return (len);
   1162  1.1  christos }
   1163  1.1  christos 
   1164  1.1  christos static void *pkt_stats (struct device *dev)
   1165  1.1  christos {
   1166  1.1  christos   struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
   1167  1.1  christos 
   1168  1.1  christos   if (!stats || !PktSessStatistics(pktInfo.handle))
   1169  1.1  christos      return (NULL);
   1170  1.1  christos 
   1171  1.1  christos   stats->rx_packets       = pktStat.inPackets;
   1172  1.1  christos   stats->rx_errors        = pktStat.lost;
   1173  1.1  christos   stats->rx_missed_errors = PktRxDropped();
   1174  1.1  christos   return (stats);
   1175  1.1  christos }
   1176  1.1  christos 
   1177  1.1  christos static int pkt_probe (struct device *dev)
   1178  1.1  christos {
   1179  1.1  christos   if (!PktSearchDriver())
   1180  1.1  christos      return (0);
   1181  1.1  christos 
   1182  1.1  christos   dev->open           = pkt_open;
   1183  1.1  christos   dev->xmit           = pkt_xmit;
   1184  1.1  christos   dev->close          = pkt_close;
   1185  1.1  christos   dev->get_stats      = pkt_stats;
   1186  1.1  christos   dev->copy_rx_buf    = PktReceive;  /* farmem peek and copy routine */
   1187  1.1  christos   dev->get_rx_buf     = NULL;
   1188  1.1  christos   dev->peek_rx_buf    = NULL;
   1189  1.1  christos   dev->release_rx_buf = NULL;
   1190  1.1  christos   dev->priv           = calloc (sizeof(struct net_device_stats), 1);
   1191  1.1  christos   if (!dev->priv)
   1192  1.1  christos      return (0);
   1193  1.1  christos   return (1);
   1194  1.1  christos }
   1195  1.1  christos 
   1196  1.1  christos /*
   1197  1.1  christos  * NDIS device functions
   1198  1.1  christos  */
   1199  1.1  christos static void ndis_close (struct device *dev)
   1200  1.1  christos {
   1201  1.1  christos #ifdef USE_NDIS2
   1202  1.1  christos   NdisShutdown();
   1203  1.1  christos #endif
   1204  1.1  christos   ARGSUSED (dev);
   1205  1.1  christos }
   1206  1.1  christos 
   1207  1.1  christos static int ndis_open (struct device *dev)
   1208  1.1  christos {
   1209  1.7  christos   int promisc = (dev->flags & IFF_PROMISC);
   1210  1.1  christos 
   1211  1.1  christos #ifdef USE_NDIS2
   1212  1.7  christos   if (!NdisInit(promisc))
   1213  1.1  christos      return (0);
   1214  1.1  christos   return (1);
   1215  1.1  christos #else
   1216  1.7  christos   ARGSUSED (promisc);
   1217  1.1  christos   return (0);
   1218  1.1  christos #endif
   1219  1.1  christos }
   1220  1.1  christos 
   1221  1.1  christos static void *ndis_stats (struct device *dev)
   1222  1.1  christos {
   1223  1.1  christos   static struct net_device_stats stats;
   1224  1.1  christos 
   1225  1.1  christos   /* to-do */
   1226  1.1  christos   ARGSUSED (dev);
   1227  1.1  christos   return (&stats);
   1228  1.1  christos }
   1229  1.1  christos 
   1230  1.1  christos static int ndis_probe (struct device *dev)
   1231  1.1  christos {
   1232  1.1  christos #ifdef USE_NDIS2
   1233  1.1  christos   if (!NdisOpen())
   1234  1.1  christos      return (0);
   1235  1.1  christos #endif
   1236  1.1  christos 
   1237  1.1  christos   dev->open           = ndis_open;
   1238  1.1  christos   dev->xmit           = NULL;
   1239  1.1  christos   dev->close          = ndis_close;
   1240  1.1  christos   dev->get_stats      = ndis_stats;
   1241  1.1  christos   dev->copy_rx_buf    = NULL;       /* to-do */
   1242  1.1  christos   dev->get_rx_buf     = NULL;       /* upcall is from rmode driver */
   1243  1.1  christos   dev->peek_rx_buf    = NULL;
   1244  1.1  christos   dev->release_rx_buf = NULL;
   1245  1.1  christos   return (0);
   1246  1.1  christos }
   1247  1.1  christos 
   1248  1.1  christos /*
   1249  1.1  christos  * Search & probe for supported 32-bit (pmode) pcap devices
   1250  1.1  christos  */
   1251  1.1  christos #if defined(USE_32BIT_DRIVERS)
   1252  1.1  christos 
   1253  1.1  christos struct device el2_dev LOCKED_VAR = {
   1254  1.1  christos               "3c503",
   1255  1.1  christos               "EtherLink II",
   1256  1.1  christos               0,
   1257  1.1  christos               0,0,0,0,0,0,
   1258  1.1  christos               NULL,
   1259  1.1  christos               el2_probe
   1260  1.1  christos             };
   1261  1.1  christos 
   1262  1.1  christos struct device el3_dev LOCKED_VAR = {
   1263  1.1  christos               "3c509",
   1264  1.1  christos               "EtherLink III",
   1265  1.1  christos               0,
   1266  1.1  christos               0,0,0,0,0,0,
   1267  1.1  christos               &el2_dev,
   1268  1.1  christos               el3_probe
   1269  1.1  christos             };
   1270  1.1  christos 
   1271  1.1  christos struct device tc515_dev LOCKED_VAR = {
   1272  1.1  christos               "3c515",
   1273  1.1  christos               "EtherLink PCI",
   1274  1.1  christos               0,
   1275  1.1  christos               0,0,0,0,0,0,
   1276  1.1  christos               &el3_dev,
   1277  1.1  christos               tc515_probe
   1278  1.1  christos             };
   1279  1.1  christos 
   1280  1.1  christos struct device tc59_dev LOCKED_VAR = {
   1281  1.1  christos               "3c59x",
   1282  1.1  christos               "EtherLink PCI",
   1283  1.1  christos               0,
   1284  1.1  christos               0,0,0,0,0,0,
   1285  1.1  christos               &tc515_dev,
   1286  1.1  christos               tc59x_probe
   1287  1.1  christos             };
   1288  1.1  christos 
   1289  1.1  christos struct device tc90xbc_dev LOCKED_VAR = {
   1290  1.1  christos               "3c90x",
   1291  1.1  christos               "EtherLink 90X",
   1292  1.1  christos               0,
   1293  1.1  christos               0,0,0,0,0,0,
   1294  1.1  christos               &tc59_dev,
   1295  1.1  christos               tc90xbc_probe
   1296  1.1  christos             };
   1297  1.1  christos 
   1298  1.1  christos struct device wd_dev LOCKED_VAR = {
   1299  1.1  christos               "wd",
   1300  1.8  christos               "Western Digital",
   1301  1.1  christos               0,
   1302  1.1  christos               0,0,0,0,0,0,
   1303  1.1  christos               &tc90xbc_dev,
   1304  1.1  christos               wd_probe
   1305  1.1  christos             };
   1306  1.1  christos 
   1307  1.1  christos struct device ne_dev LOCKED_VAR = {
   1308  1.1  christos               "ne",
   1309  1.1  christos               "NEx000",
   1310  1.1  christos               0,
   1311  1.1  christos               0,0,0,0,0,0,
   1312  1.1  christos               &wd_dev,
   1313  1.1  christos               ne_probe
   1314  1.1  christos             };
   1315  1.1  christos 
   1316  1.1  christos struct device acct_dev LOCKED_VAR = {
   1317  1.1  christos               "acct",
   1318  1.1  christos               "Accton EtherPocket",
   1319  1.1  christos               0,
   1320  1.1  christos               0,0,0,0,0,0,
   1321  1.1  christos               &ne_dev,
   1322  1.1  christos               ethpk_probe
   1323  1.1  christos             };
   1324  1.1  christos 
   1325  1.1  christos struct device cs89_dev LOCKED_VAR = {
   1326  1.1  christos               "cs89",
   1327  1.1  christos               "Crystal Semiconductor",
   1328  1.1  christos               0,
   1329  1.1  christos               0,0,0,0,0,0,
   1330  1.1  christos               &acct_dev,
   1331  1.1  christos               cs89x0_probe
   1332  1.1  christos             };
   1333  1.1  christos 
   1334  1.1  christos struct device rtl8139_dev LOCKED_VAR = {
   1335  1.1  christos               "rtl8139",
   1336  1.1  christos               "RealTek PCI",
   1337  1.1  christos               0,
   1338  1.1  christos               0,0,0,0,0,0,
   1339  1.1  christos               &cs89_dev,
   1340  1.1  christos               rtl8139_probe     /* dev->probe routine */
   1341  1.3  christos             };
   1342  1.1  christos 
   1343  1.1  christos /*
   1344  1.1  christos  * Dequeue routine is called by polling.
   1345  1.1  christos  * NOTE: the queue-element is not copied, only a pointer is
   1346  1.1  christos  * returned at '*buf'
   1347  1.1  christos  */
   1348  1.1  christos int peek_rxbuf (BYTE **buf)
   1349  1.1  christos {
   1350  1.1  christos   struct rx_elem *tail, *head;
   1351  1.1  christos 
   1352  1.1  christos   PCAP_ASSERT (pktq_check (&active_dev->queue));
   1353  1.1  christos 
   1354  1.1  christos   DISABLE();
   1355  1.1  christos   tail = pktq_out_elem (&active_dev->queue);
   1356  1.1  christos   head = pktq_in_elem (&active_dev->queue);
   1357  1.1  christos   ENABLE();
   1358  1.1  christos 
   1359  1.1  christos   if (head != tail)
   1360  1.1  christos   {
   1361  1.1  christos     PCAP_ASSERT (tail->size < active_dev->queue.elem_size-4-2);
   1362  1.1  christos 
   1363  1.1  christos     *buf = &tail->data[0];
   1364  1.1  christos     return (tail->size);
   1365  1.1  christos   }
   1366  1.1  christos   *buf = NULL;
   1367  1.1  christos   return (0);
   1368  1.1  christos }
   1369  1.1  christos 
   1370  1.1  christos /*
   1371  1.1  christos  * Release buffer we peeked at above.
   1372  1.1  christos  */
   1373  1.1  christos int release_rxbuf (BYTE *buf)
   1374  1.1  christos {
   1375  1.1  christos #ifndef NDEBUG
   1376  1.1  christos   struct rx_elem *tail = pktq_out_elem (&active_dev->queue);
   1377  1.1  christos 
   1378  1.1  christos   PCAP_ASSERT (&tail->data[0] == buf);
   1379  1.1  christos #else
   1380  1.1  christos   ARGSUSED (buf);
   1381  1.1  christos #endif
   1382  1.1  christos   pktq_inc_out (&active_dev->queue);
   1383  1.1  christos   return (1);
   1384  1.1  christos }
   1385  1.1  christos 
   1386  1.1  christos /*
   1387  1.1  christos  * get_rxbuf() routine (in locked code) is called from IRQ handler
   1388  1.1  christos  * to request a buffer. Interrupts are disabled and we have a 32kB stack.
   1389  1.1  christos  */
   1390  1.1  christos BYTE *get_rxbuf (int len)
   1391  1.1  christos {
   1392  1.1  christos   int idx;
   1393  1.1  christos 
   1394  1.1  christos   if (len < ETH_MIN || len > ETH_MAX)
   1395  1.1  christos      return (NULL);
   1396  1.1  christos 
   1397  1.1  christos   idx = pktq_in_index (&active_dev->queue);
   1398  1.1  christos 
   1399  1.1  christos #ifdef DEBUG
   1400  1.1  christos   {
   1401  1.1  christos     static int fan_idx LOCKED_VAR = 0;
   1402  1.1  christos     writew ("-\\|/"[fan_idx++] | (15 << 8),      /* white on black colour */
   1403  1.1  christos             0xB8000 + 2*79);  /* upper-right corner, 80-col colour screen */
   1404  1.1  christos     fan_idx &= 3;
   1405  1.1  christos   }
   1406  1.1  christos /* writew (idx + '0' + 0x0F00, 0xB8000 + 2*78); */
   1407  1.1  christos #endif
   1408  1.1  christos 
   1409  1.1  christos   if (idx != active_dev->queue.out_index)
   1410  1.1  christos   {
   1411  1.1  christos     struct rx_elem *head = pktq_in_elem (&active_dev->queue);
   1412  1.1  christos 
   1413  1.1  christos     head->size = len;
   1414  1.1  christos     active_dev->queue.in_index = idx;
   1415  1.1  christos     return (&head->data[0]);
   1416  1.1  christos   }
   1417  1.1  christos 
   1418  1.1  christos   /* !!to-do: drop 25% of the oldest element
   1419  1.1  christos    */
   1420  1.1  christos   pktq_clear (&active_dev->queue);
   1421  1.1  christos   return (NULL);
   1422  1.1  christos }
   1423  1.1  christos 
   1424  1.1  christos /*
   1425  1.1  christos  *  Simple ring-buffer queue handler for reception of packets
   1426  1.1  christos  *  from network driver.
   1427  1.1  christos  */
   1428  1.1  christos #define PKTQ_MARKER  0xDEADBEEF
   1429  1.1  christos 
   1430  1.1  christos static int pktq_check (struct rx_ringbuf *q)
   1431  1.1  christos {
   1432  1.1  christos #ifndef NDEBUG
   1433  1.1  christos   int   i;
   1434  1.1  christos   char *buf;
   1435  1.1  christos #endif
   1436  1.1  christos 
   1437  1.1  christos   if (!q || !q->num_elem || !q->buf_start)
   1438  1.1  christos      return (0);
   1439  1.1  christos 
   1440  1.1  christos #ifndef NDEBUG
   1441  1.1  christos   buf = q->buf_start;
   1442  1.1  christos 
   1443  1.1  christos   for (i = 0; i < q->num_elem; i++)
   1444  1.1  christos   {
   1445  1.1  christos     buf += q->elem_size;
   1446  1.1  christos     if (*(DWORD*)(buf - sizeof(DWORD)) != PKTQ_MARKER)
   1447  1.1  christos        return (0);
   1448  1.1  christos   }
   1449  1.1  christos #endif
   1450  1.1  christos   return (1);
   1451  1.1  christos }
   1452  1.1  christos 
   1453  1.1  christos static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool)
   1454  1.1  christos {
   1455  1.1  christos   int i;
   1456  1.1  christos 
   1457  1.1  christos   q->elem_size = size;
   1458  1.1  christos   q->num_elem  = num;
   1459  1.1  christos   q->buf_start = pool;
   1460  1.1  christos   q->in_index  = 0;
   1461  1.1  christos   q->out_index = 0;
   1462  1.1  christos 
   1463  1.1  christos   PCAP_ASSERT (size >= sizeof(struct rx_elem) + sizeof(DWORD));
   1464  1.1  christos   PCAP_ASSERT (num);
   1465  1.1  christos   PCAP_ASSERT (pool);
   1466  1.1  christos 
   1467  1.1  christos   for (i = 0; i < num; i++)
   1468  1.1  christos   {
   1469  1.1  christos #if 0
   1470  1.1  christos     struct rx_elem *elem = (struct rx_elem*) pool;
   1471  1.1  christos 
   1472  1.1  christos     /* assert dword aligned elements
   1473  1.1  christos      */
   1474  1.1  christos     PCAP_ASSERT (((unsigned)(&elem->data[0]) & 3) == 0);
   1475  1.1  christos #endif
   1476  1.1  christos     pool += size;
   1477  1.1  christos     *(DWORD*) (pool - sizeof(DWORD)) = PKTQ_MARKER;
   1478  1.1  christos   }
   1479  1.1  christos   return (1);
   1480  1.1  christos }
   1481  1.1  christos 
   1482  1.1  christos /*
   1483  1.1  christos  * Increment the queue 'out_index' (tail).
   1484  1.1  christos  * Check for wraps.
   1485  1.1  christos  */
   1486  1.1  christos static int pktq_inc_out (struct rx_ringbuf *q)
   1487  1.1  christos {
   1488  1.1  christos   q->out_index++;
   1489  1.1  christos   if (q->out_index >= q->num_elem)
   1490  1.1  christos       q->out_index = 0;
   1491  1.1  christos   return (q->out_index);
   1492  1.1  christos }
   1493  1.1  christos 
   1494  1.1  christos /*
   1495  1.1  christos  * Return the queue's next 'in_index' (head).
   1496  1.1  christos  * Check for wraps.
   1497  1.1  christos  */
   1498  1.1  christos static int pktq_in_index (struct rx_ringbuf *q)
   1499  1.1  christos {
   1500  1.1  christos   volatile int index = q->in_index + 1;
   1501  1.1  christos 
   1502  1.1  christos   if (index >= q->num_elem)
   1503  1.1  christos       index = 0;
   1504  1.1  christos   return (index);
   1505  1.1  christos }
   1506  1.1  christos 
   1507  1.1  christos /*
   1508  1.1  christos  * Return the queue's head-buffer.
   1509  1.1  christos  */
   1510  1.1  christos static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q)
   1511  1.1  christos {
   1512  1.1  christos   return (struct rx_elem*) (q->buf_start + (q->elem_size * q->in_index));
   1513  1.1  christos }
   1514  1.1  christos 
   1515  1.1  christos /*
   1516  1.1  christos  * Return the queue's tail-buffer.
   1517  1.1  christos  */
   1518  1.1  christos static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q)
   1519  1.1  christos {
   1520  1.1  christos   return (struct rx_elem*) (q->buf_start + (q->elem_size * q->out_index));
   1521  1.1  christos }
   1522  1.1  christos 
   1523  1.1  christos /*
   1524  1.1  christos  * Clear the queue ring-buffer by setting head=tail.
   1525  1.1  christos  */
   1526  1.1  christos static void pktq_clear (struct rx_ringbuf *q)
   1527  1.1  christos {
   1528  1.1  christos   q->in_index = q->out_index;
   1529  1.1  christos }
   1530  1.1  christos 
   1531  1.1  christos /*
   1532  1.1  christos  * Symbols that must be linkable for "gcc -O0"
   1533  1.1  christos  */
   1534  1.1  christos #undef __IOPORT_H
   1535  1.1  christos #undef __DMA_H
   1536  1.1  christos 
   1537  1.1  christos #define extern
   1538  1.1  christos #define __inline__
   1539  1.1  christos 
   1540  1.1  christos #include "msdos/pm_drvr/ioport.h"
   1541  1.1  christos #include "msdos/pm_drvr/dma.h"
   1542  1.1  christos 
   1543  1.1  christos #endif /* USE_32BIT_DRIVERS */
   1544  1.1  christos 
   1545  1.5  christos /*
   1546  1.5  christos  * Libpcap version string.
   1547  1.5  christos  */
   1548  1.5  christos const char *
   1549  1.5  christos pcap_lib_version(void)
   1550  1.5  christos {
   1551  1.5  christos   return ("DOS-" PCAP_VERSION_STRING);
   1552  1.5  christos }
   1553