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