Drop main() prototype. Syncs with NetBSD-8
[minix.git] / external / bsd / libpcap / dist / pcap-dos.c
blob4b3512b5f57fd36ff07219e01d95e8f2a8f3499a
1 /* $NetBSD: pcap-dos.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */
3 /*
4 * This file is part of DOS-libpcap
5 * Ported to DOS/DOSX by G. Vanem <gvanem@broadpark.no>
7 * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
8 * network drivers.
9 */
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>
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
39 #include "pcap.h"
40 #include "pcap-dos.h"
41 #include "pcap-int.h"
42 #include "msdos/pktdrvr.h"
44 #ifdef USE_NDIS2
45 #include "msdos/ndis2.h"
46 #endif
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>
55 #if defined(USE_32BIT_DRIVERS)
56 #define FLUSHK() do { _printk_safe = 1; _printk_flush(); } while (0)
57 #define NDIS_NEXT_DEV &rtl8139_dev
59 static char *rx_pool = NULL;
60 static void init_32bit (void);
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;
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);
71 #else
72 #define FLUSHK() ((void)0)
73 #define NDIS_NEXT_DEV NULL
74 #endif
77 * Internal variables/functions in Watt-32
79 extern WORD _pktdevclass;
80 extern BOOL _eth_is_init;
81 extern int _w32_dynamic_host;
82 extern int _watt_do_exit;
83 extern int _watt_is_init;
84 extern int _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req;
85 extern void (*_w32_usr_post_init) (void);
86 extern void (*_w32_print_hook)();
88 extern void dbug_write (const char *); /* Watt-32 lib, pcdbug.c */
89 extern int pkt_get_mtu (void);
91 static int ref_count = 0;
93 static u_long mac_count = 0;
94 static u_long filter_count = 0;
96 static volatile BOOL exc_occured = 0;
98 static struct device *handle_to_device [20];
100 static int pcap_activate_dos (pcap_t *p);
101 static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,
102 u_char *data);
103 static void pcap_cleanup_dos (pcap_t *p);
104 static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);
105 static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);
106 static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);
108 static int ndis_probe (struct device *dev);
109 static int pkt_probe (struct device *dev);
111 static void close_driver (void);
112 static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf);
113 static int first_init (const char *name, char *ebuf, int promisc);
115 static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
116 const u_char *buf);
119 * These are the device we always support
121 static struct device ndis_dev = {
122 "ndis",
123 "NDIS2 LanManager",
125 0,0,0,0,0,0,
126 NDIS_NEXT_DEV, /* NULL or a 32-bit device */
127 ndis_probe
130 static struct device pkt_dev = {
131 "pkt",
132 "Packet-Driver",
134 0,0,0,0,0,0,
135 &ndis_dev,
136 pkt_probe
139 static struct device *get_device (int fd)
141 if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0]))
142 return (NULL);
143 return handle_to_device [fd-1];
147 * Private data for capturing on MS-DOS.
149 struct pcap_dos {
150 void (*wait_proc)(void); /* call proc while waiting */
151 struct pcap_stat stat;
154 pcap_t *pcap_create_interface (const char *device, char *ebuf)
156 pcap_t *p;
158 p = pcap_create_common(device, ebuf, sizeof (struct pcap_dos));
159 if (p == NULL)
160 return (NULL);
162 p->activate_op = pcap_activate_dos;
163 return (p);
167 * Open MAC-driver with name 'device_name' for live capture of
168 * network packets.
170 static int pcap_activate_dos (pcap_t *pcap)
172 struct pcap_dos *pcapd = pcap->priv;
174 if (pcap->opt.rfmon) {
176 * No monitor mode on DOS.
178 return (PCAP_ERROR_RFMON_NOTSUP);
181 if (pcap->snapshot < ETH_MIN+8)
182 pcap->snapshot = ETH_MIN+8;
184 if (pcap->snapshot > ETH_MAX) /* silently accept and truncate large MTUs */
185 pcap->snapshot = ETH_MAX;
187 pcap->linktype = DLT_EN10MB; /* !! */
188 pcap->cleanup_op = pcap_cleanup_dos;
189 pcap->read_op = pcap_read_dos;
190 pcap->stats_op = pcap_stats_dos;
191 pcap->inject_op = pcap_sendpacket_dos;
192 pcap->setfilter_op = pcap_setfilter_dos;
193 pcap->setdirection_op = NULL; /* Not implemented.*/
194 pcap->fd = ++ref_count;
196 if (pcap->fd == 1) /* first time we're called */
198 if (!init_watt32(pcap, pcap->opt.source, pcap->errbuf) ||
199 !first_init(pcap->opt.source, pcap->errbuf, pcap->opt.promisc))
201 return (PCAP_ERROR);
203 atexit (close_driver);
205 else if (stricmp(active_dev->name,pcap->opt.source))
207 snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
208 "Cannot use different devices simultaneously "
209 "(`%s' vs. `%s')", active_dev->name, pcap->opt.source);
210 return (PCAP_ERROR);
212 handle_to_device [pcap->fd-1] = active_dev;
213 return (0);
217 * Poll the receiver queue and call the pcap callback-handler
218 * with the packet.
220 static int
221 pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
223 struct pcap_dos *pd = p->priv;
224 struct pcap_pkthdr pcap;
225 struct timeval now, expiry = { 0,0 };
226 BYTE *rx_buf;
227 int rx_len = 0;
229 if (p->opt.timeout > 0)
231 gettimeofday2 (&now, NULL);
232 expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout;
233 expiry.tv_sec = now.tv_sec;
234 while (expiry.tv_usec >= 1000000L)
236 expiry.tv_usec -= 1000000L;
237 expiry.tv_sec++;
241 while (!exc_occured)
243 volatile struct device *dev; /* might be reset by sig_handler */
245 dev = get_device (p->fd);
246 if (!dev)
247 break;
249 PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf);
250 FLUSHK();
252 /* If driver has a zero-copy receive facility, peek at the queue,
253 * filter it, do the callback and release the buffer.
255 if (dev->peek_rx_buf)
257 PCAP_ASSERT (dev->release_rx_buf);
258 rx_len = (*dev->peek_rx_buf) (&rx_buf);
260 else
262 BYTE buf [ETH_MAX+100]; /* add some margin */
263 rx_len = (*dev->copy_rx_buf) (buf, p->snapshot);
264 rx_buf = buf;
267 if (rx_len > 0) /* got a packet */
269 mac_count++;
271 FLUSHK();
273 pcap.caplen = min (rx_len, p->snapshot);
274 pcap.len = rx_len;
276 if (callback &&
277 (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, rx_buf, pcap.len, pcap.caplen)))
279 filter_count++;
281 /* Fix-me!! Should be time of arrival. Not time of
282 * capture.
284 gettimeofday2 (&pcap.ts, NULL);
285 (*callback) (data, &pcap, rx_buf);
288 if (dev->release_rx_buf)
289 (*dev->release_rx_buf) (rx_buf);
291 if (pcap_pkt_debug > 0)
293 if (callback == watt32_recv_hook)
294 dbug_write ("pcap_recv_hook\n");
295 else dbug_write ("pcap_read_op\n");
297 FLUSHK();
298 return (1);
301 /* If not to wait for a packet or pcap_cleanup_dos() called from
302 * e.g. SIGINT handler, exit loop now.
304 if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0)
305 break;
307 gettimeofday2 (&now, NULL);
309 if (timercmp(&now, &expiry, >))
310 break;
312 #ifndef DJGPP
313 kbhit(); /* a real CPU hog */
314 #endif
316 if (p->wait_proc)
317 (*p->wait_proc)(); /* call yield func */
320 if (rx_len < 0) /* receive error */
322 pd->stat.ps_drop++;
323 #ifdef USE_32BIT_DRIVERS
324 if (pcap_pkt_debug > 1)
325 printk ("pkt-err %s\n", pktInfo.error);
326 #endif
327 return (-1);
329 return (0);
332 static int
333 pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
335 struct pcap_dos *pd = p->priv;
336 int rc, num = 0;
338 while (num <= cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
340 if (p->fd <= 0)
341 return (-1);
342 rc = pcap_read_one (p, callback, data);
343 if (rc > 0)
344 num++;
345 if (rc < 0)
346 break;
347 _w32_os_yield(); /* allow SIGINT generation, yield to Win95/NT */
349 return (num);
353 * Return network statistics
355 static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
357 struct net_device_stats *stats;
358 struct pcap_dos *pd;
359 struct device *dev = p ? get_device(p->fd) : NULL;
361 if (!dev)
363 strcpy (p->errbuf, "illegal pcap handle");
364 return (-1);
367 if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL)
369 strcpy (p->errbuf, "device statistics not available");
370 return (-1);
373 FLUSHK();
375 pd = p->priv;
376 pd->stat.ps_recv = stats->rx_packets;
377 pd->stat.ps_drop += stats->rx_missed_errors;
378 pd->stat.ps_ifdrop = stats->rx_dropped + /* queue full */
379 stats->rx_errors; /* HW errors */
380 if (ps)
381 *ps = pd->stat;
383 return (0);
387 * Return detailed network/device statistics.
388 * May be called after 'dev->close' is called.
390 int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se)
392 struct device *dev = p ? get_device (p->fd) : NULL;
394 if (!dev || !dev->get_stats)
396 strlcpy (p->errbuf, "detailed device statistics not available",
397 PCAP_ERRBUF_SIZE);
398 return (-1);
401 if (!strnicmp(dev->name,"pkt",3))
403 strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
404 PCAP_ERRBUF_SIZE);
405 return (-1);
407 memcpy (se, (*dev->get_stats)(dev), sizeof(*se));
408 return (0);
412 * Simply store the filter-code for the pcap_read_dos() callback
413 * Some day the filter-code could be handed down to the active
414 * device (pkt_rx1.s or 32-bit device interrupt handler).
416 static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp)
418 if (!p)
419 return (-1);
420 p->fcode = *fp;
421 return (0);
425 * Return # of packets received in pcap_read_dos()
427 u_long pcap_mac_packets (void)
429 return (mac_count);
433 * Return # of packets passed through filter in pcap_read_dos()
435 u_long pcap_filter_packets (void)
437 return (filter_count);
441 * Close pcap device. Not called for offline captures.
443 static void pcap_cleanup_dos (pcap_t *p)
445 struct pcap_dos *pd;
447 if (p && !exc_occured)
449 pd = p->priv;
450 if (pcap_stats(p,NULL) < 0)
451 pd->stat.ps_drop = 0;
452 if (!get_device(p->fd))
453 return;
455 handle_to_device [p->fd-1] = NULL;
456 p->fd = 0;
457 if (ref_count > 0)
458 ref_count--;
459 if (ref_count > 0)
460 return;
462 close_driver();
466 * Return the name of the 1st network interface,
467 * or NULL if none can be found.
469 char *pcap_lookupdev (char *ebuf)
471 struct device *dev;
473 #ifdef USE_32BIT_DRIVERS
474 init_32bit();
475 #endif
477 for (dev = (struct device*)dev_base; dev; dev = dev->next)
479 PCAP_ASSERT (dev->probe);
481 if ((*dev->probe)(dev))
483 FLUSHK();
484 probed_dev = (struct device*) dev; /* remember last probed device */
485 return (char*) dev->name;
489 if (ebuf)
490 strcpy (ebuf, "No driver found");
491 return (NULL);
495 * Gets localnet & netmask from Watt-32.
497 int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
498 bpf_u_int32 *netmask, char *errbuf)
500 if (!_watt_is_init)
502 strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
503 "called first");
504 return (-1);
507 *netmask = _w32_sin_mask;
508 *localnet = my_ip_addr & *netmask;
509 if (*localnet == 0)
511 if (IN_CLASSA(*netmask))
512 *localnet = IN_CLASSA_NET;
513 else if (IN_CLASSB(*netmask))
514 *localnet = IN_CLASSB_NET;
515 else if (IN_CLASSC(*netmask))
516 *localnet = IN_CLASSC_NET;
517 else
519 sprintf (errbuf, "inet class for 0x%lx unknown", *netmask);
520 return (-1);
523 ARGSUSED (device);
524 return (0);
528 * Get a list of all interfaces that are present and that we probe okay.
529 * Returns -1 on error, 0 otherwise.
530 * The list, as returned through "alldevsp", may be null if no interfaces
531 * were up and could be opened.
533 int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
535 struct device *dev;
536 struct sockaddr_ll sa_ll_1, sa_ll_2;
537 struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
538 pcap_if_t *devlist = NULL;
539 int ret = 0;
540 size_t addr_size = sizeof(struct sockaddr_ll);
542 for (dev = (struct device*)dev_base; dev; dev = dev->next)
544 PCAP_ASSERT (dev->probe);
546 if (!(*dev->probe)(dev))
547 continue;
549 PCAP_ASSERT (dev->close); /* set by probe routine */
550 FLUSHK();
551 (*dev->close) (dev);
553 memset (&sa_ll_1, 0, sizeof(sa_ll_1));
554 memset (&sa_ll_2, 0, sizeof(sa_ll_2));
555 sa_ll_1.sll_family = AF_PACKET;
556 sa_ll_2.sll_family = AF_PACKET;
558 addr = (struct sockaddr*) &sa_ll_1;
559 netmask = (struct sockaddr*) &sa_ll_1;
560 dstaddr = (struct sockaddr*) &sa_ll_1;
561 broadaddr = (struct sockaddr*) &sa_ll_2;
562 memset (&sa_ll_2.sll_addr, 0xFF, sizeof(sa_ll_2.sll_addr));
564 if (pcap_add_if(&devlist, dev->name, dev->flags,
565 dev->long_name, errbuf) < 0)
567 ret = -1;
568 break;
570 if (add_addr_to_iflist(&devlist,dev->name, dev->flags, addr, addr_size,
571 netmask, addr_size, broadaddr, addr_size,
572 dstaddr, addr_size, errbuf) < 0)
574 ret = -1;
575 break;
579 if (devlist && ret < 0)
581 pcap_freealldevs (devlist);
582 devlist = NULL;
584 else
585 if (!devlist)
586 strcpy (errbuf, "No drivers found");
588 *alldevsp = devlist;
589 return (ret);
593 * pcap_assert() is mainly used for debugging
595 void pcap_assert (const char *what, const char *file, unsigned line)
597 FLUSHK();
598 fprintf (stderr, "%s (%u): Assertion \"%s\" failed\n",
599 file, line, what);
600 close_driver();
601 _exit (-1);
605 * For pcap_offline_read(): wait and yield between printing packets
606 * to simulate the pace packets where actually recorded.
608 void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
610 struct pcap_dos *pd;
611 if (p)
613 pd = p->priv;
614 pd->wait_proc = yield;
615 p->opt.timeout = wait;
620 * Initialise a named network device.
622 static struct device *
623 open_driver (const char *dev_name, char *ebuf, int promisc)
625 struct device *dev;
627 for (dev = (struct device*)dev_base; dev; dev = dev->next)
629 PCAP_ASSERT (dev->name);
631 if (strcmp (dev_name,dev->name))
632 continue;
634 if (!probed_dev) /* user didn't call pcap_lookupdev() first */
636 PCAP_ASSERT (dev->probe);
638 if (!(*dev->probe)(dev)) /* call the xx_probe() function */
640 sprintf (ebuf, "failed to detect device `%s'", dev_name);
641 return (NULL);
643 probed_dev = dev; /* device is probed okay and may be used */
645 else if (dev != probed_dev)
647 goto not_probed;
650 FLUSHK();
652 /* Select what traffic to receive
654 if (promisc)
655 dev->flags |= (IFF_ALLMULTI | IFF_PROMISC);
656 else dev->flags &= ~(IFF_ALLMULTI | IFF_PROMISC);
658 PCAP_ASSERT (dev->open);
660 if (!(*dev->open)(dev))
662 sprintf (ebuf, "failed to activate device `%s'", dev_name);
663 if (pktInfo.error && !strncmp(dev->name,"pkt",3))
665 strcat (ebuf, ": ");
666 strcat (ebuf, pktInfo.error);
668 return (NULL);
671 /* Some devices need this to operate in promiscous mode
673 if (promisc && dev->set_multicast_list)
674 (*dev->set_multicast_list) (dev);
676 active_dev = dev; /* remember our active device */
677 break;
680 /* 'dev_name' not matched in 'dev_base' list.
682 if (!dev)
684 sprintf (ebuf, "device `%s' not supported", dev_name);
685 return (NULL);
688 not_probed:
689 if (!probed_dev)
691 sprintf (ebuf, "device `%s' not probed", dev_name);
692 return (NULL);
694 return (dev);
698 * Deinitialise MAC driver.
699 * Set receive mode back to default mode.
701 static void close_driver (void)
703 /* !!todo: loop over all 'handle_to_device[]' ? */
704 struct device *dev = active_dev;
706 if (dev && dev->close)
708 (*dev->close) (dev);
709 FLUSHK();
712 active_dev = NULL;
714 #ifdef USE_32BIT_DRIVERS
715 if (rx_pool)
717 k_free (rx_pool);
718 rx_pool = NULL;
720 if (dev)
721 pcibios_exit();
722 #endif
726 #ifdef __DJGPP__
727 static void setup_signals (void (*handler)(int))
729 signal (SIGSEGV,handler);
730 signal (SIGILL, handler);
731 signal (SIGFPE, handler);
734 static void exc_handler (int sig)
736 #ifdef USE_32BIT_DRIVERS
737 if (active_dev->irq > 0) /* excludes IRQ 0 */
739 disable_irq (active_dev->irq);
740 irq_eoi_cmd (active_dev->irq);
741 _printk_safe = 1;
743 #endif
745 switch (sig)
747 case SIGSEGV:
748 fputs ("Catching SIGSEGV.\n", stderr);
749 break;
750 case SIGILL:
751 fputs ("Catching SIGILL.\n", stderr);
752 break;
753 case SIGFPE:
754 _fpreset();
755 fputs ("Catching SIGFPE.\n", stderr);
756 break;
757 default:
758 fprintf (stderr, "Catching signal %d.\n", sig);
760 exc_occured = 1;
761 pcap_cleanup_dos (NULL);
763 #endif /* __DJGPP__ */
767 * Open the pcap device for the first client calling pcap_activate()
769 static int first_init (const char *name, char *ebuf, int promisc)
771 struct device *dev;
773 #ifdef USE_32BIT_DRIVERS
774 rx_pool = k_calloc (RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE);
775 if (!rx_pool)
777 strcpy (ebuf, "Not enough memory (Rx pool)");
778 return (0);
780 #endif
782 #ifdef __DJGPP__
783 setup_signals (exc_handler);
784 #endif
786 #ifdef USE_32BIT_DRIVERS
787 init_32bit();
788 #endif
790 dev = open_driver (name, ebuf, promisc);
791 if (!dev)
793 #ifdef USE_32BIT_DRIVERS
794 k_free (rx_pool);
795 rx_pool = NULL;
796 #endif
798 #ifdef __DJGPP__
799 setup_signals (SIG_DFL);
800 #endif
801 return (0);
804 #ifdef USE_32BIT_DRIVERS
806 * If driver is NOT a 16-bit "pkt/ndis" driver (having a 'copy_rx_buf'
807 * set in it's probe handler), initialise near-memory ring-buffer for
808 * the 32-bit device.
810 if (dev->copy_rx_buf == NULL)
812 dev->get_rx_buf = get_rxbuf;
813 dev->peek_rx_buf = peek_rxbuf;
814 dev->release_rx_buf = release_rxbuf;
815 pktq_init (&dev->queue, RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE, rx_pool);
817 #endif
818 return (1);
821 #ifdef USE_32BIT_DRIVERS
822 static void init_32bit (void)
824 static int init_pci = 0;
826 if (!_printk_file)
827 _printk_init (64*1024, NULL); /* calls atexit(printk_exit) */
829 if (!init_pci)
830 (void)pci_init(); /* init BIOS32+PCI interface */
831 init_pci = 1;
833 #endif
837 * Hook functions for using Watt-32 together with pcap
839 static char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */
840 static WORD etype;
841 static pcap_t pcap_save;
843 static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
844 const u_char *buf)
846 /* Fix me: assumes Ethernet II only */
847 struct ether_header *ep = (struct ether_header*) buf;
849 memcpy (rxbuf, buf, pcap->caplen);
850 etype = ep->ether_type;
851 ARGSUSED (dummy);
854 #if (WATTCP_VER >= 0x0224)
856 * This function is used by Watt-32 to poll for a packet.
857 * i.e. it's set to bypass _eth_arrived()
859 static void *pcap_recv_hook (WORD *type)
861 int len = pcap_read_dos (&pcap_save, 1, watt32_recv_hook, NULL);
863 if (len < 0)
864 return (NULL);
866 *type = etype;
867 return (void*) &rxbuf;
871 * This function is called by Watt-32 (via _eth_xmit_hook).
872 * If dbug_init() was called, we should trace packets sent.
874 static int pcap_xmit_hook (const void *buf, unsigned len)
876 int rc = 0;
878 if (pcap_pkt_debug > 0)
879 dbug_write ("pcap_xmit_hook: ");
881 if (active_dev && active_dev->xmit)
882 if ((*active_dev->xmit) (active_dev, buf, len) > 0)
883 rc = len;
885 if (pcap_pkt_debug > 0)
886 dbug_write (rc ? "ok\n" : "fail\n");
887 return (rc);
889 #endif
891 static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len)
893 struct device *dev = p ? get_device(p->fd) : NULL;
895 if (!dev || !dev->xmit)
896 return (-1);
897 return (*dev->xmit) (dev, buf, len);
901 * This function is called by Watt-32 in tcp_post_init().
902 * We should prevent Watt-32 from using BOOTP/DHCP/RARP etc.
904 static void (*prev_post_hook) (void);
906 static void pcap_init_hook (void)
908 _w32__bootp_on = _w32__dhcp_on = _w32__rarp_on = 0;
909 _w32__do_mask_req = 0;
910 _w32_dynamic_host = 0;
911 if (prev_post_hook)
912 (*prev_post_hook)();
916 * Supress PRINT message from Watt-32's sock_init()
918 static void null_print (void) {}
921 * To use features of Watt-32 (netdb functions and socket etc.)
922 * we must call sock_init(). But we set various hooks to prevent
923 * using normal PKTDRVR functions in pcpkt.c. This should hopefully
924 * make Watt-32 and pcap co-operate.
926 static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
928 char *env;
929 int rc, MTU, has_ip_addr;
930 int using_pktdrv = 1;
932 /* If user called sock_init() first, we need to reinit in
933 * order to open debug/trace-file properly
935 if (_watt_is_init)
936 sock_exit();
938 env = getenv ("PCAP_DEBUG");
939 if (env && atoi(env) > 0 &&
940 pcap_pkt_debug < 0) /* if not already set */
942 dbug_init();
943 pcap_pkt_debug = atoi (env);
946 _watt_do_exit = 0; /* prevent sock_init() calling exit() */
947 prev_post_hook = _w32_usr_post_init;
948 _w32_usr_post_init = pcap_init_hook;
949 _w32_print_hook = null_print;
951 if (dev_name && strncmp(dev_name,"pkt",3))
952 using_pktdrv = FALSE;
954 rc = sock_init();
955 has_ip_addr = (rc != 8); /* IP-address assignment failed */
957 /* if pcap is using a 32-bit driver w/o a pktdrvr loaded, we
958 * just pretend Watt-32 is initialised okay.
960 * !! fix-me: The Watt-32 config isn't done if no pktdrvr
961 * was found. In that case my_ip_addr + sin_mask
962 * have default values. Should be taken from another
963 * ini-file/environment in any case (ref. tcpdump.ini)
965 _watt_is_init = 1;
967 if (!using_pktdrv || !has_ip_addr) /* for now .... */
969 static const char myip[] = "192.168.0.1";
970 static const char mask[] = "255.255.255.0";
972 printf ("Just guessing, using IP %s and netmask %s\n", myip, mask);
973 my_ip_addr = aton (myip);
974 _w32_sin_mask = aton (mask);
976 else if (rc && using_pktdrv)
978 sprintf (err_buf, "sock_init() failed, code %d", rc);
979 return (0);
982 /* Set recv-hook for peeking in _eth_arrived().
984 #if (WATTCP_VER >= 0x0224)
985 _eth_recv_hook = pcap_recv_hook;
986 _eth_xmit_hook = pcap_xmit_hook;
987 #endif
989 /* Free the pkt-drvr handle allocated in pkt_init().
990 * The above hooks should thus use the handle reopened in open_driver()
992 if (using_pktdrv)
994 _eth_release();
995 /* _eth_is_init = 1; */ /* hack to get Rx/Tx-hooks in Watt-32 working */
998 memcpy (&pcap_save, pcap, sizeof(pcap_save));
999 MTU = pkt_get_mtu();
1000 pcap_save.fcode.bf_insns = NULL;
1001 pcap_save.linktype = _eth_get_hwtype (NULL, NULL);
1002 pcap_save.snapshot = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */
1004 #if 1
1005 /* prevent use of resolve() and resolve_ip()
1007 last_nameserver = 0;
1008 #endif
1009 return (1);
1012 int EISA_bus = 0; /* Where is natural place for this? */
1015 * Application config hooks to set various driver parameters.
1018 static const struct config_table debug_tab[] = {
1019 { "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug },
1020 { "PKT.VECTOR", ARG_ATOX_W, NULL },
1021 { "NDIS.DEBUG", ARG_ATOI, NULL },
1022 #ifdef USE_32BIT_DRIVERS
1023 { "3C503.DEBUG", ARG_ATOI, &ei_debug },
1024 { "3C503.IO_BASE", ARG_ATOX_W, &el2_dev.base_addr },
1025 { "3C503.MEMORY", ARG_ATOX_W, &el2_dev.mem_start },
1026 { "3C503.IRQ", ARG_ATOI, &el2_dev.irq },
1027 { "3C505.DEBUG", ARG_ATOI, NULL },
1028 { "3C505.BASE", ARG_ATOX_W, NULL },
1029 { "3C507.DEBUG", ARG_ATOI, NULL },
1030 { "3C509.DEBUG", ARG_ATOI, &el3_debug },
1031 { "3C509.ILOOP", ARG_ATOI, &el3_max_loop },
1032 { "3C529.DEBUG", ARG_ATOI, NULL },
1033 { "3C575.DEBUG", ARG_ATOI, &debug_3c575 },
1034 { "3C59X.DEBUG", ARG_ATOI, &vortex_debug },
1035 { "3C59X.IFACE0", ARG_ATOI, &vortex_options[0] },
1036 { "3C59X.IFACE1", ARG_ATOI, &vortex_options[1] },
1037 { "3C59X.IFACE2", ARG_ATOI, &vortex_options[2] },
1038 { "3C59X.IFACE3", ARG_ATOI, &vortex_options[3] },
1039 { "3C90X.DEBUG", ARG_ATOX_W, &tc90xbc_debug },
1040 { "ACCT.DEBUG", ARG_ATOI, &ethpk_debug },
1041 { "CS89.DEBUG", ARG_ATOI, &cs89_debug },
1042 { "RTL8139.DEBUG", ARG_ATOI, &rtl8139_debug },
1043 /* { "RTL8139.FDUPLEX", ARG_ATOI, &rtl8139_options }, */
1044 { "SMC.DEBUG", ARG_ATOI, &ei_debug },
1045 /* { "E100.DEBUG", ARG_ATOI, &e100_debug }, */
1046 { "PCI.DEBUG", ARG_ATOI, &pci_debug },
1047 { "BIOS32.DEBUG", ARG_ATOI, &bios32_debug },
1048 { "IRQ.DEBUG", ARG_ATOI, &irq_debug },
1049 { "TIMER.IRQ", ARG_ATOI, &timer_irq },
1050 #endif
1051 { NULL }
1055 * pcap_config_hook() is an extension to application's config
1056 * handling. Uses Watt-32's config-table function.
1058 int pcap_config_hook (const char *name, const char *value)
1060 return parse_config_table (debug_tab, NULL, name, value);
1064 * Linked list of supported devices
1066 struct device *active_dev = NULL; /* the device we have opened */
1067 struct device *probed_dev = NULL; /* the device we have probed */
1068 const struct device *dev_base = &pkt_dev; /* list of network devices */
1071 * PKTDRVR device functions
1073 int pcap_pkt_debug = -1;
1075 static void pkt_close (struct device *dev)
1077 BOOL okay = PktExitDriver();
1079 if (pcap_pkt_debug > 1)
1080 fprintf (stderr, "pkt_close(): %d\n", okay);
1082 if (dev->priv)
1083 free (dev->priv);
1084 dev->priv = NULL;
1087 static int pkt_open (struct device *dev)
1089 PKT_RX_MODE mode;
1091 if (dev->flags & IFF_PROMISC)
1092 mode = PDRX_ALL_PACKETS;
1093 else mode = PDRX_BROADCAST;
1095 if (!PktInitDriver(mode))
1096 return (0);
1098 PktResetStatistics (pktInfo.handle);
1099 PktQueueBusy (FALSE);
1100 return (1);
1103 static int pkt_xmit (struct device *dev, const void *buf, int len)
1105 struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
1107 if (pcap_pkt_debug > 0)
1108 dbug_write ("pcap_xmit\n");
1110 if (!PktTransmit(buf,len))
1112 stats->tx_errors++;
1113 return (0);
1115 return (len);
1118 static void *pkt_stats (struct device *dev)
1120 struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
1122 if (!stats || !PktSessStatistics(pktInfo.handle))
1123 return (NULL);
1125 stats->rx_packets = pktStat.inPackets;
1126 stats->rx_errors = pktStat.lost;
1127 stats->rx_missed_errors = PktRxDropped();
1128 return (stats);
1131 static int pkt_probe (struct device *dev)
1133 if (!PktSearchDriver())
1134 return (0);
1136 dev->open = pkt_open;
1137 dev->xmit = pkt_xmit;
1138 dev->close = pkt_close;
1139 dev->get_stats = pkt_stats;
1140 dev->copy_rx_buf = PktReceive; /* farmem peek and copy routine */
1141 dev->get_rx_buf = NULL;
1142 dev->peek_rx_buf = NULL;
1143 dev->release_rx_buf = NULL;
1144 dev->priv = calloc (sizeof(struct net_device_stats), 1);
1145 if (!dev->priv)
1146 return (0);
1147 return (1);
1151 * NDIS device functions
1153 static void ndis_close (struct device *dev)
1155 #ifdef USE_NDIS2
1156 NdisShutdown();
1157 #endif
1158 ARGSUSED (dev);
1161 static int ndis_open (struct device *dev)
1163 int promis = (dev->flags & IFF_PROMISC);
1165 #ifdef USE_NDIS2
1166 if (!NdisInit(promis))
1167 return (0);
1168 return (1);
1169 #else
1170 ARGSUSED (promis);
1171 return (0);
1172 #endif
1175 static void *ndis_stats (struct device *dev)
1177 static struct net_device_stats stats;
1179 /* to-do */
1180 ARGSUSED (dev);
1181 return (&stats);
1184 static int ndis_probe (struct device *dev)
1186 #ifdef USE_NDIS2
1187 if (!NdisOpen())
1188 return (0);
1189 #endif
1191 dev->open = ndis_open;
1192 dev->xmit = NULL;
1193 dev->close = ndis_close;
1194 dev->get_stats = ndis_stats;
1195 dev->copy_rx_buf = NULL; /* to-do */
1196 dev->get_rx_buf = NULL; /* upcall is from rmode driver */
1197 dev->peek_rx_buf = NULL;
1198 dev->release_rx_buf = NULL;
1199 return (0);
1203 * Search & probe for supported 32-bit (pmode) pcap devices
1205 #if defined(USE_32BIT_DRIVERS)
1207 struct device el2_dev LOCKED_VAR = {
1208 "3c503",
1209 "EtherLink II",
1211 0,0,0,0,0,0,
1212 NULL,
1213 el2_probe
1216 struct device el3_dev LOCKED_VAR = {
1217 "3c509",
1218 "EtherLink III",
1220 0,0,0,0,0,0,
1221 &el2_dev,
1222 el3_probe
1225 struct device tc515_dev LOCKED_VAR = {
1226 "3c515",
1227 "EtherLink PCI",
1229 0,0,0,0,0,0,
1230 &el3_dev,
1231 tc515_probe
1234 struct device tc59_dev LOCKED_VAR = {
1235 "3c59x",
1236 "EtherLink PCI",
1238 0,0,0,0,0,0,
1239 &tc515_dev,
1240 tc59x_probe
1243 struct device tc90xbc_dev LOCKED_VAR = {
1244 "3c90x",
1245 "EtherLink 90X",
1247 0,0,0,0,0,0,
1248 &tc59_dev,
1249 tc90xbc_probe
1252 struct device wd_dev LOCKED_VAR = {
1253 "wd",
1254 "Westen Digital",
1256 0,0,0,0,0,0,
1257 &tc90xbc_dev,
1258 wd_probe
1261 struct device ne_dev LOCKED_VAR = {
1262 "ne",
1263 "NEx000",
1265 0,0,0,0,0,0,
1266 &wd_dev,
1267 ne_probe
1270 struct device acct_dev LOCKED_VAR = {
1271 "acct",
1272 "Accton EtherPocket",
1274 0,0,0,0,0,0,
1275 &ne_dev,
1276 ethpk_probe
1279 struct device cs89_dev LOCKED_VAR = {
1280 "cs89",
1281 "Crystal Semiconductor",
1283 0,0,0,0,0,0,
1284 &acct_dev,
1285 cs89x0_probe
1288 struct device rtl8139_dev LOCKED_VAR = {
1289 "rtl8139",
1290 "RealTek PCI",
1292 0,0,0,0,0,0,
1293 &cs89_dev,
1294 rtl8139_probe /* dev->probe routine */
1298 * Dequeue routine is called by polling.
1299 * NOTE: the queue-element is not copied, only a pointer is
1300 * returned at '*buf'
1302 int peek_rxbuf (BYTE **buf)
1304 struct rx_elem *tail, *head;
1306 PCAP_ASSERT (pktq_check (&active_dev->queue));
1308 DISABLE();
1309 tail = pktq_out_elem (&active_dev->queue);
1310 head = pktq_in_elem (&active_dev->queue);
1311 ENABLE();
1313 if (head != tail)
1315 PCAP_ASSERT (tail->size < active_dev->queue.elem_size-4-2);
1317 *buf = &tail->data[0];
1318 return (tail->size);
1320 *buf = NULL;
1321 return (0);
1325 * Release buffer we peeked at above.
1327 int release_rxbuf (BYTE *buf)
1329 #ifndef NDEBUG
1330 struct rx_elem *tail = pktq_out_elem (&active_dev->queue);
1332 PCAP_ASSERT (&tail->data[0] == buf);
1333 #else
1334 ARGSUSED (buf);
1335 #endif
1336 pktq_inc_out (&active_dev->queue);
1337 return (1);
1341 * get_rxbuf() routine (in locked code) is called from IRQ handler
1342 * to request a buffer. Interrupts are disabled and we have a 32kB stack.
1344 BYTE *get_rxbuf (int len)
1346 int idx;
1348 if (len < ETH_MIN || len > ETH_MAX)
1349 return (NULL);
1351 idx = pktq_in_index (&active_dev->queue);
1353 #ifdef DEBUG
1355 static int fan_idx LOCKED_VAR = 0;
1356 writew ("-\\|/"[fan_idx++] | (15 << 8), /* white on black colour */
1357 0xB8000 + 2*79); /* upper-right corner, 80-col colour screen */
1358 fan_idx &= 3;
1360 /* writew (idx + '0' + 0x0F00, 0xB8000 + 2*78); */
1361 #endif
1363 if (idx != active_dev->queue.out_index)
1365 struct rx_elem *head = pktq_in_elem (&active_dev->queue);
1367 head->size = len;
1368 active_dev->queue.in_index = idx;
1369 return (&head->data[0]);
1372 /* !!to-do: drop 25% of the oldest element
1374 pktq_clear (&active_dev->queue);
1375 return (NULL);
1379 * Simple ring-buffer queue handler for reception of packets
1380 * from network driver.
1382 #define PKTQ_MARKER 0xDEADBEEF
1384 static int pktq_check (struct rx_ringbuf *q)
1386 #ifndef NDEBUG
1387 int i;
1388 char *buf;
1389 #endif
1391 if (!q || !q->num_elem || !q->buf_start)
1392 return (0);
1394 #ifndef NDEBUG
1395 buf = q->buf_start;
1397 for (i = 0; i < q->num_elem; i++)
1399 buf += q->elem_size;
1400 if (*(DWORD*)(buf - sizeof(DWORD)) != PKTQ_MARKER)
1401 return (0);
1403 #endif
1404 return (1);
1407 static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool)
1409 int i;
1411 q->elem_size = size;
1412 q->num_elem = num;
1413 q->buf_start = pool;
1414 q->in_index = 0;
1415 q->out_index = 0;
1417 PCAP_ASSERT (size >= sizeof(struct rx_elem) + sizeof(DWORD));
1418 PCAP_ASSERT (num);
1419 PCAP_ASSERT (pool);
1421 for (i = 0; i < num; i++)
1423 #if 0
1424 struct rx_elem *elem = (struct rx_elem*) pool;
1426 /* assert dword aligned elements
1428 PCAP_ASSERT (((unsigned)(&elem->data[0]) & 3) == 0);
1429 #endif
1430 pool += size;
1431 *(DWORD*) (pool - sizeof(DWORD)) = PKTQ_MARKER;
1433 return (1);
1437 * Increment the queue 'out_index' (tail).
1438 * Check for wraps.
1440 static int pktq_inc_out (struct rx_ringbuf *q)
1442 q->out_index++;
1443 if (q->out_index >= q->num_elem)
1444 q->out_index = 0;
1445 return (q->out_index);
1449 * Return the queue's next 'in_index' (head).
1450 * Check for wraps.
1452 static int pktq_in_index (struct rx_ringbuf *q)
1454 volatile int index = q->in_index + 1;
1456 if (index >= q->num_elem)
1457 index = 0;
1458 return (index);
1462 * Return the queue's head-buffer.
1464 static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q)
1466 return (struct rx_elem*) (q->buf_start + (q->elem_size * q->in_index));
1470 * Return the queue's tail-buffer.
1472 static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q)
1474 return (struct rx_elem*) (q->buf_start + (q->elem_size * q->out_index));
1478 * Clear the queue ring-buffer by setting head=tail.
1480 static void pktq_clear (struct rx_ringbuf *q)
1482 q->in_index = q->out_index;
1486 * Symbols that must be linkable for "gcc -O0"
1488 #undef __IOPORT_H
1489 #undef __DMA_H
1491 #define extern
1492 #define __inline__
1494 #include "msdos/pm_drvr/ioport.h"
1495 #include "msdos/pm_drvr/dma.h"
1497 #endif /* USE_32BIT_DRIVERS */