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