104fb2745SSam Leffler /*
204fb2745SSam Leffler * This file is part of DOS-libpcap
3ada6f083SXin LI * Ported to DOS/DOSX by G. Vanem <gvanem@yahoo.no>
404fb2745SSam Leffler *
504fb2745SSam Leffler * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
604fb2745SSam Leffler * network drivers.
704fb2745SSam Leffler */
804fb2745SSam Leffler
904fb2745SSam Leffler #include <stdio.h>
1004fb2745SSam Leffler #include <stdlib.h>
1104fb2745SSam Leffler #include <string.h>
1204fb2745SSam Leffler #include <signal.h>
1304fb2745SSam Leffler #include <float.h>
1404fb2745SSam Leffler #include <fcntl.h>
156f9cba8fSJoseph Mingrone #include <limits.h> /* for INT_MAX */
1604fb2745SSam Leffler #include <io.h>
1704fb2745SSam Leffler
1804fb2745SSam Leffler #if defined(USE_32BIT_DRIVERS)
1904fb2745SSam Leffler #include "msdos/pm_drvr/pmdrvr.h"
2004fb2745SSam Leffler #include "msdos/pm_drvr/pci.h"
2104fb2745SSam Leffler #include "msdos/pm_drvr/bios32.h"
2204fb2745SSam Leffler #include "msdos/pm_drvr/module.h"
2304fb2745SSam Leffler #include "msdos/pm_drvr/3c501.h"
2404fb2745SSam Leffler #include "msdos/pm_drvr/3c503.h"
2504fb2745SSam Leffler #include "msdos/pm_drvr/3c509.h"
2604fb2745SSam Leffler #include "msdos/pm_drvr/3c59x.h"
2704fb2745SSam Leffler #include "msdos/pm_drvr/3c515.h"
2804fb2745SSam Leffler #include "msdos/pm_drvr/3c90x.h"
2904fb2745SSam Leffler #include "msdos/pm_drvr/3c575_cb.h"
3004fb2745SSam Leffler #include "msdos/pm_drvr/ne.h"
3104fb2745SSam Leffler #include "msdos/pm_drvr/wd.h"
3204fb2745SSam Leffler #include "msdos/pm_drvr/accton.h"
3304fb2745SSam Leffler #include "msdos/pm_drvr/cs89x0.h"
3404fb2745SSam Leffler #include "msdos/pm_drvr/rtl8139.h"
3504fb2745SSam Leffler #include "msdos/pm_drvr/ne2k-pci.h"
3604fb2745SSam Leffler #endif
3704fb2745SSam Leffler
3804fb2745SSam Leffler #include "pcap.h"
3904fb2745SSam Leffler #include "pcap-dos.h"
4004fb2745SSam Leffler #include "pcap-int.h"
4104fb2745SSam Leffler #include "msdos/pktdrvr.h"
4204fb2745SSam Leffler
4304fb2745SSam Leffler #ifdef USE_NDIS2
4404fb2745SSam Leffler #include "msdos/ndis2.h"
4504fb2745SSam Leffler #endif
4604fb2745SSam Leffler
4704fb2745SSam Leffler #include <arpa/inet.h>
4804fb2745SSam Leffler #include <net/if.h>
4904fb2745SSam Leffler #include <net/if_arp.h>
5004fb2745SSam Leffler #include <net/if_ether.h>
5104fb2745SSam Leffler #include <net/if_packe.h>
5204fb2745SSam Leffler #include <tcp.h>
5304fb2745SSam Leffler
5404fb2745SSam Leffler #if defined(USE_32BIT_DRIVERS)
5504fb2745SSam Leffler #define FLUSHK() do { _printk_safe = 1; _printk_flush(); } while (0)
5604fb2745SSam Leffler #define NDIS_NEXT_DEV &rtl8139_dev
5704fb2745SSam Leffler
5804fb2745SSam Leffler static char *rx_pool = NULL;
5904fb2745SSam Leffler static void init_32bit (void);
6004fb2745SSam Leffler
6104fb2745SSam Leffler static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool);
6204fb2745SSam Leffler static int pktq_check (struct rx_ringbuf *q);
6304fb2745SSam Leffler static int pktq_inc_out (struct rx_ringbuf *q);
6404fb2745SSam Leffler static int pktq_in_index (struct rx_ringbuf *q) LOCKED_FUNC;
6504fb2745SSam Leffler static void pktq_clear (struct rx_ringbuf *q) LOCKED_FUNC;
6604fb2745SSam Leffler
6704fb2745SSam Leffler static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q) LOCKED_FUNC;
6804fb2745SSam Leffler static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q);
6904fb2745SSam Leffler
7004fb2745SSam Leffler #else
7104fb2745SSam Leffler #define FLUSHK() ((void)0)
7204fb2745SSam Leffler #define NDIS_NEXT_DEV NULL
7304fb2745SSam Leffler #endif
7404fb2745SSam Leffler
7504fb2745SSam Leffler /*
7604fb2745SSam Leffler * Internal variables/functions in Watt-32
7704fb2745SSam Leffler */
7804fb2745SSam Leffler extern WORD _pktdevclass;
7904fb2745SSam Leffler extern BOOL _eth_is_init;
8004fb2745SSam Leffler extern int _w32_dynamic_host;
8104fb2745SSam Leffler extern int _watt_do_exit;
8204fb2745SSam Leffler extern int _watt_is_init;
8304fb2745SSam Leffler extern int _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req;
8404fb2745SSam Leffler extern void (*_w32_usr_post_init) (void);
8504fb2745SSam Leffler extern void (*_w32_print_hook)();
8604fb2745SSam Leffler
8704fb2745SSam Leffler extern void dbug_write (const char *); /* Watt-32 lib, pcdbug.c */
8804fb2745SSam Leffler extern int pkt_get_mtu (void);
8904fb2745SSam Leffler
9004fb2745SSam Leffler static int ref_count = 0;
9104fb2745SSam Leffler
9204fb2745SSam Leffler static u_long mac_count = 0;
9304fb2745SSam Leffler static u_long filter_count = 0;
9404fb2745SSam Leffler
95*afdbf109SJoseph Mingrone static volatile BOOL exc_occurred = 0;
9604fb2745SSam Leffler
9704fb2745SSam Leffler static struct device *handle_to_device [20];
9804fb2745SSam Leffler
99a8e07101SRui Paulo static int pcap_activate_dos (pcap_t *p);
10004fb2745SSam Leffler static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,
10104fb2745SSam Leffler u_char *data);
102a8e07101SRui Paulo static void pcap_cleanup_dos (pcap_t *p);
10304fb2745SSam Leffler static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);
10404fb2745SSam Leffler static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);
10504fb2745SSam Leffler static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);
10604fb2745SSam Leffler
10704fb2745SSam Leffler static int ndis_probe (struct device *dev);
10804fb2745SSam Leffler static int pkt_probe (struct device *dev);
10904fb2745SSam Leffler
11004fb2745SSam Leffler static void close_driver (void);
11104fb2745SSam Leffler static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf);
11204fb2745SSam Leffler static int first_init (const char *name, char *ebuf, int promisc);
11304fb2745SSam Leffler
11404fb2745SSam Leffler static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
11504fb2745SSam Leffler const u_char *buf);
11604fb2745SSam Leffler
11704fb2745SSam Leffler /*
11804fb2745SSam Leffler * These are the device we always support
11904fb2745SSam Leffler */
12004fb2745SSam Leffler static struct device ndis_dev = {
12104fb2745SSam Leffler "ndis",
12204fb2745SSam Leffler "NDIS2 LanManager",
12304fb2745SSam Leffler 0,
12404fb2745SSam Leffler 0,0,0,0,0,0,
12504fb2745SSam Leffler NDIS_NEXT_DEV, /* NULL or a 32-bit device */
12604fb2745SSam Leffler ndis_probe
12704fb2745SSam Leffler };
12804fb2745SSam Leffler
12904fb2745SSam Leffler static struct device pkt_dev = {
13004fb2745SSam Leffler "pkt",
13104fb2745SSam Leffler "Packet-Driver",
13204fb2745SSam Leffler 0,
13304fb2745SSam Leffler 0,0,0,0,0,0,
13404fb2745SSam Leffler &ndis_dev,
13504fb2745SSam Leffler pkt_probe
13604fb2745SSam Leffler };
13704fb2745SSam Leffler
get_device(int fd)13804fb2745SSam Leffler static struct device *get_device (int fd)
13904fb2745SSam Leffler {
14004fb2745SSam Leffler if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0]))
14104fb2745SSam Leffler return (NULL);
14204fb2745SSam Leffler return handle_to_device [fd-1];
14304fb2745SSam Leffler }
14404fb2745SSam Leffler
145681ed54cSXin LI /*
146681ed54cSXin LI * Private data for capturing on MS-DOS.
147681ed54cSXin LI */
148681ed54cSXin LI struct pcap_dos {
149681ed54cSXin LI void (*wait_proc)(void); /* call proc while waiting */
150681ed54cSXin LI struct pcap_stat stat;
151681ed54cSXin LI };
152681ed54cSXin LI
pcap_create_interface(const char * device _U_,char * ebuf)153ada6f083SXin LI pcap_t *pcap_create_interface (const char *device _U_, char *ebuf)
154a8e07101SRui Paulo {
155a8e07101SRui Paulo pcap_t *p;
156a8e07101SRui Paulo
1576f9cba8fSJoseph Mingrone p = PCAP_CREATE_COMMON(ebuf, struct pcap_dos);
158a8e07101SRui Paulo if (p == NULL)
159a8e07101SRui Paulo return (NULL);
160a8e07101SRui Paulo
161a8e07101SRui Paulo p->activate_op = pcap_activate_dos;
162a8e07101SRui Paulo return (p);
163a8e07101SRui Paulo }
164a8e07101SRui Paulo
16504fb2745SSam Leffler /*
16604fb2745SSam Leffler * Open MAC-driver with name 'device_name' for live capture of
16704fb2745SSam Leffler * network packets.
16804fb2745SSam Leffler */
pcap_activate_dos(pcap_t * pcap)169a8e07101SRui Paulo static int pcap_activate_dos (pcap_t *pcap)
17004fb2745SSam Leffler {
171a8e07101SRui Paulo if (pcap->opt.rfmon) {
172a8e07101SRui Paulo /*
173a8e07101SRui Paulo * No monitor mode on DOS.
174a8e07101SRui Paulo */
175a8e07101SRui Paulo return (PCAP_ERROR_RFMON_NOTSUP);
17604fb2745SSam Leffler }
17704fb2745SSam Leffler
178b00ab754SHans Petter Selasky /*
179b00ab754SHans Petter Selasky * Turn a negative snapshot value (invalid), a snapshot value of
180b00ab754SHans Petter Selasky * 0 (unspecified), or a value bigger than the normal maximum
181b00ab754SHans Petter Selasky * value, into the maximum allowed value.
182b00ab754SHans Petter Selasky *
183b00ab754SHans Petter Selasky * If some application really *needs* a bigger snapshot
184b00ab754SHans Petter Selasky * length, we should just increase MAXIMUM_SNAPLEN.
185b00ab754SHans Petter Selasky */
186b00ab754SHans Petter Selasky if (pcap->snapshot <= 0 || pcap->snapshot > MAXIMUM_SNAPLEN)
187b00ab754SHans Petter Selasky pcap->snapshot = MAXIMUM_SNAPLEN;
188b00ab754SHans Petter Selasky
189a8e07101SRui Paulo if (pcap->snapshot < ETH_MIN+8)
190a8e07101SRui Paulo pcap->snapshot = ETH_MIN+8;
191a8e07101SRui Paulo
192a8e07101SRui Paulo if (pcap->snapshot > ETH_MAX) /* silently accept and truncate large MTUs */
193a8e07101SRui Paulo pcap->snapshot = ETH_MAX;
194a8e07101SRui Paulo
19504fb2745SSam Leffler pcap->linktype = DLT_EN10MB; /* !! */
196a8e07101SRui Paulo pcap->cleanup_op = pcap_cleanup_dos;
19704fb2745SSam Leffler pcap->read_op = pcap_read_dos;
19804fb2745SSam Leffler pcap->stats_op = pcap_stats_dos;
19904fb2745SSam Leffler pcap->inject_op = pcap_sendpacket_dos;
20004fb2745SSam Leffler pcap->setfilter_op = pcap_setfilter_dos;
201ee2dd488SSam Leffler pcap->setdirection_op = NULL; /* Not implemented.*/
20204fb2745SSam Leffler pcap->fd = ++ref_count;
20304fb2745SSam Leffler
204ada6f083SXin LI pcap->bufsize = ETH_MAX+100; /* add some margin */
205ada6f083SXin LI pcap->buffer = calloc (pcap->bufsize, 1);
206ada6f083SXin LI
20704fb2745SSam Leffler if (pcap->fd == 1) /* first time we're called */
20804fb2745SSam Leffler {
209ada6f083SXin LI if (!init_watt32(pcap, pcap->opt.device, pcap->errbuf) ||
210ada6f083SXin LI !first_init(pcap->opt.device, pcap->errbuf, pcap->opt.promisc))
21104fb2745SSam Leffler {
212b00ab754SHans Petter Selasky /* XXX - free pcap->buffer? */
213a8e07101SRui Paulo return (PCAP_ERROR);
21404fb2745SSam Leffler }
21504fb2745SSam Leffler atexit (close_driver);
21604fb2745SSam Leffler }
217ada6f083SXin LI else if (stricmp(active_dev->name,pcap->opt.device))
21804fb2745SSam Leffler {
2196f9cba8fSJoseph Mingrone snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
22004fb2745SSam Leffler "Cannot use different devices simultaneously "
221ada6f083SXin LI "(`%s' vs. `%s')", active_dev->name, pcap->opt.device);
222b00ab754SHans Petter Selasky /* XXX - free pcap->buffer? */
223a8e07101SRui Paulo return (PCAP_ERROR);
22404fb2745SSam Leffler }
22504fb2745SSam Leffler handle_to_device [pcap->fd-1] = active_dev;
226a8e07101SRui Paulo return (0);
22704fb2745SSam Leffler }
22804fb2745SSam Leffler
22904fb2745SSam Leffler /*
23004fb2745SSam Leffler * Poll the receiver queue and call the pcap callback-handler
23104fb2745SSam Leffler * with the packet.
23204fb2745SSam Leffler */
23304fb2745SSam Leffler static int
pcap_read_one(pcap_t * p,pcap_handler callback,u_char * data)23404fb2745SSam Leffler pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
23504fb2745SSam Leffler {
236681ed54cSXin LI struct pcap_dos *pd = p->priv;
23704fb2745SSam Leffler struct pcap_pkthdr pcap;
238681ed54cSXin LI struct timeval now, expiry = { 0,0 };
23904fb2745SSam Leffler int rx_len = 0;
24004fb2745SSam Leffler
241681ed54cSXin LI if (p->opt.timeout > 0)
24204fb2745SSam Leffler {
24304fb2745SSam Leffler gettimeofday2 (&now, NULL);
244681ed54cSXin LI expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout;
24504fb2745SSam Leffler expiry.tv_sec = now.tv_sec;
24604fb2745SSam Leffler while (expiry.tv_usec >= 1000000L)
24704fb2745SSam Leffler {
24804fb2745SSam Leffler expiry.tv_usec -= 1000000L;
24904fb2745SSam Leffler expiry.tv_sec++;
25004fb2745SSam Leffler }
25104fb2745SSam Leffler }
25204fb2745SSam Leffler
253*afdbf109SJoseph Mingrone while (!exc_occurred)
25404fb2745SSam Leffler {
25504fb2745SSam Leffler volatile struct device *dev; /* might be reset by sig_handler */
25604fb2745SSam Leffler
25704fb2745SSam Leffler dev = get_device (p->fd);
25804fb2745SSam Leffler if (!dev)
25904fb2745SSam Leffler break;
26004fb2745SSam Leffler
26104fb2745SSam Leffler PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf);
26204fb2745SSam Leffler FLUSHK();
26304fb2745SSam Leffler
26404fb2745SSam Leffler /* If driver has a zero-copy receive facility, peek at the queue,
26504fb2745SSam Leffler * filter it, do the callback and release the buffer.
26604fb2745SSam Leffler */
26704fb2745SSam Leffler if (dev->peek_rx_buf)
26804fb2745SSam Leffler {
26904fb2745SSam Leffler PCAP_ASSERT (dev->release_rx_buf);
270ada6f083SXin LI rx_len = (*dev->peek_rx_buf) (&p->buffer);
27104fb2745SSam Leffler }
27204fb2745SSam Leffler else
27304fb2745SSam Leffler {
274ada6f083SXin LI rx_len = (*dev->copy_rx_buf) (p->buffer, p->snapshot);
27504fb2745SSam Leffler }
27604fb2745SSam Leffler
27704fb2745SSam Leffler if (rx_len > 0) /* got a packet */
27804fb2745SSam Leffler {
27904fb2745SSam Leffler mac_count++;
28004fb2745SSam Leffler
28104fb2745SSam Leffler FLUSHK();
28204fb2745SSam Leffler
28304fb2745SSam Leffler pcap.caplen = min (rx_len, p->snapshot);
28404fb2745SSam Leffler pcap.len = rx_len;
28504fb2745SSam Leffler
28604fb2745SSam Leffler if (callback &&
2876f9cba8fSJoseph Mingrone (!p->fcode.bf_insns || pcap_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen)))
28804fb2745SSam Leffler {
28904fb2745SSam Leffler filter_count++;
29004fb2745SSam Leffler
29104fb2745SSam Leffler /* Fix-me!! Should be time of arrival. Not time of
29204fb2745SSam Leffler * capture.
29304fb2745SSam Leffler */
29404fb2745SSam Leffler gettimeofday2 (&pcap.ts, NULL);
295ada6f083SXin LI (*callback) (data, &pcap, p->buffer);
29604fb2745SSam Leffler }
29704fb2745SSam Leffler
29804fb2745SSam Leffler if (dev->release_rx_buf)
299ada6f083SXin LI (*dev->release_rx_buf) (p->buffer);
30004fb2745SSam Leffler
30104fb2745SSam Leffler if (pcap_pkt_debug > 0)
30204fb2745SSam Leffler {
30304fb2745SSam Leffler if (callback == watt32_recv_hook)
30404fb2745SSam Leffler dbug_write ("pcap_recv_hook\n");
30504fb2745SSam Leffler else dbug_write ("pcap_read_op\n");
30604fb2745SSam Leffler }
30704fb2745SSam Leffler FLUSHK();
30804fb2745SSam Leffler return (1);
30904fb2745SSam Leffler }
31004fb2745SSam Leffler
311ada6f083SXin LI /* Has "pcap_breakloop()" been called?
312ada6f083SXin LI */
313ada6f083SXin LI if (p->break_loop) {
314ada6f083SXin LI /*
315ada6f083SXin LI * Yes - clear the flag that indicates that it
316ada6f083SXin LI * has, and return -2 to indicate that we were
317ada6f083SXin LI * told to break out of the loop.
318ada6f083SXin LI */
319ada6f083SXin LI p->break_loop = 0;
320ada6f083SXin LI return (-2);
321ada6f083SXin LI }
322ada6f083SXin LI
323681ed54cSXin LI /* If not to wait for a packet or pcap_cleanup_dos() called from
32404fb2745SSam Leffler * e.g. SIGINT handler, exit loop now.
32504fb2745SSam Leffler */
326681ed54cSXin LI if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0)
32704fb2745SSam Leffler break;
32804fb2745SSam Leffler
32904fb2745SSam Leffler gettimeofday2 (&now, NULL);
33004fb2745SSam Leffler
33104fb2745SSam Leffler if (timercmp(&now, &expiry, >))
33204fb2745SSam Leffler break;
33304fb2745SSam Leffler
33404fb2745SSam Leffler #ifndef DJGPP
33504fb2745SSam Leffler kbhit(); /* a real CPU hog */
33604fb2745SSam Leffler #endif
33704fb2745SSam Leffler
338ada6f083SXin LI if (pd->wait_proc)
339ada6f083SXin LI (*pd->wait_proc)(); /* call yield func */
34004fb2745SSam Leffler }
34104fb2745SSam Leffler
34204fb2745SSam Leffler if (rx_len < 0) /* receive error */
34304fb2745SSam Leffler {
344681ed54cSXin LI pd->stat.ps_drop++;
34504fb2745SSam Leffler #ifdef USE_32BIT_DRIVERS
34604fb2745SSam Leffler if (pcap_pkt_debug > 1)
34704fb2745SSam Leffler printk ("pkt-err %s\n", pktInfo.error);
34804fb2745SSam Leffler #endif
34904fb2745SSam Leffler return (-1);
35004fb2745SSam Leffler }
35104fb2745SSam Leffler return (0);
35204fb2745SSam Leffler }
35304fb2745SSam Leffler
35404fb2745SSam Leffler static int
pcap_read_dos(pcap_t * p,int cnt,pcap_handler callback,u_char * data)35504fb2745SSam Leffler pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
35604fb2745SSam Leffler {
35704fb2745SSam Leffler int rc, num = 0;
35804fb2745SSam Leffler
3596f9cba8fSJoseph Mingrone /*
3606f9cba8fSJoseph Mingrone * This can conceivably process more than INT_MAX packets,
3616f9cba8fSJoseph Mingrone * which would overflow the packet count, causing it either
3626f9cba8fSJoseph Mingrone * to look like a negative number, and thus cause us to
3636f9cba8fSJoseph Mingrone * return a value that looks like an error, or overflow
3646f9cba8fSJoseph Mingrone * back into positive territory, and thus cause us to
3656f9cba8fSJoseph Mingrone * return a too-low count.
3666f9cba8fSJoseph Mingrone *
3676f9cba8fSJoseph Mingrone * Therefore, if the packet count is unlimited, we clip
3686f9cba8fSJoseph Mingrone * it at INT_MAX; this routine is not expected to
3696f9cba8fSJoseph Mingrone * process packets indefinitely, so that's not an issue.
3706f9cba8fSJoseph Mingrone */
3716f9cba8fSJoseph Mingrone if (PACKET_COUNT_IS_UNLIMITED(cnt))
3726f9cba8fSJoseph Mingrone cnt = INT_MAX;
3736f9cba8fSJoseph Mingrone
3746f9cba8fSJoseph Mingrone while (num <= cnt)
37504fb2745SSam Leffler {
37604fb2745SSam Leffler if (p->fd <= 0)
37704fb2745SSam Leffler return (-1);
37804fb2745SSam Leffler rc = pcap_read_one (p, callback, data);
37904fb2745SSam Leffler if (rc > 0)
38004fb2745SSam Leffler num++;
38104fb2745SSam Leffler if (rc < 0)
38204fb2745SSam Leffler break;
38304fb2745SSam Leffler _w32_os_yield(); /* allow SIGINT generation, yield to Win95/NT */
38404fb2745SSam Leffler }
38504fb2745SSam Leffler return (num);
38604fb2745SSam Leffler }
38704fb2745SSam Leffler
38804fb2745SSam Leffler /*
38904fb2745SSam Leffler * Return network statistics
39004fb2745SSam Leffler */
pcap_stats_dos(pcap_t * p,struct pcap_stat * ps)39104fb2745SSam Leffler static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
39204fb2745SSam Leffler {
39304fb2745SSam Leffler struct net_device_stats *stats;
394681ed54cSXin LI struct pcap_dos *pd;
39504fb2745SSam Leffler struct device *dev = p ? get_device(p->fd) : NULL;
39604fb2745SSam Leffler
39704fb2745SSam Leffler if (!dev)
39804fb2745SSam Leffler {
39904fb2745SSam Leffler strcpy (p->errbuf, "illegal pcap handle");
40004fb2745SSam Leffler return (-1);
40104fb2745SSam Leffler }
40204fb2745SSam Leffler
40304fb2745SSam Leffler if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL)
40404fb2745SSam Leffler {
40504fb2745SSam Leffler strcpy (p->errbuf, "device statistics not available");
40604fb2745SSam Leffler return (-1);
40704fb2745SSam Leffler }
40804fb2745SSam Leffler
40904fb2745SSam Leffler FLUSHK();
41004fb2745SSam Leffler
411681ed54cSXin LI pd = p->priv;
412681ed54cSXin LI pd->stat.ps_recv = stats->rx_packets;
413681ed54cSXin LI pd->stat.ps_drop += stats->rx_missed_errors;
414681ed54cSXin LI pd->stat.ps_ifdrop = stats->rx_dropped + /* queue full */
41504fb2745SSam Leffler stats->rx_errors; /* HW errors */
41604fb2745SSam Leffler if (ps)
417681ed54cSXin LI *ps = pd->stat;
41804fb2745SSam Leffler
41904fb2745SSam Leffler return (0);
42004fb2745SSam Leffler }
42104fb2745SSam Leffler
42204fb2745SSam Leffler /*
42304fb2745SSam Leffler * Return detailed network/device statistics.
42404fb2745SSam Leffler * May be called after 'dev->close' is called.
42504fb2745SSam Leffler */
pcap_stats_ex(pcap_t * p,struct pcap_stat_ex * se)42604fb2745SSam Leffler int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se)
42704fb2745SSam Leffler {
42804fb2745SSam Leffler struct device *dev = p ? get_device (p->fd) : NULL;
42904fb2745SSam Leffler
43004fb2745SSam Leffler if (!dev || !dev->get_stats)
43104fb2745SSam Leffler {
43257e22627SCy Schubert pcap_strlcpy (p->errbuf, "detailed device statistics not available",
43304fb2745SSam Leffler PCAP_ERRBUF_SIZE);
43404fb2745SSam Leffler return (-1);
43504fb2745SSam Leffler }
43604fb2745SSam Leffler
43704fb2745SSam Leffler if (!strnicmp(dev->name,"pkt",3))
43804fb2745SSam Leffler {
43957e22627SCy Schubert pcap_strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
44004fb2745SSam Leffler PCAP_ERRBUF_SIZE);
44104fb2745SSam Leffler return (-1);
44204fb2745SSam Leffler }
44304fb2745SSam Leffler memcpy (se, (*dev->get_stats)(dev), sizeof(*se));
44404fb2745SSam Leffler return (0);
44504fb2745SSam Leffler }
44604fb2745SSam Leffler
44704fb2745SSam Leffler /*
44804fb2745SSam Leffler * Simply store the filter-code for the pcap_read_dos() callback
44904fb2745SSam Leffler * Some day the filter-code could be handed down to the active
45004fb2745SSam Leffler * device (pkt_rx1.s or 32-bit device interrupt handler).
45104fb2745SSam Leffler */
pcap_setfilter_dos(pcap_t * p,struct bpf_program * fp)45204fb2745SSam Leffler static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp)
45304fb2745SSam Leffler {
45404fb2745SSam Leffler if (!p)
45504fb2745SSam Leffler return (-1);
45604fb2745SSam Leffler p->fcode = *fp;
45704fb2745SSam Leffler return (0);
45804fb2745SSam Leffler }
45904fb2745SSam Leffler
46004fb2745SSam Leffler /*
46104fb2745SSam Leffler * Return # of packets received in pcap_read_dos()
46204fb2745SSam Leffler */
pcap_mac_packets(void)46304fb2745SSam Leffler u_long pcap_mac_packets (void)
46404fb2745SSam Leffler {
46504fb2745SSam Leffler return (mac_count);
46604fb2745SSam Leffler }
46704fb2745SSam Leffler
46804fb2745SSam Leffler /*
46904fb2745SSam Leffler * Return # of packets passed through filter in pcap_read_dos()
47004fb2745SSam Leffler */
pcap_filter_packets(void)47104fb2745SSam Leffler u_long pcap_filter_packets (void)
47204fb2745SSam Leffler {
47304fb2745SSam Leffler return (filter_count);
47404fb2745SSam Leffler }
47504fb2745SSam Leffler
47604fb2745SSam Leffler /*
47704fb2745SSam Leffler * Close pcap device. Not called for offline captures.
47804fb2745SSam Leffler */
pcap_cleanup_dos(pcap_t * p)479a8e07101SRui Paulo static void pcap_cleanup_dos (pcap_t *p)
48004fb2745SSam Leffler {
481681ed54cSXin LI struct pcap_dos *pd;
482681ed54cSXin LI
483*afdbf109SJoseph Mingrone if (!exc_occurred)
48404fb2745SSam Leffler {
485681ed54cSXin LI pd = p->priv;
48604fb2745SSam Leffler if (pcap_stats(p,NULL) < 0)
487681ed54cSXin LI pd->stat.ps_drop = 0;
48804fb2745SSam Leffler if (!get_device(p->fd))
48904fb2745SSam Leffler return;
49004fb2745SSam Leffler
49104fb2745SSam Leffler handle_to_device [p->fd-1] = NULL;
49204fb2745SSam Leffler p->fd = 0;
49304fb2745SSam Leffler if (ref_count > 0)
49404fb2745SSam Leffler ref_count--;
49504fb2745SSam Leffler if (ref_count > 0)
49604fb2745SSam Leffler return;
49704fb2745SSam Leffler }
49804fb2745SSam Leffler close_driver();
499b00ab754SHans Petter Selasky /* XXX - call pcap_cleanup_live_common? */
50004fb2745SSam Leffler }
50104fb2745SSam Leffler
50204fb2745SSam Leffler /*
50304fb2745SSam Leffler * Return the name of the 1st network interface,
50404fb2745SSam Leffler * or NULL if none can be found.
50504fb2745SSam Leffler */
pcap_lookupdev(char * ebuf)50604fb2745SSam Leffler char *pcap_lookupdev (char *ebuf)
50704fb2745SSam Leffler {
50804fb2745SSam Leffler struct device *dev;
50904fb2745SSam Leffler
51004fb2745SSam Leffler #ifdef USE_32BIT_DRIVERS
51104fb2745SSam Leffler init_32bit();
51204fb2745SSam Leffler #endif
51304fb2745SSam Leffler
51404fb2745SSam Leffler for (dev = (struct device*)dev_base; dev; dev = dev->next)
51504fb2745SSam Leffler {
51604fb2745SSam Leffler PCAP_ASSERT (dev->probe);
51704fb2745SSam Leffler
51804fb2745SSam Leffler if ((*dev->probe)(dev))
51904fb2745SSam Leffler {
52004fb2745SSam Leffler FLUSHK();
52104fb2745SSam Leffler probed_dev = (struct device*) dev; /* remember last probed device */
52204fb2745SSam Leffler return (char*) dev->name;
52304fb2745SSam Leffler }
52404fb2745SSam Leffler }
52504fb2745SSam Leffler
52604fb2745SSam Leffler if (ebuf)
52704fb2745SSam Leffler strcpy (ebuf, "No driver found");
52804fb2745SSam Leffler return (NULL);
52904fb2745SSam Leffler }
53004fb2745SSam Leffler
53104fb2745SSam Leffler /*
53204fb2745SSam Leffler * Gets localnet & netmask from Watt-32.
53304fb2745SSam Leffler */
pcap_lookupnet(const char * device,bpf_u_int32 * localnet,bpf_u_int32 * netmask,char * errbuf)53404fb2745SSam Leffler int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
53504fb2745SSam Leffler bpf_u_int32 *netmask, char *errbuf)
53604fb2745SSam Leffler {
537ada6f083SXin LI DWORD mask, net;
538ada6f083SXin LI
53904fb2745SSam Leffler if (!_watt_is_init)
54004fb2745SSam Leffler {
541a8e07101SRui Paulo strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
54204fb2745SSam Leffler "called first");
54304fb2745SSam Leffler return (-1);
54404fb2745SSam Leffler }
54504fb2745SSam Leffler
546ada6f083SXin LI mask = _w32_sin_mask;
547ada6f083SXin LI net = my_ip_addr & mask;
548ada6f083SXin LI if (net == 0)
54904fb2745SSam Leffler {
55004fb2745SSam Leffler if (IN_CLASSA(*netmask))
551ada6f083SXin LI net = IN_CLASSA_NET;
55204fb2745SSam Leffler else if (IN_CLASSB(*netmask))
553ada6f083SXin LI net = IN_CLASSB_NET;
55404fb2745SSam Leffler else if (IN_CLASSC(*netmask))
555ada6f083SXin LI net = IN_CLASSC_NET;
55604fb2745SSam Leffler else
55704fb2745SSam Leffler {
5586f9cba8fSJoseph Mingrone snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask);
55904fb2745SSam Leffler return (-1);
56004fb2745SSam Leffler }
56104fb2745SSam Leffler }
562ada6f083SXin LI *localnet = htonl (net);
563ada6f083SXin LI *netmask = htonl (mask);
564ada6f083SXin LI
56504fb2745SSam Leffler ARGSUSED (device);
56604fb2745SSam Leffler return (0);
56704fb2745SSam Leffler }
56804fb2745SSam Leffler
56904fb2745SSam Leffler /*
57004fb2745SSam Leffler * Get a list of all interfaces that are present and that we probe okay.
57104fb2745SSam Leffler * Returns -1 on error, 0 otherwise.
5726f9cba8fSJoseph Mingrone * The list may be NULL empty if no interfaces were up and could be opened.
57304fb2745SSam Leffler */
pcap_platform_finddevs(pcap_if_list_t * devlistp,char * errbuf)574b00ab754SHans Petter Selasky int pcap_platform_finddevs (pcap_if_list_t *devlistp, char *errbuf)
57504fb2745SSam Leffler {
57604fb2745SSam Leffler struct device *dev;
577b00ab754SHans Petter Selasky pcap_if_t *curdev;
578b00ab754SHans Petter Selasky #if 0 /* Pkt drivers should have no addresses */
579ada6f083SXin LI struct sockaddr_in sa_ll_1, sa_ll_2;
58004fb2745SSam Leffler struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
581b00ab754SHans Petter Selasky #endif
58204fb2745SSam Leffler int ret = 0;
583b00ab754SHans Petter Selasky int found = 0;
58404fb2745SSam Leffler
58504fb2745SSam Leffler for (dev = (struct device*)dev_base; dev; dev = dev->next)
58604fb2745SSam Leffler {
58704fb2745SSam Leffler PCAP_ASSERT (dev->probe);
58804fb2745SSam Leffler
58904fb2745SSam Leffler if (!(*dev->probe)(dev))
59004fb2745SSam Leffler continue;
59104fb2745SSam Leffler
59204fb2745SSam Leffler PCAP_ASSERT (dev->close); /* set by probe routine */
59304fb2745SSam Leffler FLUSHK();
59404fb2745SSam Leffler (*dev->close) (dev);
59504fb2745SSam Leffler
596b00ab754SHans Petter Selasky /*
597b00ab754SHans Petter Selasky * XXX - find out whether it's up or running? Does that apply here?
598b00ab754SHans Petter Selasky * Can we find out if anything's plugged into the adapter, if it's
599b00ab754SHans Petter Selasky * a wired device, and set PCAP_IF_CONNECTION_STATUS_CONNECTED
600b00ab754SHans Petter Selasky * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
601b00ab754SHans Petter Selasky */
602*afdbf109SJoseph Mingrone if ((curdev = pcap_add_dev(devlistp, dev->name, 0,
603b00ab754SHans Petter Selasky dev->long_name, errbuf)) == NULL)
604b00ab754SHans Petter Selasky {
605b00ab754SHans Petter Selasky ret = -1;
606b00ab754SHans Petter Selasky break;
607b00ab754SHans Petter Selasky }
608b00ab754SHans Petter Selasky found = 1;
609b00ab754SHans Petter Selasky #if 0 /* Pkt drivers should have no addresses */
61004fb2745SSam Leffler memset (&sa_ll_1, 0, sizeof(sa_ll_1));
61104fb2745SSam Leffler memset (&sa_ll_2, 0, sizeof(sa_ll_2));
612ada6f083SXin LI sa_ll_1.sin_family = AF_INET;
613ada6f083SXin LI sa_ll_2.sin_family = AF_INET;
61404fb2745SSam Leffler
61504fb2745SSam Leffler addr = (struct sockaddr*) &sa_ll_1;
61604fb2745SSam Leffler netmask = (struct sockaddr*) &sa_ll_1;
61704fb2745SSam Leffler dstaddr = (struct sockaddr*) &sa_ll_1;
61804fb2745SSam Leffler broadaddr = (struct sockaddr*) &sa_ll_2;
619ada6f083SXin LI memset (&sa_ll_2.sin_addr, 0xFF, sizeof(sa_ll_2.sin_addr));
62004fb2745SSam Leffler
621*afdbf109SJoseph Mingrone if (pcap_add_addr_to_dev(curdev, addr, sizeof(*addr),
622b00ab754SHans Petter Selasky netmask, sizeof(*netmask),
623b00ab754SHans Petter Selasky broadaddr, sizeof(*broadaddr),
624b00ab754SHans Petter Selasky dstaddr, sizeof(*dstaddr), errbuf) < 0)
62504fb2745SSam Leffler {
62604fb2745SSam Leffler ret = -1;
62704fb2745SSam Leffler break;
62804fb2745SSam Leffler }
629ada6f083SXin LI #endif
63004fb2745SSam Leffler }
63104fb2745SSam Leffler
632b00ab754SHans Petter Selasky if (ret == 0 && !found)
63304fb2745SSam Leffler strcpy (errbuf, "No drivers found");
63404fb2745SSam Leffler
63504fb2745SSam Leffler return (ret);
63604fb2745SSam Leffler }
63704fb2745SSam Leffler
63804fb2745SSam Leffler /*
63904fb2745SSam Leffler * pcap_assert() is mainly used for debugging
64004fb2745SSam Leffler */
pcap_assert(const char * what,const char * file,unsigned line)64104fb2745SSam Leffler void pcap_assert (const char *what, const char *file, unsigned line)
64204fb2745SSam Leffler {
64304fb2745SSam Leffler FLUSHK();
64404fb2745SSam Leffler fprintf (stderr, "%s (%u): Assertion \"%s\" failed\n",
64504fb2745SSam Leffler file, line, what);
64604fb2745SSam Leffler close_driver();
64704fb2745SSam Leffler _exit (-1);
64804fb2745SSam Leffler }
64904fb2745SSam Leffler
65004fb2745SSam Leffler /*
65104fb2745SSam Leffler * For pcap_offline_read(): wait and yield between printing packets
65204fb2745SSam Leffler * to simulate the pace packets where actually recorded.
65304fb2745SSam Leffler */
pcap_set_wait(pcap_t * p,void (* yield)(void),int wait)65404fb2745SSam Leffler void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
65504fb2745SSam Leffler {
65604fb2745SSam Leffler if (p)
65704fb2745SSam Leffler {
658ada6f083SXin LI struct pcap_dos *pd = p->priv;
659ada6f083SXin LI
660681ed54cSXin LI pd->wait_proc = yield;
661681ed54cSXin LI p->opt.timeout = wait;
66204fb2745SSam Leffler }
66304fb2745SSam Leffler }
66404fb2745SSam Leffler
66504fb2745SSam Leffler /*
666*afdbf109SJoseph Mingrone * Initialize a named network device.
66704fb2745SSam Leffler */
66804fb2745SSam Leffler static struct device *
open_driver(const char * dev_name,char * ebuf,int promisc)66904fb2745SSam Leffler open_driver (const char *dev_name, char *ebuf, int promisc)
67004fb2745SSam Leffler {
67104fb2745SSam Leffler struct device *dev;
67204fb2745SSam Leffler
67304fb2745SSam Leffler for (dev = (struct device*)dev_base; dev; dev = dev->next)
67404fb2745SSam Leffler {
67504fb2745SSam Leffler PCAP_ASSERT (dev->name);
67604fb2745SSam Leffler
67704fb2745SSam Leffler if (strcmp (dev_name,dev->name))
67804fb2745SSam Leffler continue;
67904fb2745SSam Leffler
68004fb2745SSam Leffler if (!probed_dev) /* user didn't call pcap_lookupdev() first */
68104fb2745SSam Leffler {
68204fb2745SSam Leffler PCAP_ASSERT (dev->probe);
68304fb2745SSam Leffler
68404fb2745SSam Leffler if (!(*dev->probe)(dev)) /* call the xx_probe() function */
68504fb2745SSam Leffler {
6866f9cba8fSJoseph Mingrone snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to detect device `%s'", dev_name);
68704fb2745SSam Leffler return (NULL);
68804fb2745SSam Leffler }
68904fb2745SSam Leffler probed_dev = dev; /* device is probed okay and may be used */
69004fb2745SSam Leffler }
69104fb2745SSam Leffler else if (dev != probed_dev)
69204fb2745SSam Leffler {
69304fb2745SSam Leffler goto not_probed;
69404fb2745SSam Leffler }
69504fb2745SSam Leffler
69604fb2745SSam Leffler FLUSHK();
69704fb2745SSam Leffler
69804fb2745SSam Leffler /* Select what traffic to receive
69904fb2745SSam Leffler */
70004fb2745SSam Leffler if (promisc)
70104fb2745SSam Leffler dev->flags |= (IFF_ALLMULTI | IFF_PROMISC);
70204fb2745SSam Leffler else dev->flags &= ~(IFF_ALLMULTI | IFF_PROMISC);
70304fb2745SSam Leffler
70404fb2745SSam Leffler PCAP_ASSERT (dev->open);
70504fb2745SSam Leffler
70604fb2745SSam Leffler if (!(*dev->open)(dev))
70704fb2745SSam Leffler {
7086f9cba8fSJoseph Mingrone snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name);
70904fb2745SSam Leffler if (pktInfo.error && !strncmp(dev->name,"pkt",3))
71004fb2745SSam Leffler {
71104fb2745SSam Leffler strcat (ebuf, ": ");
71204fb2745SSam Leffler strcat (ebuf, pktInfo.error);
71304fb2745SSam Leffler }
71404fb2745SSam Leffler return (NULL);
71504fb2745SSam Leffler }
71604fb2745SSam Leffler
7176f9cba8fSJoseph Mingrone /* Some devices need this to operate in promiscuous mode
71804fb2745SSam Leffler */
71904fb2745SSam Leffler if (promisc && dev->set_multicast_list)
72004fb2745SSam Leffler (*dev->set_multicast_list) (dev);
72104fb2745SSam Leffler
72204fb2745SSam Leffler active_dev = dev; /* remember our active device */
72304fb2745SSam Leffler break;
72404fb2745SSam Leffler }
72504fb2745SSam Leffler
72604fb2745SSam Leffler /* 'dev_name' not matched in 'dev_base' list.
72704fb2745SSam Leffler */
72804fb2745SSam Leffler if (!dev)
72904fb2745SSam Leffler {
7306f9cba8fSJoseph Mingrone snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name);
73104fb2745SSam Leffler return (NULL);
73204fb2745SSam Leffler }
73304fb2745SSam Leffler
73404fb2745SSam Leffler not_probed:
73504fb2745SSam Leffler if (!probed_dev)
73604fb2745SSam Leffler {
7376f9cba8fSJoseph Mingrone snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name);
73804fb2745SSam Leffler return (NULL);
73904fb2745SSam Leffler }
74004fb2745SSam Leffler return (dev);
74104fb2745SSam Leffler }
74204fb2745SSam Leffler
74304fb2745SSam Leffler /*
744*afdbf109SJoseph Mingrone * Deinitialize MAC driver.
74504fb2745SSam Leffler * Set receive mode back to default mode.
74604fb2745SSam Leffler */
close_driver(void)74704fb2745SSam Leffler static void close_driver (void)
74804fb2745SSam Leffler {
74904fb2745SSam Leffler /* !!todo: loop over all 'handle_to_device[]' ? */
75004fb2745SSam Leffler struct device *dev = active_dev;
75104fb2745SSam Leffler
75204fb2745SSam Leffler if (dev && dev->close)
75304fb2745SSam Leffler {
75404fb2745SSam Leffler (*dev->close) (dev);
75504fb2745SSam Leffler FLUSHK();
75604fb2745SSam Leffler }
75704fb2745SSam Leffler
75804fb2745SSam Leffler active_dev = NULL;
75904fb2745SSam Leffler
76004fb2745SSam Leffler #ifdef USE_32BIT_DRIVERS
76104fb2745SSam Leffler if (rx_pool)
76204fb2745SSam Leffler {
76304fb2745SSam Leffler k_free (rx_pool);
76404fb2745SSam Leffler rx_pool = NULL;
76504fb2745SSam Leffler }
76604fb2745SSam Leffler if (dev)
76704fb2745SSam Leffler pcibios_exit();
76804fb2745SSam Leffler #endif
76904fb2745SSam Leffler }
77004fb2745SSam Leffler
77104fb2745SSam Leffler
77204fb2745SSam Leffler #ifdef __DJGPP__
setup_signals(void (* handler)(int))77304fb2745SSam Leffler static void setup_signals (void (*handler)(int))
77404fb2745SSam Leffler {
77504fb2745SSam Leffler signal (SIGSEGV,handler);
77604fb2745SSam Leffler signal (SIGILL, handler);
77704fb2745SSam Leffler signal (SIGFPE, handler);
77804fb2745SSam Leffler }
77904fb2745SSam Leffler
exc_handler(int sig)78004fb2745SSam Leffler static void exc_handler (int sig)
78104fb2745SSam Leffler {
78204fb2745SSam Leffler #ifdef USE_32BIT_DRIVERS
78304fb2745SSam Leffler if (active_dev->irq > 0) /* excludes IRQ 0 */
78404fb2745SSam Leffler {
78504fb2745SSam Leffler disable_irq (active_dev->irq);
78604fb2745SSam Leffler irq_eoi_cmd (active_dev->irq);
78704fb2745SSam Leffler _printk_safe = 1;
78804fb2745SSam Leffler }
78904fb2745SSam Leffler #endif
79004fb2745SSam Leffler
79104fb2745SSam Leffler switch (sig)
79204fb2745SSam Leffler {
79304fb2745SSam Leffler case SIGSEGV:
79404fb2745SSam Leffler fputs ("Catching SIGSEGV.\n", stderr);
79504fb2745SSam Leffler break;
79604fb2745SSam Leffler case SIGILL:
79704fb2745SSam Leffler fputs ("Catching SIGILL.\n", stderr);
79804fb2745SSam Leffler break;
79904fb2745SSam Leffler case SIGFPE:
80004fb2745SSam Leffler _fpreset();
80104fb2745SSam Leffler fputs ("Catching SIGFPE.\n", stderr);
80204fb2745SSam Leffler break;
80304fb2745SSam Leffler default:
80404fb2745SSam Leffler fprintf (stderr, "Catching signal %d.\n", sig);
80504fb2745SSam Leffler }
806*afdbf109SJoseph Mingrone exc_occurred = 1;
807ada6f083SXin LI close_driver();
80804fb2745SSam Leffler }
80904fb2745SSam Leffler #endif /* __DJGPP__ */
81004fb2745SSam Leffler
81104fb2745SSam Leffler
81204fb2745SSam Leffler /*
813a8e07101SRui Paulo * Open the pcap device for the first client calling pcap_activate()
81404fb2745SSam Leffler */
first_init(const char * name,char * ebuf,int promisc)81504fb2745SSam Leffler static int first_init (const char *name, char *ebuf, int promisc)
81604fb2745SSam Leffler {
81704fb2745SSam Leffler struct device *dev;
81804fb2745SSam Leffler
81904fb2745SSam Leffler #ifdef USE_32BIT_DRIVERS
82004fb2745SSam Leffler rx_pool = k_calloc (RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE);
82104fb2745SSam Leffler if (!rx_pool)
82204fb2745SSam Leffler {
82304fb2745SSam Leffler strcpy (ebuf, "Not enough memory (Rx pool)");
82404fb2745SSam Leffler return (0);
82504fb2745SSam Leffler }
82604fb2745SSam Leffler #endif
82704fb2745SSam Leffler
82804fb2745SSam Leffler #ifdef __DJGPP__
82904fb2745SSam Leffler setup_signals (exc_handler);
83004fb2745SSam Leffler #endif
83104fb2745SSam Leffler
83204fb2745SSam Leffler #ifdef USE_32BIT_DRIVERS
83304fb2745SSam Leffler init_32bit();
83404fb2745SSam Leffler #endif
83504fb2745SSam Leffler
83604fb2745SSam Leffler dev = open_driver (name, ebuf, promisc);
83704fb2745SSam Leffler if (!dev)
83804fb2745SSam Leffler {
83904fb2745SSam Leffler #ifdef USE_32BIT_DRIVERS
84004fb2745SSam Leffler k_free (rx_pool);
84104fb2745SSam Leffler rx_pool = NULL;
84204fb2745SSam Leffler #endif
84304fb2745SSam Leffler
84404fb2745SSam Leffler #ifdef __DJGPP__
84504fb2745SSam Leffler setup_signals (SIG_DFL);
84604fb2745SSam Leffler #endif
84704fb2745SSam Leffler return (0);
84804fb2745SSam Leffler }
84904fb2745SSam Leffler
85004fb2745SSam Leffler #ifdef USE_32BIT_DRIVERS
85104fb2745SSam Leffler /*
85204fb2745SSam Leffler * If driver is NOT a 16-bit "pkt/ndis" driver (having a 'copy_rx_buf'
853*afdbf109SJoseph Mingrone * set in it's probe handler), initialize near-memory ring-buffer for
85404fb2745SSam Leffler * the 32-bit device.
85504fb2745SSam Leffler */
85604fb2745SSam Leffler if (dev->copy_rx_buf == NULL)
85704fb2745SSam Leffler {
85804fb2745SSam Leffler dev->get_rx_buf = get_rxbuf;
85904fb2745SSam Leffler dev->peek_rx_buf = peek_rxbuf;
86004fb2745SSam Leffler dev->release_rx_buf = release_rxbuf;
86104fb2745SSam Leffler pktq_init (&dev->queue, RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE, rx_pool);
86204fb2745SSam Leffler }
86304fb2745SSam Leffler #endif
86404fb2745SSam Leffler return (1);
86504fb2745SSam Leffler }
86604fb2745SSam Leffler
86704fb2745SSam Leffler #ifdef USE_32BIT_DRIVERS
init_32bit(void)86804fb2745SSam Leffler static void init_32bit (void)
86904fb2745SSam Leffler {
87004fb2745SSam Leffler static int init_pci = 0;
87104fb2745SSam Leffler
87204fb2745SSam Leffler if (!_printk_file)
87304fb2745SSam Leffler _printk_init (64*1024, NULL); /* calls atexit(printk_exit) */
87404fb2745SSam Leffler
87504fb2745SSam Leffler if (!init_pci)
87604fb2745SSam Leffler (void)pci_init(); /* init BIOS32+PCI interface */
87704fb2745SSam Leffler init_pci = 1;
87804fb2745SSam Leffler }
87904fb2745SSam Leffler #endif
88004fb2745SSam Leffler
88104fb2745SSam Leffler
88204fb2745SSam Leffler /*
88304fb2745SSam Leffler * Hook functions for using Watt-32 together with pcap
88404fb2745SSam Leffler */
88504fb2745SSam Leffler static char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */
88604fb2745SSam Leffler static WORD etype;
88704fb2745SSam Leffler static pcap_t pcap_save;
88804fb2745SSam Leffler
watt32_recv_hook(u_char * dummy,const struct pcap_pkthdr * pcap,const u_char * buf)88904fb2745SSam Leffler static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
89004fb2745SSam Leffler const u_char *buf)
89104fb2745SSam Leffler {
89204fb2745SSam Leffler /* Fix me: assumes Ethernet II only */
89304fb2745SSam Leffler struct ether_header *ep = (struct ether_header*) buf;
89404fb2745SSam Leffler
89504fb2745SSam Leffler memcpy (rxbuf, buf, pcap->caplen);
89604fb2745SSam Leffler etype = ep->ether_type;
89704fb2745SSam Leffler ARGSUSED (dummy);
89804fb2745SSam Leffler }
89904fb2745SSam Leffler
90004fb2745SSam Leffler #if (WATTCP_VER >= 0x0224)
90104fb2745SSam Leffler /*
90204fb2745SSam Leffler * This function is used by Watt-32 to poll for a packet.
90304fb2745SSam Leffler * i.e. it's set to bypass _eth_arrived()
90404fb2745SSam Leffler */
pcap_recv_hook(WORD * type)90504fb2745SSam Leffler static void *pcap_recv_hook (WORD *type)
90604fb2745SSam Leffler {
90704fb2745SSam Leffler int len = pcap_read_dos (&pcap_save, 1, watt32_recv_hook, NULL);
90804fb2745SSam Leffler
90904fb2745SSam Leffler if (len < 0)
91004fb2745SSam Leffler return (NULL);
91104fb2745SSam Leffler
91204fb2745SSam Leffler *type = etype;
91304fb2745SSam Leffler return (void*) &rxbuf;
91404fb2745SSam Leffler }
91504fb2745SSam Leffler
91604fb2745SSam Leffler /*
91704fb2745SSam Leffler * This function is called by Watt-32 (via _eth_xmit_hook).
91804fb2745SSam Leffler * If dbug_init() was called, we should trace packets sent.
91904fb2745SSam Leffler */
pcap_xmit_hook(const void * buf,unsigned len)92004fb2745SSam Leffler static int pcap_xmit_hook (const void *buf, unsigned len)
92104fb2745SSam Leffler {
92204fb2745SSam Leffler int rc = 0;
92304fb2745SSam Leffler
92404fb2745SSam Leffler if (pcap_pkt_debug > 0)
92504fb2745SSam Leffler dbug_write ("pcap_xmit_hook: ");
92604fb2745SSam Leffler
92704fb2745SSam Leffler if (active_dev && active_dev->xmit)
92804fb2745SSam Leffler if ((*active_dev->xmit) (active_dev, buf, len) > 0)
92904fb2745SSam Leffler rc = len;
93004fb2745SSam Leffler
93104fb2745SSam Leffler if (pcap_pkt_debug > 0)
93204fb2745SSam Leffler dbug_write (rc ? "ok\n" : "fail\n");
93304fb2745SSam Leffler return (rc);
93404fb2745SSam Leffler }
93504fb2745SSam Leffler #endif
93604fb2745SSam Leffler
pcap_sendpacket_dos(pcap_t * p,const void * buf,size_t len)93704fb2745SSam Leffler static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len)
93804fb2745SSam Leffler {
93904fb2745SSam Leffler struct device *dev = p ? get_device(p->fd) : NULL;
94004fb2745SSam Leffler
94104fb2745SSam Leffler if (!dev || !dev->xmit)
94204fb2745SSam Leffler return (-1);
94304fb2745SSam Leffler return (*dev->xmit) (dev, buf, len);
94404fb2745SSam Leffler }
94504fb2745SSam Leffler
94604fb2745SSam Leffler /*
94704fb2745SSam Leffler * This function is called by Watt-32 in tcp_post_init().
94804fb2745SSam Leffler * We should prevent Watt-32 from using BOOTP/DHCP/RARP etc.
94904fb2745SSam Leffler */
95004fb2745SSam Leffler static void (*prev_post_hook) (void);
95104fb2745SSam Leffler
pcap_init_hook(void)95204fb2745SSam Leffler static void pcap_init_hook (void)
95304fb2745SSam Leffler {
95404fb2745SSam Leffler _w32__bootp_on = _w32__dhcp_on = _w32__rarp_on = 0;
95504fb2745SSam Leffler _w32__do_mask_req = 0;
95604fb2745SSam Leffler _w32_dynamic_host = 0;
95704fb2745SSam Leffler if (prev_post_hook)
95804fb2745SSam Leffler (*prev_post_hook)();
95904fb2745SSam Leffler }
96004fb2745SSam Leffler
96104fb2745SSam Leffler /*
9626f9cba8fSJoseph Mingrone * Suppress PRINT message from Watt-32's sock_init()
96304fb2745SSam Leffler */
null_print(void)96404fb2745SSam Leffler static void null_print (void) {}
96504fb2745SSam Leffler
96604fb2745SSam Leffler /*
96704fb2745SSam Leffler * To use features of Watt-32 (netdb functions and socket etc.)
96804fb2745SSam Leffler * we must call sock_init(). But we set various hooks to prevent
96904fb2745SSam Leffler * using normal PKTDRVR functions in pcpkt.c. This should hopefully
97004fb2745SSam Leffler * make Watt-32 and pcap co-operate.
97104fb2745SSam Leffler */
init_watt32(struct pcap * pcap,const char * dev_name,char * err_buf)97204fb2745SSam Leffler static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
97304fb2745SSam Leffler {
97404fb2745SSam Leffler char *env;
97504fb2745SSam Leffler int rc, MTU, has_ip_addr;
97604fb2745SSam Leffler int using_pktdrv = 1;
97704fb2745SSam Leffler
97804fb2745SSam Leffler /* If user called sock_init() first, we need to reinit in
97904fb2745SSam Leffler * order to open debug/trace-file properly
98004fb2745SSam Leffler */
98104fb2745SSam Leffler if (_watt_is_init)
98204fb2745SSam Leffler sock_exit();
98304fb2745SSam Leffler
984ada6f083SXin LI env = getenv ("PCAP_TRACE");
98504fb2745SSam Leffler if (env && atoi(env) > 0 &&
98604fb2745SSam Leffler pcap_pkt_debug < 0) /* if not already set */
98704fb2745SSam Leffler {
98804fb2745SSam Leffler dbug_init();
98904fb2745SSam Leffler pcap_pkt_debug = atoi (env);
99004fb2745SSam Leffler }
99104fb2745SSam Leffler
99204fb2745SSam Leffler _watt_do_exit = 0; /* prevent sock_init() calling exit() */
99304fb2745SSam Leffler prev_post_hook = _w32_usr_post_init;
99404fb2745SSam Leffler _w32_usr_post_init = pcap_init_hook;
99504fb2745SSam Leffler _w32_print_hook = null_print;
99604fb2745SSam Leffler
99704fb2745SSam Leffler if (dev_name && strncmp(dev_name,"pkt",3))
99804fb2745SSam Leffler using_pktdrv = FALSE;
99904fb2745SSam Leffler
100004fb2745SSam Leffler rc = sock_init();
100104fb2745SSam Leffler has_ip_addr = (rc != 8); /* IP-address assignment failed */
100204fb2745SSam Leffler
100304fb2745SSam Leffler /* if pcap is using a 32-bit driver w/o a pktdrvr loaded, we
1004*afdbf109SJoseph Mingrone * just pretend Watt-32 is initialized okay.
100504fb2745SSam Leffler *
100604fb2745SSam Leffler * !! fix-me: The Watt-32 config isn't done if no pktdrvr
100704fb2745SSam Leffler * was found. In that case my_ip_addr + sin_mask
100804fb2745SSam Leffler * have default values. Should be taken from another
100904fb2745SSam Leffler * ini-file/environment in any case (ref. tcpdump.ini)
101004fb2745SSam Leffler */
101104fb2745SSam Leffler _watt_is_init = 1;
101204fb2745SSam Leffler
101304fb2745SSam Leffler if (!using_pktdrv || !has_ip_addr) /* for now .... */
101404fb2745SSam Leffler {
101504fb2745SSam Leffler static const char myip[] = "192.168.0.1";
101604fb2745SSam Leffler static const char mask[] = "255.255.255.0";
101704fb2745SSam Leffler
101804fb2745SSam Leffler printf ("Just guessing, using IP %s and netmask %s\n", myip, mask);
101904fb2745SSam Leffler my_ip_addr = aton (myip);
102004fb2745SSam Leffler _w32_sin_mask = aton (mask);
102104fb2745SSam Leffler }
102204fb2745SSam Leffler else if (rc && using_pktdrv)
102304fb2745SSam Leffler {
10246f9cba8fSJoseph Mingrone snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc);
102504fb2745SSam Leffler return (0);
102604fb2745SSam Leffler }
102704fb2745SSam Leffler
102804fb2745SSam Leffler /* Set recv-hook for peeking in _eth_arrived().
102904fb2745SSam Leffler */
103004fb2745SSam Leffler #if (WATTCP_VER >= 0x0224)
103104fb2745SSam Leffler _eth_recv_hook = pcap_recv_hook;
103204fb2745SSam Leffler _eth_xmit_hook = pcap_xmit_hook;
103304fb2745SSam Leffler #endif
103404fb2745SSam Leffler
103504fb2745SSam Leffler /* Free the pkt-drvr handle allocated in pkt_init().
103604fb2745SSam Leffler * The above hooks should thus use the handle reopened in open_driver()
103704fb2745SSam Leffler */
103804fb2745SSam Leffler if (using_pktdrv)
103904fb2745SSam Leffler {
104004fb2745SSam Leffler _eth_release();
104104fb2745SSam Leffler /* _eth_is_init = 1; */ /* hack to get Rx/Tx-hooks in Watt-32 working */
104204fb2745SSam Leffler }
104304fb2745SSam Leffler
104404fb2745SSam Leffler memcpy (&pcap_save, pcap, sizeof(pcap_save));
104504fb2745SSam Leffler MTU = pkt_get_mtu();
104604fb2745SSam Leffler pcap_save.fcode.bf_insns = NULL;
104704fb2745SSam Leffler pcap_save.linktype = _eth_get_hwtype (NULL, NULL);
104804fb2745SSam Leffler pcap_save.snapshot = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */
104904fb2745SSam Leffler
105004fb2745SSam Leffler /* prevent use of resolve() and resolve_ip()
105104fb2745SSam Leffler */
105204fb2745SSam Leffler last_nameserver = 0;
105304fb2745SSam Leffler return (1);
105404fb2745SSam Leffler }
105504fb2745SSam Leffler
105604fb2745SSam Leffler int EISA_bus = 0; /* Where is natural place for this? */
105704fb2745SSam Leffler
105804fb2745SSam Leffler /*
105904fb2745SSam Leffler * Application config hooks to set various driver parameters.
106004fb2745SSam Leffler */
106104fb2745SSam Leffler
1062a8e07101SRui Paulo static const struct config_table debug_tab[] = {
106304fb2745SSam Leffler { "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug },
106404fb2745SSam Leffler { "PKT.VECTOR", ARG_ATOX_W, NULL },
106504fb2745SSam Leffler { "NDIS.DEBUG", ARG_ATOI, NULL },
106604fb2745SSam Leffler #ifdef USE_32BIT_DRIVERS
106704fb2745SSam Leffler { "3C503.DEBUG", ARG_ATOI, &ei_debug },
106804fb2745SSam Leffler { "3C503.IO_BASE", ARG_ATOX_W, &el2_dev.base_addr },
106904fb2745SSam Leffler { "3C503.MEMORY", ARG_ATOX_W, &el2_dev.mem_start },
107004fb2745SSam Leffler { "3C503.IRQ", ARG_ATOI, &el2_dev.irq },
107104fb2745SSam Leffler { "3C505.DEBUG", ARG_ATOI, NULL },
107204fb2745SSam Leffler { "3C505.BASE", ARG_ATOX_W, NULL },
107304fb2745SSam Leffler { "3C507.DEBUG", ARG_ATOI, NULL },
107404fb2745SSam Leffler { "3C509.DEBUG", ARG_ATOI, &el3_debug },
107504fb2745SSam Leffler { "3C509.ILOOP", ARG_ATOI, &el3_max_loop },
107604fb2745SSam Leffler { "3C529.DEBUG", ARG_ATOI, NULL },
107704fb2745SSam Leffler { "3C575.DEBUG", ARG_ATOI, &debug_3c575 },
107804fb2745SSam Leffler { "3C59X.DEBUG", ARG_ATOI, &vortex_debug },
107904fb2745SSam Leffler { "3C59X.IFACE0", ARG_ATOI, &vortex_options[0] },
108004fb2745SSam Leffler { "3C59X.IFACE1", ARG_ATOI, &vortex_options[1] },
108104fb2745SSam Leffler { "3C59X.IFACE2", ARG_ATOI, &vortex_options[2] },
108204fb2745SSam Leffler { "3C59X.IFACE3", ARG_ATOI, &vortex_options[3] },
108304fb2745SSam Leffler { "3C90X.DEBUG", ARG_ATOX_W, &tc90xbc_debug },
108404fb2745SSam Leffler { "ACCT.DEBUG", ARG_ATOI, ðpk_debug },
108504fb2745SSam Leffler { "CS89.DEBUG", ARG_ATOI, &cs89_debug },
108604fb2745SSam Leffler { "RTL8139.DEBUG", ARG_ATOI, &rtl8139_debug },
108704fb2745SSam Leffler /* { "RTL8139.FDUPLEX", ARG_ATOI, &rtl8139_options }, */
108804fb2745SSam Leffler { "SMC.DEBUG", ARG_ATOI, &ei_debug },
108904fb2745SSam Leffler /* { "E100.DEBUG", ARG_ATOI, &e100_debug }, */
109004fb2745SSam Leffler { "PCI.DEBUG", ARG_ATOI, &pci_debug },
109104fb2745SSam Leffler { "BIOS32.DEBUG", ARG_ATOI, &bios32_debug },
109204fb2745SSam Leffler { "IRQ.DEBUG", ARG_ATOI, &irq_debug },
109304fb2745SSam Leffler { "TIMER.IRQ", ARG_ATOI, &timer_irq },
109404fb2745SSam Leffler #endif
109504fb2745SSam Leffler { NULL }
109604fb2745SSam Leffler };
109704fb2745SSam Leffler
109804fb2745SSam Leffler /*
109904fb2745SSam Leffler * pcap_config_hook() is an extension to application's config
110004fb2745SSam Leffler * handling. Uses Watt-32's config-table function.
110104fb2745SSam Leffler */
pcap_config_hook(const char * keyword,const char * value)1102ada6f083SXin LI int pcap_config_hook (const char *keyword, const char *value)
110304fb2745SSam Leffler {
1104ada6f083SXin LI return parse_config_table (debug_tab, NULL, keyword, value);
110504fb2745SSam Leffler }
110604fb2745SSam Leffler
110704fb2745SSam Leffler /*
110804fb2745SSam Leffler * Linked list of supported devices
110904fb2745SSam Leffler */
111004fb2745SSam Leffler struct device *active_dev = NULL; /* the device we have opened */
111104fb2745SSam Leffler struct device *probed_dev = NULL; /* the device we have probed */
111204fb2745SSam Leffler const struct device *dev_base = &pkt_dev; /* list of network devices */
111304fb2745SSam Leffler
111404fb2745SSam Leffler /*
111504fb2745SSam Leffler * PKTDRVR device functions
111604fb2745SSam Leffler */
111704fb2745SSam Leffler int pcap_pkt_debug = -1;
111804fb2745SSam Leffler
pkt_close(struct device * dev)111904fb2745SSam Leffler static void pkt_close (struct device *dev)
112004fb2745SSam Leffler {
112104fb2745SSam Leffler BOOL okay = PktExitDriver();
112204fb2745SSam Leffler
112304fb2745SSam Leffler if (pcap_pkt_debug > 1)
112404fb2745SSam Leffler fprintf (stderr, "pkt_close(): %d\n", okay);
112504fb2745SSam Leffler
112604fb2745SSam Leffler if (dev->priv)
112704fb2745SSam Leffler free (dev->priv);
112804fb2745SSam Leffler dev->priv = NULL;
112904fb2745SSam Leffler }
113004fb2745SSam Leffler
pkt_open(struct device * dev)113104fb2745SSam Leffler static int pkt_open (struct device *dev)
113204fb2745SSam Leffler {
113304fb2745SSam Leffler PKT_RX_MODE mode;
113404fb2745SSam Leffler
113504fb2745SSam Leffler if (dev->flags & IFF_PROMISC)
113604fb2745SSam Leffler mode = PDRX_ALL_PACKETS;
113704fb2745SSam Leffler else mode = PDRX_BROADCAST;
113804fb2745SSam Leffler
113904fb2745SSam Leffler if (!PktInitDriver(mode))
114004fb2745SSam Leffler return (0);
114104fb2745SSam Leffler
114204fb2745SSam Leffler PktResetStatistics (pktInfo.handle);
114304fb2745SSam Leffler PktQueueBusy (FALSE);
114404fb2745SSam Leffler return (1);
114504fb2745SSam Leffler }
114604fb2745SSam Leffler
pkt_xmit(struct device * dev,const void * buf,int len)114704fb2745SSam Leffler static int pkt_xmit (struct device *dev, const void *buf, int len)
114804fb2745SSam Leffler {
114904fb2745SSam Leffler struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
115004fb2745SSam Leffler
115104fb2745SSam Leffler if (pcap_pkt_debug > 0)
115204fb2745SSam Leffler dbug_write ("pcap_xmit\n");
115304fb2745SSam Leffler
115404fb2745SSam Leffler if (!PktTransmit(buf,len))
115504fb2745SSam Leffler {
115604fb2745SSam Leffler stats->tx_errors++;
115704fb2745SSam Leffler return (0);
115804fb2745SSam Leffler }
115904fb2745SSam Leffler return (len);
116004fb2745SSam Leffler }
116104fb2745SSam Leffler
pkt_stats(struct device * dev)116204fb2745SSam Leffler static void *pkt_stats (struct device *dev)
116304fb2745SSam Leffler {
116404fb2745SSam Leffler struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
116504fb2745SSam Leffler
116604fb2745SSam Leffler if (!stats || !PktSessStatistics(pktInfo.handle))
116704fb2745SSam Leffler return (NULL);
116804fb2745SSam Leffler
116904fb2745SSam Leffler stats->rx_packets = pktStat.inPackets;
117004fb2745SSam Leffler stats->rx_errors = pktStat.lost;
117104fb2745SSam Leffler stats->rx_missed_errors = PktRxDropped();
117204fb2745SSam Leffler return (stats);
117304fb2745SSam Leffler }
117404fb2745SSam Leffler
pkt_probe(struct device * dev)117504fb2745SSam Leffler static int pkt_probe (struct device *dev)
117604fb2745SSam Leffler {
117704fb2745SSam Leffler if (!PktSearchDriver())
117804fb2745SSam Leffler return (0);
117904fb2745SSam Leffler
118004fb2745SSam Leffler dev->open = pkt_open;
118104fb2745SSam Leffler dev->xmit = pkt_xmit;
118204fb2745SSam Leffler dev->close = pkt_close;
118304fb2745SSam Leffler dev->get_stats = pkt_stats;
118404fb2745SSam Leffler dev->copy_rx_buf = PktReceive; /* farmem peek and copy routine */
118504fb2745SSam Leffler dev->get_rx_buf = NULL;
118604fb2745SSam Leffler dev->peek_rx_buf = NULL;
118704fb2745SSam Leffler dev->release_rx_buf = NULL;
118804fb2745SSam Leffler dev->priv = calloc (sizeof(struct net_device_stats), 1);
118904fb2745SSam Leffler if (!dev->priv)
119004fb2745SSam Leffler return (0);
119104fb2745SSam Leffler return (1);
119204fb2745SSam Leffler }
119304fb2745SSam Leffler
119404fb2745SSam Leffler /*
119504fb2745SSam Leffler * NDIS device functions
119604fb2745SSam Leffler */
ndis_close(struct device * dev)119704fb2745SSam Leffler static void ndis_close (struct device *dev)
119804fb2745SSam Leffler {
119904fb2745SSam Leffler #ifdef USE_NDIS2
120004fb2745SSam Leffler NdisShutdown();
120104fb2745SSam Leffler #endif
120204fb2745SSam Leffler ARGSUSED (dev);
120304fb2745SSam Leffler }
120404fb2745SSam Leffler
ndis_open(struct device * dev)120504fb2745SSam Leffler static int ndis_open (struct device *dev)
120604fb2745SSam Leffler {
12076f9cba8fSJoseph Mingrone int promisc = (dev->flags & IFF_PROMISC);
120804fb2745SSam Leffler
120904fb2745SSam Leffler #ifdef USE_NDIS2
12106f9cba8fSJoseph Mingrone if (!NdisInit(promisc))
121104fb2745SSam Leffler return (0);
121204fb2745SSam Leffler return (1);
121304fb2745SSam Leffler #else
12146f9cba8fSJoseph Mingrone ARGSUSED (promisc);
121504fb2745SSam Leffler return (0);
121604fb2745SSam Leffler #endif
121704fb2745SSam Leffler }
121804fb2745SSam Leffler
ndis_stats(struct device * dev)121904fb2745SSam Leffler static void *ndis_stats (struct device *dev)
122004fb2745SSam Leffler {
122104fb2745SSam Leffler static struct net_device_stats stats;
122204fb2745SSam Leffler
122304fb2745SSam Leffler /* to-do */
122404fb2745SSam Leffler ARGSUSED (dev);
122504fb2745SSam Leffler return (&stats);
122604fb2745SSam Leffler }
122704fb2745SSam Leffler
ndis_probe(struct device * dev)122804fb2745SSam Leffler static int ndis_probe (struct device *dev)
122904fb2745SSam Leffler {
123004fb2745SSam Leffler #ifdef USE_NDIS2
123104fb2745SSam Leffler if (!NdisOpen())
123204fb2745SSam Leffler return (0);
123304fb2745SSam Leffler #endif
123404fb2745SSam Leffler
123504fb2745SSam Leffler dev->open = ndis_open;
123604fb2745SSam Leffler dev->xmit = NULL;
123704fb2745SSam Leffler dev->close = ndis_close;
123804fb2745SSam Leffler dev->get_stats = ndis_stats;
123904fb2745SSam Leffler dev->copy_rx_buf = NULL; /* to-do */
124004fb2745SSam Leffler dev->get_rx_buf = NULL; /* upcall is from rmode driver */
124104fb2745SSam Leffler dev->peek_rx_buf = NULL;
124204fb2745SSam Leffler dev->release_rx_buf = NULL;
124304fb2745SSam Leffler return (0);
124404fb2745SSam Leffler }
124504fb2745SSam Leffler
124604fb2745SSam Leffler /*
124704fb2745SSam Leffler * Search & probe for supported 32-bit (pmode) pcap devices
124804fb2745SSam Leffler */
124904fb2745SSam Leffler #if defined(USE_32BIT_DRIVERS)
125004fb2745SSam Leffler
125104fb2745SSam Leffler struct device el2_dev LOCKED_VAR = {
125204fb2745SSam Leffler "3c503",
125304fb2745SSam Leffler "EtherLink II",
125404fb2745SSam Leffler 0,
125504fb2745SSam Leffler 0,0,0,0,0,0,
125604fb2745SSam Leffler NULL,
125704fb2745SSam Leffler el2_probe
125804fb2745SSam Leffler };
125904fb2745SSam Leffler
126004fb2745SSam Leffler struct device el3_dev LOCKED_VAR = {
126104fb2745SSam Leffler "3c509",
126204fb2745SSam Leffler "EtherLink III",
126304fb2745SSam Leffler 0,
126404fb2745SSam Leffler 0,0,0,0,0,0,
126504fb2745SSam Leffler &el2_dev,
126604fb2745SSam Leffler el3_probe
126704fb2745SSam Leffler };
126804fb2745SSam Leffler
126904fb2745SSam Leffler struct device tc515_dev LOCKED_VAR = {
127004fb2745SSam Leffler "3c515",
127104fb2745SSam Leffler "EtherLink PCI",
127204fb2745SSam Leffler 0,
127304fb2745SSam Leffler 0,0,0,0,0,0,
127404fb2745SSam Leffler &el3_dev,
127504fb2745SSam Leffler tc515_probe
127604fb2745SSam Leffler };
127704fb2745SSam Leffler
127804fb2745SSam Leffler struct device tc59_dev LOCKED_VAR = {
127904fb2745SSam Leffler "3c59x",
128004fb2745SSam Leffler "EtherLink PCI",
128104fb2745SSam Leffler 0,
128204fb2745SSam Leffler 0,0,0,0,0,0,
128304fb2745SSam Leffler &tc515_dev,
128404fb2745SSam Leffler tc59x_probe
128504fb2745SSam Leffler };
128604fb2745SSam Leffler
128704fb2745SSam Leffler struct device tc90xbc_dev LOCKED_VAR = {
128804fb2745SSam Leffler "3c90x",
128904fb2745SSam Leffler "EtherLink 90X",
129004fb2745SSam Leffler 0,
129104fb2745SSam Leffler 0,0,0,0,0,0,
129204fb2745SSam Leffler &tc59_dev,
129304fb2745SSam Leffler tc90xbc_probe
129404fb2745SSam Leffler };
129504fb2745SSam Leffler
129604fb2745SSam Leffler struct device wd_dev LOCKED_VAR = {
129704fb2745SSam Leffler "wd",
1298*afdbf109SJoseph Mingrone "Western Digital",
129904fb2745SSam Leffler 0,
130004fb2745SSam Leffler 0,0,0,0,0,0,
130104fb2745SSam Leffler &tc90xbc_dev,
130204fb2745SSam Leffler wd_probe
130304fb2745SSam Leffler };
130404fb2745SSam Leffler
130504fb2745SSam Leffler struct device ne_dev LOCKED_VAR = {
130604fb2745SSam Leffler "ne",
130704fb2745SSam Leffler "NEx000",
130804fb2745SSam Leffler 0,
130904fb2745SSam Leffler 0,0,0,0,0,0,
131004fb2745SSam Leffler &wd_dev,
131104fb2745SSam Leffler ne_probe
131204fb2745SSam Leffler };
131304fb2745SSam Leffler
131404fb2745SSam Leffler struct device acct_dev LOCKED_VAR = {
131504fb2745SSam Leffler "acct",
131604fb2745SSam Leffler "Accton EtherPocket",
131704fb2745SSam Leffler 0,
131804fb2745SSam Leffler 0,0,0,0,0,0,
131904fb2745SSam Leffler &ne_dev,
132004fb2745SSam Leffler ethpk_probe
132104fb2745SSam Leffler };
132204fb2745SSam Leffler
132304fb2745SSam Leffler struct device cs89_dev LOCKED_VAR = {
132404fb2745SSam Leffler "cs89",
132504fb2745SSam Leffler "Crystal Semiconductor",
132604fb2745SSam Leffler 0,
132704fb2745SSam Leffler 0,0,0,0,0,0,
132804fb2745SSam Leffler &acct_dev,
132904fb2745SSam Leffler cs89x0_probe
133004fb2745SSam Leffler };
133104fb2745SSam Leffler
133204fb2745SSam Leffler struct device rtl8139_dev LOCKED_VAR = {
133304fb2745SSam Leffler "rtl8139",
133404fb2745SSam Leffler "RealTek PCI",
133504fb2745SSam Leffler 0,
133604fb2745SSam Leffler 0,0,0,0,0,0,
133704fb2745SSam Leffler &cs89_dev,
133804fb2745SSam Leffler rtl8139_probe /* dev->probe routine */
133904fb2745SSam Leffler };
134004fb2745SSam Leffler
134104fb2745SSam Leffler /*
134204fb2745SSam Leffler * Dequeue routine is called by polling.
134304fb2745SSam Leffler * NOTE: the queue-element is not copied, only a pointer is
134404fb2745SSam Leffler * returned at '*buf'
134504fb2745SSam Leffler */
peek_rxbuf(BYTE ** buf)134604fb2745SSam Leffler int peek_rxbuf (BYTE **buf)
134704fb2745SSam Leffler {
134804fb2745SSam Leffler struct rx_elem *tail, *head;
134904fb2745SSam Leffler
135004fb2745SSam Leffler PCAP_ASSERT (pktq_check (&active_dev->queue));
135104fb2745SSam Leffler
135204fb2745SSam Leffler DISABLE();
135304fb2745SSam Leffler tail = pktq_out_elem (&active_dev->queue);
135404fb2745SSam Leffler head = pktq_in_elem (&active_dev->queue);
135504fb2745SSam Leffler ENABLE();
135604fb2745SSam Leffler
135704fb2745SSam Leffler if (head != tail)
135804fb2745SSam Leffler {
135904fb2745SSam Leffler PCAP_ASSERT (tail->size < active_dev->queue.elem_size-4-2);
136004fb2745SSam Leffler
136104fb2745SSam Leffler *buf = &tail->data[0];
136204fb2745SSam Leffler return (tail->size);
136304fb2745SSam Leffler }
136404fb2745SSam Leffler *buf = NULL;
136504fb2745SSam Leffler return (0);
136604fb2745SSam Leffler }
136704fb2745SSam Leffler
136804fb2745SSam Leffler /*
136904fb2745SSam Leffler * Release buffer we peeked at above.
137004fb2745SSam Leffler */
release_rxbuf(BYTE * buf)137104fb2745SSam Leffler int release_rxbuf (BYTE *buf)
137204fb2745SSam Leffler {
137304fb2745SSam Leffler #ifndef NDEBUG
137404fb2745SSam Leffler struct rx_elem *tail = pktq_out_elem (&active_dev->queue);
137504fb2745SSam Leffler
137604fb2745SSam Leffler PCAP_ASSERT (&tail->data[0] == buf);
137704fb2745SSam Leffler #else
137804fb2745SSam Leffler ARGSUSED (buf);
137904fb2745SSam Leffler #endif
138004fb2745SSam Leffler pktq_inc_out (&active_dev->queue);
138104fb2745SSam Leffler return (1);
138204fb2745SSam Leffler }
138304fb2745SSam Leffler
138404fb2745SSam Leffler /*
138504fb2745SSam Leffler * get_rxbuf() routine (in locked code) is called from IRQ handler
138604fb2745SSam Leffler * to request a buffer. Interrupts are disabled and we have a 32kB stack.
138704fb2745SSam Leffler */
get_rxbuf(int len)138804fb2745SSam Leffler BYTE *get_rxbuf (int len)
138904fb2745SSam Leffler {
139004fb2745SSam Leffler int idx;
139104fb2745SSam Leffler
139204fb2745SSam Leffler if (len < ETH_MIN || len > ETH_MAX)
139304fb2745SSam Leffler return (NULL);
139404fb2745SSam Leffler
139504fb2745SSam Leffler idx = pktq_in_index (&active_dev->queue);
139604fb2745SSam Leffler
139704fb2745SSam Leffler #ifdef DEBUG
139804fb2745SSam Leffler {
139904fb2745SSam Leffler static int fan_idx LOCKED_VAR = 0;
140004fb2745SSam Leffler writew ("-\\|/"[fan_idx++] | (15 << 8), /* white on black colour */
140104fb2745SSam Leffler 0xB8000 + 2*79); /* upper-right corner, 80-col colour screen */
140204fb2745SSam Leffler fan_idx &= 3;
140304fb2745SSam Leffler }
140404fb2745SSam Leffler /* writew (idx + '0' + 0x0F00, 0xB8000 + 2*78); */
140504fb2745SSam Leffler #endif
140604fb2745SSam Leffler
140704fb2745SSam Leffler if (idx != active_dev->queue.out_index)
140804fb2745SSam Leffler {
140904fb2745SSam Leffler struct rx_elem *head = pktq_in_elem (&active_dev->queue);
141004fb2745SSam Leffler
141104fb2745SSam Leffler head->size = len;
141204fb2745SSam Leffler active_dev->queue.in_index = idx;
141304fb2745SSam Leffler return (&head->data[0]);
141404fb2745SSam Leffler }
141504fb2745SSam Leffler
141604fb2745SSam Leffler /* !!to-do: drop 25% of the oldest element
141704fb2745SSam Leffler */
141804fb2745SSam Leffler pktq_clear (&active_dev->queue);
141904fb2745SSam Leffler return (NULL);
142004fb2745SSam Leffler }
142104fb2745SSam Leffler
142204fb2745SSam Leffler /*
142304fb2745SSam Leffler * Simple ring-buffer queue handler for reception of packets
142404fb2745SSam Leffler * from network driver.
142504fb2745SSam Leffler */
142604fb2745SSam Leffler #define PKTQ_MARKER 0xDEADBEEF
142704fb2745SSam Leffler
pktq_check(struct rx_ringbuf * q)142804fb2745SSam Leffler static int pktq_check (struct rx_ringbuf *q)
142904fb2745SSam Leffler {
143004fb2745SSam Leffler #ifndef NDEBUG
143104fb2745SSam Leffler int i;
143204fb2745SSam Leffler char *buf;
143304fb2745SSam Leffler #endif
143404fb2745SSam Leffler
143504fb2745SSam Leffler if (!q || !q->num_elem || !q->buf_start)
143604fb2745SSam Leffler return (0);
143704fb2745SSam Leffler
143804fb2745SSam Leffler #ifndef NDEBUG
143904fb2745SSam Leffler buf = q->buf_start;
144004fb2745SSam Leffler
144104fb2745SSam Leffler for (i = 0; i < q->num_elem; i++)
144204fb2745SSam Leffler {
144304fb2745SSam Leffler buf += q->elem_size;
144404fb2745SSam Leffler if (*(DWORD*)(buf - sizeof(DWORD)) != PKTQ_MARKER)
144504fb2745SSam Leffler return (0);
144604fb2745SSam Leffler }
144704fb2745SSam Leffler #endif
144804fb2745SSam Leffler return (1);
144904fb2745SSam Leffler }
145004fb2745SSam Leffler
pktq_init(struct rx_ringbuf * q,int size,int num,char * pool)145104fb2745SSam Leffler static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool)
145204fb2745SSam Leffler {
145304fb2745SSam Leffler int i;
145404fb2745SSam Leffler
145504fb2745SSam Leffler q->elem_size = size;
145604fb2745SSam Leffler q->num_elem = num;
145704fb2745SSam Leffler q->buf_start = pool;
145804fb2745SSam Leffler q->in_index = 0;
145904fb2745SSam Leffler q->out_index = 0;
146004fb2745SSam Leffler
146104fb2745SSam Leffler PCAP_ASSERT (size >= sizeof(struct rx_elem) + sizeof(DWORD));
146204fb2745SSam Leffler PCAP_ASSERT (num);
146304fb2745SSam Leffler PCAP_ASSERT (pool);
146404fb2745SSam Leffler
146504fb2745SSam Leffler for (i = 0; i < num; i++)
146604fb2745SSam Leffler {
146704fb2745SSam Leffler #if 0
146804fb2745SSam Leffler struct rx_elem *elem = (struct rx_elem*) pool;
146904fb2745SSam Leffler
147004fb2745SSam Leffler /* assert dword aligned elements
147104fb2745SSam Leffler */
147204fb2745SSam Leffler PCAP_ASSERT (((unsigned)(&elem->data[0]) & 3) == 0);
147304fb2745SSam Leffler #endif
147404fb2745SSam Leffler pool += size;
147504fb2745SSam Leffler *(DWORD*) (pool - sizeof(DWORD)) = PKTQ_MARKER;
147604fb2745SSam Leffler }
147704fb2745SSam Leffler return (1);
147804fb2745SSam Leffler }
147904fb2745SSam Leffler
148004fb2745SSam Leffler /*
148104fb2745SSam Leffler * Increment the queue 'out_index' (tail).
148204fb2745SSam Leffler * Check for wraps.
148304fb2745SSam Leffler */
pktq_inc_out(struct rx_ringbuf * q)148404fb2745SSam Leffler static int pktq_inc_out (struct rx_ringbuf *q)
148504fb2745SSam Leffler {
148604fb2745SSam Leffler q->out_index++;
148704fb2745SSam Leffler if (q->out_index >= q->num_elem)
148804fb2745SSam Leffler q->out_index = 0;
148904fb2745SSam Leffler return (q->out_index);
149004fb2745SSam Leffler }
149104fb2745SSam Leffler
149204fb2745SSam Leffler /*
149304fb2745SSam Leffler * Return the queue's next 'in_index' (head).
149404fb2745SSam Leffler * Check for wraps.
149504fb2745SSam Leffler */
pktq_in_index(struct rx_ringbuf * q)149604fb2745SSam Leffler static int pktq_in_index (struct rx_ringbuf *q)
149704fb2745SSam Leffler {
149804fb2745SSam Leffler volatile int index = q->in_index + 1;
149904fb2745SSam Leffler
150004fb2745SSam Leffler if (index >= q->num_elem)
150104fb2745SSam Leffler index = 0;
150204fb2745SSam Leffler return (index);
150304fb2745SSam Leffler }
150404fb2745SSam Leffler
150504fb2745SSam Leffler /*
150604fb2745SSam Leffler * Return the queue's head-buffer.
150704fb2745SSam Leffler */
pktq_in_elem(struct rx_ringbuf * q)150804fb2745SSam Leffler static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q)
150904fb2745SSam Leffler {
151004fb2745SSam Leffler return (struct rx_elem*) (q->buf_start + (q->elem_size * q->in_index));
151104fb2745SSam Leffler }
151204fb2745SSam Leffler
151304fb2745SSam Leffler /*
151404fb2745SSam Leffler * Return the queue's tail-buffer.
151504fb2745SSam Leffler */
pktq_out_elem(struct rx_ringbuf * q)151604fb2745SSam Leffler static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q)
151704fb2745SSam Leffler {
151804fb2745SSam Leffler return (struct rx_elem*) (q->buf_start + (q->elem_size * q->out_index));
151904fb2745SSam Leffler }
152004fb2745SSam Leffler
152104fb2745SSam Leffler /*
152204fb2745SSam Leffler * Clear the queue ring-buffer by setting head=tail.
152304fb2745SSam Leffler */
pktq_clear(struct rx_ringbuf * q)152404fb2745SSam Leffler static void pktq_clear (struct rx_ringbuf *q)
152504fb2745SSam Leffler {
152604fb2745SSam Leffler q->in_index = q->out_index;
152704fb2745SSam Leffler }
152804fb2745SSam Leffler
152904fb2745SSam Leffler /*
153004fb2745SSam Leffler * Symbols that must be linkable for "gcc -O0"
153104fb2745SSam Leffler */
153204fb2745SSam Leffler #undef __IOPORT_H
153304fb2745SSam Leffler #undef __DMA_H
153404fb2745SSam Leffler
153504fb2745SSam Leffler #define extern
153604fb2745SSam Leffler #define __inline__
153704fb2745SSam Leffler
153804fb2745SSam Leffler #include "msdos/pm_drvr/ioport.h"
153904fb2745SSam Leffler #include "msdos/pm_drvr/dma.h"
154004fb2745SSam Leffler
154104fb2745SSam Leffler #endif /* USE_32BIT_DRIVERS */
154204fb2745SSam Leffler
1543b00ab754SHans Petter Selasky /*
1544b00ab754SHans Petter Selasky * Libpcap version string.
1545b00ab754SHans Petter Selasky */
1546b00ab754SHans Petter Selasky const char *
pcap_lib_version(void)1547b00ab754SHans Petter Selasky pcap_lib_version(void)
1548b00ab754SHans Petter Selasky {
1549b00ab754SHans Petter Selasky return ("DOS-" PCAP_VERSION_STRING);
1550b00ab754SHans Petter Selasky }
1551