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