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