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 */ 79extern WORD _pktdevclass; 80extern BOOL _eth_is_init; 81extern int _w32_dynamic_host; 82extern int _watt_do_exit; 83extern int _watt_is_init; 84extern int _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req; 85extern void (*_w32_usr_post_init) (void); 86extern void (*_w32_print_hook)(); 87 88extern void dbug_write (const char *); /* Watt-32 lib, pcdbug.c */ 89extern int pkt_get_mtu (void); 90 91static int ref_count = 0; 92 93static u_long mac_count = 0; 94static u_long filter_count = 0; 95 96static volatile BOOL exc_occured = 0; 97 98static struct device *handle_to_device [20]; 99 100static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, 101 u_char *data); 102static void pcap_close_dos (pcap_t *p); 103static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps); 104static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len); 105static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp); 106 107static int ndis_probe (struct device *dev); 108static int pkt_probe (struct device *dev); 109 110static void close_driver (void); 111static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf); 112static int first_init (const char *name, char *ebuf, int promisc); 113 114static 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 */ 120static 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 129static 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 138static 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 */ 149pcap_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 */ 204static int 205pcap_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 316static int 317pcap_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 */ 338static 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 */ 371int 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 */ 397static 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 */ 408u_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 */ 416u_long pcap_filter_packets (void) 417{ 418 return (filter_count); 419} 420 421/* 422 * Close pcap device. Not called for offline captures. 423 */ 424static 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 */ 447char *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 */ 475int 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 */ 511int 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 */ 573void 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 */ 586void 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 */ 598static struct device * 599open_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 664not_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 */ 677static 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__ 703static void setup_signals (void (*handler)(int)) 704{ 705 signal (SIGSEGV,handler); 706 signal (SIGILL, handler); 707 signal (SIGFPE, handler); 708} 709 710static 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 */ 745static 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 798static 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 */ 815static char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */ 816static WORD etype; 817static pcap_t pcap_save; 818 819static 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 */ 835static 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 */ 850static 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 867static 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 */ 880static void (*prev_post_hook) (void); 881 882static 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 */ 894static 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 */ 902static 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 988int EISA_bus = 0; /* Where is natural place for this? */ 989 990/* 991 * Application config hooks to set various driver parameters. 992 */ 993 994static 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 */ 1034int 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 */ 1042struct device *active_dev = NULL; /* the device we have opened */ 1043struct device *probed_dev = NULL; /* the device we have probed */ 1044const struct device *dev_base = &pkt_dev; /* list of network devices */ 1045 1046/* 1047 * PKTDRVR device functions 1048 */ 1049int pcap_pkt_debug = -1; 1050 1051static 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 1063static 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 1079static 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 1094static 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 1107static 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 */ 1129static void ndis_close (struct device *dev) 1130{ 1131#ifdef USE_NDIS2 1132 NdisShutdown(); 1133#endif 1134 ARGSUSED (dev); 1135} 1136 1137static 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 1151static 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 1160static 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 1183struct 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 1192struct 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 1201struct 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 1210struct 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 1219struct 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 1228struct 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 1237struct 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 1246struct 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 1255struct 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 1264struct 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 */ 1278int 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 */ 1303int 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 */ 1320BYTE *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 1360static 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 1383static 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 */ 1416static 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 */ 1428static 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 */ 1440static 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 */ 1448static 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 */ 1456static 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