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