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, ðpk_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