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