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