"Fossies" - the Fresh Open Source Software Archive

Member "libpcap-1.9.1/./pcap-dos.c" (30 Sep 2019, 36759 Bytes) of package /linux/misc/libpcap-1.9.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pcap-dos.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.9.0_vs_1.9.1.

    1 /*
    2  *  This file is part of DOS-libpcap
    3  *  Ported to DOS/DOSX by G. Vanem <gvanem@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     pcap_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     pcap_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 }