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