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