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