pcap-dos.c revision 190225
1146768Ssam/* 2146768Ssam * This file is part of DOS-libpcap 3190225Srpaulo * Ported to DOS/DOSX by G. Vanem <gvanem@broadpark.no> 4146768Ssam * 5146768Ssam * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode 6146768Ssam * network drivers. 7146768Ssam * 8190225Srpaulo * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.2.2.5 2008-04-22 17:16:49 guy Exp $ (LBL) 9146768Ssam */ 10146768Ssam 11146768Ssam#include <stdio.h> 12146768Ssam#include <stdlib.h> 13146768Ssam#include <string.h> 14146768Ssam#include <signal.h> 15146768Ssam#include <float.h> 16146768Ssam#include <fcntl.h> 17146768Ssam#include <io.h> 18146768Ssam 19146768Ssam#if defined(USE_32BIT_DRIVERS) 20146768Ssam #include "msdos/pm_drvr/pmdrvr.h" 21146768Ssam #include "msdos/pm_drvr/pci.h" 22146768Ssam #include "msdos/pm_drvr/bios32.h" 23146768Ssam #include "msdos/pm_drvr/module.h" 24146768Ssam #include "msdos/pm_drvr/3c501.h" 25146768Ssam #include "msdos/pm_drvr/3c503.h" 26146768Ssam #include "msdos/pm_drvr/3c509.h" 27146768Ssam #include "msdos/pm_drvr/3c59x.h" 28146768Ssam #include "msdos/pm_drvr/3c515.h" 29146768Ssam #include "msdos/pm_drvr/3c90x.h" 30146768Ssam #include "msdos/pm_drvr/3c575_cb.h" 31146768Ssam #include "msdos/pm_drvr/ne.h" 32146768Ssam #include "msdos/pm_drvr/wd.h" 33146768Ssam #include "msdos/pm_drvr/accton.h" 34146768Ssam #include "msdos/pm_drvr/cs89x0.h" 35146768Ssam #include "msdos/pm_drvr/rtl8139.h" 36146768Ssam #include "msdos/pm_drvr/ne2k-pci.h" 37146768Ssam#endif 38146768Ssam 39146768Ssam#include "pcap.h" 40146768Ssam#include "pcap-dos.h" 41146768Ssam#include "pcap-int.h" 42146768Ssam#include "msdos/pktdrvr.h" 43146768Ssam 44146768Ssam#ifdef USE_NDIS2 45146768Ssam#include "msdos/ndis2.h" 46146768Ssam#endif 47146768Ssam 48146768Ssam#include <arpa/inet.h> 49146768Ssam#include <net/if.h> 50146768Ssam#include <net/if_arp.h> 51146768Ssam#include <net/if_ether.h> 52146768Ssam#include <net/if_packe.h> 53146768Ssam#include <tcp.h> 54146768Ssam 55146768Ssam#if defined(USE_32BIT_DRIVERS) 56146768Ssam #define FLUSHK() do { _printk_safe = 1; _printk_flush(); } while (0) 57146768Ssam #define NDIS_NEXT_DEV &rtl8139_dev 58146768Ssam 59146768Ssam static char *rx_pool = NULL; 60146768Ssam static void init_32bit (void); 61146768Ssam 62146768Ssam static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool); 63146768Ssam static int pktq_check (struct rx_ringbuf *q); 64146768Ssam static int pktq_inc_out (struct rx_ringbuf *q); 65146768Ssam static int pktq_in_index (struct rx_ringbuf *q) LOCKED_FUNC; 66146768Ssam static void pktq_clear (struct rx_ringbuf *q) LOCKED_FUNC; 67146768Ssam 68146768Ssam static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q) LOCKED_FUNC; 69146768Ssam static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q); 70146768Ssam 71146768Ssam#else 72146768Ssam #define FLUSHK() ((void)0) 73146768Ssam #define NDIS_NEXT_DEV NULL 74146768Ssam#endif 75146768Ssam 76146768Ssam/* 77146768Ssam * Internal variables/functions in Watt-32 78146768Ssam */ 79146768Ssamextern WORD _pktdevclass; 80146768Ssamextern BOOL _eth_is_init; 81146768Ssamextern int _w32_dynamic_host; 82146768Ssamextern int _watt_do_exit; 83146768Ssamextern int _watt_is_init; 84146768Ssamextern int _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req; 85146768Ssamextern void (*_w32_usr_post_init) (void); 86146768Ssamextern void (*_w32_print_hook)(); 87146768Ssam 88146768Ssamextern void dbug_write (const char *); /* Watt-32 lib, pcdbug.c */ 89146768Ssamextern int pkt_get_mtu (void); 90146768Ssam 91146768Ssamstatic int ref_count = 0; 92146768Ssam 93146768Ssamstatic u_long mac_count = 0; 94146768Ssamstatic u_long filter_count = 0; 95146768Ssam 96146768Ssamstatic volatile BOOL exc_occured = 0; 97146768Ssam 98146768Ssamstatic struct device *handle_to_device [20]; 99146768Ssam 100190225Srpaulostatic int pcap_activate_dos (pcap_t *p); 101146768Ssamstatic int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, 102146768Ssam u_char *data); 103190225Srpaulostatic void pcap_cleanup_dos (pcap_t *p); 104146768Ssamstatic int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps); 105146768Ssamstatic int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len); 106146768Ssamstatic int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp); 107146768Ssam 108146768Ssamstatic int ndis_probe (struct device *dev); 109146768Ssamstatic int pkt_probe (struct device *dev); 110146768Ssam 111146768Ssamstatic void close_driver (void); 112146768Ssamstatic int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf); 113146768Ssamstatic int first_init (const char *name, char *ebuf, int promisc); 114146768Ssam 115146768Ssamstatic void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap, 116146768Ssam const u_char *buf); 117146768Ssam 118146768Ssam/* 119146768Ssam * These are the device we always support 120146768Ssam */ 121146768Ssamstatic struct device ndis_dev = { 122146768Ssam "ndis", 123146768Ssam "NDIS2 LanManager", 124146768Ssam 0, 125146768Ssam 0,0,0,0,0,0, 126146768Ssam NDIS_NEXT_DEV, /* NULL or a 32-bit device */ 127146768Ssam ndis_probe 128146768Ssam }; 129146768Ssam 130146768Ssamstatic struct device pkt_dev = { 131146768Ssam "pkt", 132146768Ssam "Packet-Driver", 133146768Ssam 0, 134146768Ssam 0,0,0,0,0,0, 135146768Ssam &ndis_dev, 136146768Ssam pkt_probe 137146768Ssam }; 138146768Ssam 139146768Ssamstatic struct device *get_device (int fd) 140146768Ssam{ 141146768Ssam if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0])) 142146768Ssam return (NULL); 143146768Ssam return handle_to_device [fd-1]; 144146768Ssam} 145146768Ssam 146190225Srpaulopcap_t *pcap_create (const char *device, char *ebuf) 147190225Srpaulo{ 148190225Srpaulo pcap_t *p; 149190225Srpaulo 150190225Srpaulo p = pcap_create_common(device, ebuf); 151190225Srpaulo if (p == NULL) 152190225Srpaulo return (NULL); 153190225Srpaulo 154190225Srpaulo p->activate_op = pcap_activate_dos; 155190225Srpaulo return (p); 156190225Srpaulo} 157190225Srpaulo 158146768Ssam/* 159146768Ssam * Open MAC-driver with name 'device_name' for live capture of 160146768Ssam * network packets. 161146768Ssam */ 162190225Srpaulostatic int pcap_activate_dos (pcap_t *pcap) 163146768Ssam{ 164190225Srpaulo if (pcap->opt.rfmon) { 165190225Srpaulo /* 166190225Srpaulo * No monitor mode on DOS. 167190225Srpaulo */ 168190225Srpaulo return (PCAP_ERROR_RFMON_NOTSUP); 169190225Srpaulo } 170146768Ssam 171190225Srpaulo if (pcap->snapshot < ETH_MIN+8) 172190225Srpaulo pcap->snapshot = ETH_MIN+8; 173146768Ssam 174190225Srpaulo if (pcap->snapshot > ETH_MAX) /* silently accept and truncate large MTUs */ 175190225Srpaulo pcap->snapshot = ETH_MAX; 176146768Ssam 177146768Ssam pcap->linktype = DLT_EN10MB; /* !! */ 178190225Srpaulo pcap->cleanup_op = pcap_cleanup_dos; 179146768Ssam pcap->read_op = pcap_read_dos; 180146768Ssam pcap->stats_op = pcap_stats_dos; 181146768Ssam pcap->inject_op = pcap_sendpacket_dos; 182146768Ssam pcap->setfilter_op = pcap_setfilter_dos; 183190225Srpaulo pcap->setdirection_op = NULL; /* Not implemented.*/ 184146768Ssam pcap->fd = ++ref_count; 185146768Ssam 186146768Ssam if (pcap->fd == 1) /* first time we're called */ 187146768Ssam { 188190225Srpaulo if (!init_watt32(pcap, pcap->opt.source, pcap->errbuf) || 189190225Srpaulo !first_init(pcap->opt.source, pcap->errbuf, pcap->opt.promisc)) 190146768Ssam { 191190225Srpaulo return (PCAP_ERROR); 192146768Ssam } 193146768Ssam atexit (close_driver); 194146768Ssam } 195190225Srpaulo else if (stricmp(active_dev->name,pcap->opt.source)) 196146768Ssam { 197190225Srpaulo snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE, 198146768Ssam "Cannot use different devices simultaneously " 199190225Srpaulo "(`%s' vs. `%s')", active_dev->name, pcap->opt.source); 200190225Srpaulo return (PCAP_ERROR); 201146768Ssam } 202146768Ssam handle_to_device [pcap->fd-1] = active_dev; 203190225Srpaulo return (0); 204146768Ssam} 205146768Ssam 206146768Ssam/* 207146768Ssam * Poll the receiver queue and call the pcap callback-handler 208146768Ssam * with the packet. 209146768Ssam */ 210146768Ssamstatic int 211146768Ssampcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) 212146768Ssam{ 213146768Ssam struct pcap_pkthdr pcap; 214146768Ssam struct timeval now, expiry; 215146768Ssam BYTE *rx_buf; 216146768Ssam int rx_len = 0; 217146768Ssam 218190225Srpaulo if (p->md.timeout > 0) 219146768Ssam { 220146768Ssam gettimeofday2 (&now, NULL); 221190225Srpaulo expiry.tv_usec = now.tv_usec + 1000UL * p->md.timeout; 222146768Ssam expiry.tv_sec = now.tv_sec; 223146768Ssam while (expiry.tv_usec >= 1000000L) 224146768Ssam { 225146768Ssam expiry.tv_usec -= 1000000L; 226146768Ssam expiry.tv_sec++; 227146768Ssam } 228146768Ssam } 229146768Ssam 230146768Ssam while (!exc_occured) 231146768Ssam { 232146768Ssam volatile struct device *dev; /* might be reset by sig_handler */ 233146768Ssam 234146768Ssam dev = get_device (p->fd); 235146768Ssam if (!dev) 236146768Ssam break; 237146768Ssam 238146768Ssam PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf); 239146768Ssam FLUSHK(); 240146768Ssam 241146768Ssam /* If driver has a zero-copy receive facility, peek at the queue, 242146768Ssam * filter it, do the callback and release the buffer. 243146768Ssam */ 244146768Ssam if (dev->peek_rx_buf) 245146768Ssam { 246146768Ssam PCAP_ASSERT (dev->release_rx_buf); 247146768Ssam rx_len = (*dev->peek_rx_buf) (&rx_buf); 248146768Ssam } 249146768Ssam else 250146768Ssam { 251146768Ssam BYTE buf [ETH_MAX+100]; /* add some margin */ 252146768Ssam rx_len = (*dev->copy_rx_buf) (buf, p->snapshot); 253146768Ssam rx_buf = buf; 254146768Ssam } 255146768Ssam 256146768Ssam if (rx_len > 0) /* got a packet */ 257146768Ssam { 258146768Ssam mac_count++; 259146768Ssam 260146768Ssam FLUSHK(); 261146768Ssam 262146768Ssam pcap.caplen = min (rx_len, p->snapshot); 263146768Ssam pcap.len = rx_len; 264146768Ssam 265146768Ssam if (callback && 266190225Srpaulo (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, rx_buf, pcap.len, pcap.caplen))) 267146768Ssam { 268146768Ssam filter_count++; 269146768Ssam 270146768Ssam /* Fix-me!! Should be time of arrival. Not time of 271146768Ssam * capture. 272146768Ssam */ 273146768Ssam gettimeofday2 (&pcap.ts, NULL); 274146768Ssam (*callback) (data, &pcap, rx_buf); 275146768Ssam } 276146768Ssam 277146768Ssam if (dev->release_rx_buf) 278146768Ssam (*dev->release_rx_buf) (rx_buf); 279146768Ssam 280146768Ssam if (pcap_pkt_debug > 0) 281146768Ssam { 282146768Ssam if (callback == watt32_recv_hook) 283146768Ssam dbug_write ("pcap_recv_hook\n"); 284146768Ssam else dbug_write ("pcap_read_op\n"); 285146768Ssam } 286146768Ssam FLUSHK(); 287146768Ssam return (1); 288146768Ssam } 289146768Ssam 290146768Ssam /* If not to wait for a packet or pcap_close() called from 291146768Ssam * e.g. SIGINT handler, exit loop now. 292146768Ssam */ 293190225Srpaulo if (p->md.timeout <= 0 || (volatile int)p->fd <= 0) 294146768Ssam break; 295146768Ssam 296146768Ssam gettimeofday2 (&now, NULL); 297146768Ssam 298146768Ssam if (timercmp(&now, &expiry, >)) 299146768Ssam break; 300146768Ssam 301146768Ssam#ifndef DJGPP 302146768Ssam kbhit(); /* a real CPU hog */ 303146768Ssam#endif 304146768Ssam 305146768Ssam if (p->wait_proc) 306146768Ssam (*p->wait_proc)(); /* call yield func */ 307146768Ssam } 308146768Ssam 309146768Ssam if (rx_len < 0) /* receive error */ 310146768Ssam { 311146768Ssam p->md.stat.ps_drop++; 312146768Ssam#ifdef USE_32BIT_DRIVERS 313146768Ssam if (pcap_pkt_debug > 1) 314146768Ssam printk ("pkt-err %s\n", pktInfo.error); 315146768Ssam#endif 316146768Ssam return (-1); 317146768Ssam } 318146768Ssam return (0); 319146768Ssam} 320146768Ssam 321146768Ssamstatic int 322146768Ssampcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data) 323146768Ssam{ 324146768Ssam int rc, num = 0; 325146768Ssam 326146768Ssam while (num <= cnt || (cnt < 0)) 327146768Ssam { 328146768Ssam if (p->fd <= 0) 329146768Ssam return (-1); 330146768Ssam rc = pcap_read_one (p, callback, data); 331146768Ssam if (rc > 0) 332146768Ssam num++; 333146768Ssam if (rc < 0) 334146768Ssam break; 335146768Ssam _w32_os_yield(); /* allow SIGINT generation, yield to Win95/NT */ 336146768Ssam } 337146768Ssam return (num); 338146768Ssam} 339146768Ssam 340146768Ssam/* 341146768Ssam * Return network statistics 342146768Ssam */ 343146768Ssamstatic int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps) 344146768Ssam{ 345146768Ssam struct net_device_stats *stats; 346146768Ssam struct device *dev = p ? get_device(p->fd) : NULL; 347146768Ssam 348146768Ssam if (!dev) 349146768Ssam { 350146768Ssam strcpy (p->errbuf, "illegal pcap handle"); 351146768Ssam return (-1); 352146768Ssam } 353146768Ssam 354146768Ssam if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL) 355146768Ssam { 356146768Ssam strcpy (p->errbuf, "device statistics not available"); 357146768Ssam return (-1); 358146768Ssam } 359146768Ssam 360146768Ssam FLUSHK(); 361146768Ssam 362146768Ssam p->md.stat.ps_recv = stats->rx_packets; 363146768Ssam p->md.stat.ps_drop += stats->rx_missed_errors; 364146768Ssam p->md.stat.ps_ifdrop = stats->rx_dropped + /* queue full */ 365146768Ssam stats->rx_errors; /* HW errors */ 366146768Ssam if (ps) 367146768Ssam *ps = p->md.stat; 368146768Ssam 369146768Ssam return (0); 370146768Ssam} 371146768Ssam 372146768Ssam/* 373146768Ssam * Return detailed network/device statistics. 374146768Ssam * May be called after 'dev->close' is called. 375146768Ssam */ 376146768Ssamint pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se) 377146768Ssam{ 378146768Ssam struct device *dev = p ? get_device (p->fd) : NULL; 379146768Ssam 380146768Ssam if (!dev || !dev->get_stats) 381146768Ssam { 382146768Ssam strlcpy (p->errbuf, "detailed device statistics not available", 383146768Ssam PCAP_ERRBUF_SIZE); 384146768Ssam return (-1); 385146768Ssam } 386146768Ssam 387146768Ssam if (!strnicmp(dev->name,"pkt",3)) 388146768Ssam { 389146768Ssam strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics", 390146768Ssam PCAP_ERRBUF_SIZE); 391146768Ssam return (-1); 392146768Ssam } 393146768Ssam memcpy (se, (*dev->get_stats)(dev), sizeof(*se)); 394146768Ssam return (0); 395146768Ssam} 396146768Ssam 397146768Ssam/* 398146768Ssam * Simply store the filter-code for the pcap_read_dos() callback 399146768Ssam * Some day the filter-code could be handed down to the active 400146768Ssam * device (pkt_rx1.s or 32-bit device interrupt handler). 401146768Ssam */ 402146768Ssamstatic int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp) 403146768Ssam{ 404146768Ssam if (!p) 405146768Ssam return (-1); 406146768Ssam p->fcode = *fp; 407146768Ssam return (0); 408146768Ssam} 409146768Ssam 410146768Ssam/* 411146768Ssam * Return # of packets received in pcap_read_dos() 412146768Ssam */ 413146768Ssamu_long pcap_mac_packets (void) 414146768Ssam{ 415146768Ssam return (mac_count); 416146768Ssam} 417146768Ssam 418146768Ssam/* 419146768Ssam * Return # of packets passed through filter in pcap_read_dos() 420146768Ssam */ 421146768Ssamu_long pcap_filter_packets (void) 422146768Ssam{ 423146768Ssam return (filter_count); 424146768Ssam} 425146768Ssam 426146768Ssam/* 427146768Ssam * Close pcap device. Not called for offline captures. 428146768Ssam */ 429190225Srpaulostatic void pcap_cleanup_dos (pcap_t *p) 430146768Ssam{ 431146768Ssam if (p && !exc_occured) 432146768Ssam { 433146768Ssam if (pcap_stats(p,NULL) < 0) 434146768Ssam p->md.stat.ps_drop = 0; 435146768Ssam if (!get_device(p->fd)) 436146768Ssam return; 437146768Ssam 438146768Ssam handle_to_device [p->fd-1] = NULL; 439146768Ssam p->fd = 0; 440146768Ssam if (ref_count > 0) 441146768Ssam ref_count--; 442146768Ssam if (ref_count > 0) 443146768Ssam return; 444146768Ssam } 445146768Ssam close_driver(); 446146768Ssam} 447146768Ssam 448146768Ssam/* 449146768Ssam * Return the name of the 1st network interface, 450146768Ssam * or NULL if none can be found. 451146768Ssam */ 452146768Ssamchar *pcap_lookupdev (char *ebuf) 453146768Ssam{ 454146768Ssam struct device *dev; 455146768Ssam 456146768Ssam#ifdef USE_32BIT_DRIVERS 457146768Ssam init_32bit(); 458146768Ssam#endif 459146768Ssam 460146768Ssam for (dev = (struct device*)dev_base; dev; dev = dev->next) 461146768Ssam { 462146768Ssam PCAP_ASSERT (dev->probe); 463146768Ssam 464146768Ssam if ((*dev->probe)(dev)) 465146768Ssam { 466146768Ssam FLUSHK(); 467146768Ssam probed_dev = (struct device*) dev; /* remember last probed device */ 468146768Ssam return (char*) dev->name; 469146768Ssam } 470146768Ssam } 471146768Ssam 472146768Ssam if (ebuf) 473146768Ssam strcpy (ebuf, "No driver found"); 474146768Ssam return (NULL); 475146768Ssam} 476146768Ssam 477146768Ssam/* 478146768Ssam * Gets localnet & netmask from Watt-32. 479146768Ssam */ 480146768Ssamint pcap_lookupnet (const char *device, bpf_u_int32 *localnet, 481146768Ssam bpf_u_int32 *netmask, char *errbuf) 482146768Ssam{ 483146768Ssam if (!_watt_is_init) 484146768Ssam { 485190225Srpaulo strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be " 486146768Ssam "called first"); 487146768Ssam return (-1); 488146768Ssam } 489146768Ssam 490146768Ssam *netmask = _w32_sin_mask; 491146768Ssam *localnet = my_ip_addr & *netmask; 492146768Ssam if (*localnet == 0) 493146768Ssam { 494146768Ssam if (IN_CLASSA(*netmask)) 495146768Ssam *localnet = IN_CLASSA_NET; 496146768Ssam else if (IN_CLASSB(*netmask)) 497146768Ssam *localnet = IN_CLASSB_NET; 498146768Ssam else if (IN_CLASSC(*netmask)) 499146768Ssam *localnet = IN_CLASSC_NET; 500146768Ssam else 501146768Ssam { 502146768Ssam sprintf (errbuf, "inet class for 0x%lx unknown", *netmask); 503146768Ssam return (-1); 504146768Ssam } 505146768Ssam } 506146768Ssam ARGSUSED (device); 507146768Ssam return (0); 508146768Ssam} 509146768Ssam 510146768Ssam/* 511146768Ssam * Get a list of all interfaces that are present and that we probe okay. 512146768Ssam * Returns -1 on error, 0 otherwise. 513146768Ssam * The list, as returned through "alldevsp", may be null if no interfaces 514146768Ssam * were up and could be opened. 515146768Ssam */ 516146768Ssamint pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf) 517146768Ssam{ 518146768Ssam struct device *dev; 519146768Ssam struct sockaddr_ll sa_ll_1, sa_ll_2; 520146768Ssam struct sockaddr *addr, *netmask, *broadaddr, *dstaddr; 521146768Ssam pcap_if_t *devlist = NULL; 522146768Ssam int ret = 0; 523146768Ssam size_t addr_size = sizeof(struct sockaddr_ll); 524146768Ssam 525146768Ssam for (dev = (struct device*)dev_base; dev; dev = dev->next) 526146768Ssam { 527146768Ssam PCAP_ASSERT (dev->probe); 528146768Ssam 529146768Ssam if (!(*dev->probe)(dev)) 530146768Ssam continue; 531146768Ssam 532146768Ssam PCAP_ASSERT (dev->close); /* set by probe routine */ 533146768Ssam FLUSHK(); 534146768Ssam (*dev->close) (dev); 535146768Ssam 536146768Ssam memset (&sa_ll_1, 0, sizeof(sa_ll_1)); 537146768Ssam memset (&sa_ll_2, 0, sizeof(sa_ll_2)); 538146768Ssam sa_ll_1.sll_family = AF_PACKET; 539146768Ssam sa_ll_2.sll_family = AF_PACKET; 540146768Ssam 541146768Ssam addr = (struct sockaddr*) &sa_ll_1; 542146768Ssam netmask = (struct sockaddr*) &sa_ll_1; 543146768Ssam dstaddr = (struct sockaddr*) &sa_ll_1; 544146768Ssam broadaddr = (struct sockaddr*) &sa_ll_2; 545146768Ssam memset (&sa_ll_2.sll_addr, 0xFF, sizeof(sa_ll_2.sll_addr)); 546146768Ssam 547146768Ssam if (pcap_add_if(&devlist, dev->name, dev->flags, 548146768Ssam dev->long_name, errbuf) < 0) 549146768Ssam { 550146768Ssam ret = -1; 551146768Ssam break; 552146768Ssam } 553146768Ssam if (add_addr_to_iflist(&devlist,dev->name, dev->flags, addr, addr_size, 554146768Ssam netmask, addr_size, broadaddr, addr_size, 555146768Ssam dstaddr, addr_size, errbuf) < 0) 556146768Ssam { 557146768Ssam ret = -1; 558146768Ssam break; 559146768Ssam } 560146768Ssam } 561146768Ssam 562146768Ssam if (devlist && ret < 0) 563146768Ssam { 564146768Ssam pcap_freealldevs (devlist); 565146768Ssam devlist = NULL; 566146768Ssam } 567146768Ssam else 568146768Ssam if (!devlist) 569146768Ssam strcpy (errbuf, "No drivers found"); 570146768Ssam 571146768Ssam *alldevsp = devlist; 572146768Ssam return (ret); 573146768Ssam} 574146768Ssam 575146768Ssam/* 576146768Ssam * pcap_assert() is mainly used for debugging 577146768Ssam */ 578146768Ssamvoid pcap_assert (const char *what, const char *file, unsigned line) 579146768Ssam{ 580146768Ssam FLUSHK(); 581146768Ssam fprintf (stderr, "%s (%u): Assertion \"%s\" failed\n", 582146768Ssam file, line, what); 583146768Ssam close_driver(); 584146768Ssam _exit (-1); 585146768Ssam} 586146768Ssam 587146768Ssam/* 588146768Ssam * For pcap_offline_read(): wait and yield between printing packets 589146768Ssam * to simulate the pace packets where actually recorded. 590146768Ssam */ 591146768Ssamvoid pcap_set_wait (pcap_t *p, void (*yield)(void), int wait) 592146768Ssam{ 593146768Ssam if (p) 594146768Ssam { 595146768Ssam p->wait_proc = yield; 596190225Srpaulo p->md.timeout = wait; 597146768Ssam } 598146768Ssam} 599146768Ssam 600146768Ssam/* 601146768Ssam * Initialise a named network device. 602146768Ssam */ 603146768Ssamstatic struct device * 604146768Ssamopen_driver (const char *dev_name, char *ebuf, int promisc) 605146768Ssam{ 606146768Ssam struct device *dev; 607146768Ssam 608146768Ssam for (dev = (struct device*)dev_base; dev; dev = dev->next) 609146768Ssam { 610146768Ssam PCAP_ASSERT (dev->name); 611146768Ssam 612146768Ssam if (strcmp (dev_name,dev->name)) 613146768Ssam continue; 614146768Ssam 615146768Ssam if (!probed_dev) /* user didn't call pcap_lookupdev() first */ 616146768Ssam { 617146768Ssam PCAP_ASSERT (dev->probe); 618146768Ssam 619146768Ssam if (!(*dev->probe)(dev)) /* call the xx_probe() function */ 620146768Ssam { 621146768Ssam sprintf (ebuf, "failed to detect device `%s'", dev_name); 622146768Ssam return (NULL); 623146768Ssam } 624146768Ssam probed_dev = dev; /* device is probed okay and may be used */ 625146768Ssam } 626146768Ssam else if (dev != probed_dev) 627146768Ssam { 628146768Ssam goto not_probed; 629146768Ssam } 630146768Ssam 631146768Ssam FLUSHK(); 632146768Ssam 633146768Ssam /* Select what traffic to receive 634146768Ssam */ 635146768Ssam if (promisc) 636146768Ssam dev->flags |= (IFF_ALLMULTI | IFF_PROMISC); 637146768Ssam else dev->flags &= ~(IFF_ALLMULTI | IFF_PROMISC); 638146768Ssam 639146768Ssam PCAP_ASSERT (dev->open); 640146768Ssam 641146768Ssam if (!(*dev->open)(dev)) 642146768Ssam { 643146768Ssam sprintf (ebuf, "failed to activate device `%s'", dev_name); 644146768Ssam if (pktInfo.error && !strncmp(dev->name,"pkt",3)) 645146768Ssam { 646146768Ssam strcat (ebuf, ": "); 647146768Ssam strcat (ebuf, pktInfo.error); 648146768Ssam } 649146768Ssam return (NULL); 650146768Ssam } 651146768Ssam 652146768Ssam /* Some devices need this to operate in promiscous mode 653146768Ssam */ 654146768Ssam if (promisc && dev->set_multicast_list) 655146768Ssam (*dev->set_multicast_list) (dev); 656146768Ssam 657146768Ssam active_dev = dev; /* remember our active device */ 658146768Ssam break; 659146768Ssam } 660146768Ssam 661146768Ssam /* 'dev_name' not matched in 'dev_base' list. 662146768Ssam */ 663146768Ssam if (!dev) 664146768Ssam { 665146768Ssam sprintf (ebuf, "device `%s' not supported", dev_name); 666146768Ssam return (NULL); 667146768Ssam } 668146768Ssam 669146768Ssamnot_probed: 670146768Ssam if (!probed_dev) 671146768Ssam { 672146768Ssam sprintf (ebuf, "device `%s' not probed", dev_name); 673146768Ssam return (NULL); 674146768Ssam } 675146768Ssam return (dev); 676146768Ssam} 677146768Ssam 678146768Ssam/* 679146768Ssam * Deinitialise MAC driver. 680146768Ssam * Set receive mode back to default mode. 681146768Ssam */ 682146768Ssamstatic void close_driver (void) 683146768Ssam{ 684146768Ssam /* !!todo: loop over all 'handle_to_device[]' ? */ 685146768Ssam struct device *dev = active_dev; 686146768Ssam 687146768Ssam if (dev && dev->close) 688146768Ssam { 689146768Ssam (*dev->close) (dev); 690146768Ssam FLUSHK(); 691146768Ssam } 692146768Ssam 693146768Ssam active_dev = NULL; 694146768Ssam 695146768Ssam#ifdef USE_32BIT_DRIVERS 696146768Ssam if (rx_pool) 697146768Ssam { 698146768Ssam k_free (rx_pool); 699146768Ssam rx_pool = NULL; 700146768Ssam } 701146768Ssam if (dev) 702146768Ssam pcibios_exit(); 703146768Ssam#endif 704146768Ssam} 705146768Ssam 706146768Ssam 707146768Ssam#ifdef __DJGPP__ 708146768Ssamstatic void setup_signals (void (*handler)(int)) 709146768Ssam{ 710146768Ssam signal (SIGSEGV,handler); 711146768Ssam signal (SIGILL, handler); 712146768Ssam signal (SIGFPE, handler); 713146768Ssam} 714146768Ssam 715146768Ssamstatic void exc_handler (int sig) 716146768Ssam{ 717146768Ssam#ifdef USE_32BIT_DRIVERS 718146768Ssam if (active_dev->irq > 0) /* excludes IRQ 0 */ 719146768Ssam { 720146768Ssam disable_irq (active_dev->irq); 721146768Ssam irq_eoi_cmd (active_dev->irq); 722146768Ssam _printk_safe = 1; 723146768Ssam } 724146768Ssam#endif 725146768Ssam 726146768Ssam switch (sig) 727146768Ssam { 728146768Ssam case SIGSEGV: 729146768Ssam fputs ("Catching SIGSEGV.\n", stderr); 730146768Ssam break; 731146768Ssam case SIGILL: 732146768Ssam fputs ("Catching SIGILL.\n", stderr); 733146768Ssam break; 734146768Ssam case SIGFPE: 735146768Ssam _fpreset(); 736146768Ssam fputs ("Catching SIGFPE.\n", stderr); 737146768Ssam break; 738146768Ssam default: 739146768Ssam fprintf (stderr, "Catching signal %d.\n", sig); 740146768Ssam } 741146768Ssam exc_occured = 1; 742190225Srpaulo pcap_cleanup_dos (NULL); 743146768Ssam} 744146768Ssam#endif /* __DJGPP__ */ 745146768Ssam 746146768Ssam 747146768Ssam/* 748190225Srpaulo * Open the pcap device for the first client calling pcap_activate() 749146768Ssam */ 750146768Ssamstatic int first_init (const char *name, char *ebuf, int promisc) 751146768Ssam{ 752146768Ssam struct device *dev; 753146768Ssam 754146768Ssam#ifdef USE_32BIT_DRIVERS 755146768Ssam rx_pool = k_calloc (RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE); 756146768Ssam if (!rx_pool) 757146768Ssam { 758146768Ssam strcpy (ebuf, "Not enough memory (Rx pool)"); 759146768Ssam return (0); 760146768Ssam } 761146768Ssam#endif 762146768Ssam 763146768Ssam#ifdef __DJGPP__ 764146768Ssam setup_signals (exc_handler); 765146768Ssam#endif 766146768Ssam 767146768Ssam#ifdef USE_32BIT_DRIVERS 768146768Ssam init_32bit(); 769146768Ssam#endif 770146768Ssam 771146768Ssam dev = open_driver (name, ebuf, promisc); 772146768Ssam if (!dev) 773146768Ssam { 774146768Ssam#ifdef USE_32BIT_DRIVERS 775146768Ssam k_free (rx_pool); 776146768Ssam rx_pool = NULL; 777146768Ssam#endif 778146768Ssam 779146768Ssam#ifdef __DJGPP__ 780146768Ssam setup_signals (SIG_DFL); 781146768Ssam#endif 782146768Ssam return (0); 783146768Ssam } 784146768Ssam 785146768Ssam#ifdef USE_32BIT_DRIVERS 786146768Ssam /* 787146768Ssam * If driver is NOT a 16-bit "pkt/ndis" driver (having a 'copy_rx_buf' 788146768Ssam * set in it's probe handler), initialise near-memory ring-buffer for 789146768Ssam * the 32-bit device. 790146768Ssam */ 791146768Ssam if (dev->copy_rx_buf == NULL) 792146768Ssam { 793146768Ssam dev->get_rx_buf = get_rxbuf; 794146768Ssam dev->peek_rx_buf = peek_rxbuf; 795146768Ssam dev->release_rx_buf = release_rxbuf; 796146768Ssam pktq_init (&dev->queue, RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE, rx_pool); 797146768Ssam } 798146768Ssam#endif 799146768Ssam return (1); 800146768Ssam} 801146768Ssam 802146768Ssam#ifdef USE_32BIT_DRIVERS 803146768Ssamstatic void init_32bit (void) 804146768Ssam{ 805146768Ssam static int init_pci = 0; 806146768Ssam 807146768Ssam if (!_printk_file) 808146768Ssam _printk_init (64*1024, NULL); /* calls atexit(printk_exit) */ 809146768Ssam 810146768Ssam if (!init_pci) 811146768Ssam (void)pci_init(); /* init BIOS32+PCI interface */ 812146768Ssam init_pci = 1; 813146768Ssam} 814146768Ssam#endif 815146768Ssam 816146768Ssam 817146768Ssam/* 818146768Ssam * Hook functions for using Watt-32 together with pcap 819146768Ssam */ 820146768Ssamstatic char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */ 821146768Ssamstatic WORD etype; 822146768Ssamstatic pcap_t pcap_save; 823146768Ssam 824146768Ssamstatic void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap, 825146768Ssam const u_char *buf) 826146768Ssam{ 827146768Ssam /* Fix me: assumes Ethernet II only */ 828146768Ssam struct ether_header *ep = (struct ether_header*) buf; 829146768Ssam 830146768Ssam memcpy (rxbuf, buf, pcap->caplen); 831146768Ssam etype = ep->ether_type; 832146768Ssam ARGSUSED (dummy); 833146768Ssam} 834146768Ssam 835146768Ssam#if (WATTCP_VER >= 0x0224) 836146768Ssam/* 837146768Ssam * This function is used by Watt-32 to poll for a packet. 838146768Ssam * i.e. it's set to bypass _eth_arrived() 839146768Ssam */ 840146768Ssamstatic void *pcap_recv_hook (WORD *type) 841146768Ssam{ 842146768Ssam int len = pcap_read_dos (&pcap_save, 1, watt32_recv_hook, NULL); 843146768Ssam 844146768Ssam if (len < 0) 845146768Ssam return (NULL); 846146768Ssam 847146768Ssam *type = etype; 848146768Ssam return (void*) &rxbuf; 849146768Ssam} 850146768Ssam 851146768Ssam/* 852146768Ssam * This function is called by Watt-32 (via _eth_xmit_hook). 853146768Ssam * If dbug_init() was called, we should trace packets sent. 854146768Ssam */ 855146768Ssamstatic int pcap_xmit_hook (const void *buf, unsigned len) 856146768Ssam{ 857146768Ssam int rc = 0; 858146768Ssam 859146768Ssam if (pcap_pkt_debug > 0) 860146768Ssam dbug_write ("pcap_xmit_hook: "); 861146768Ssam 862146768Ssam if (active_dev && active_dev->xmit) 863146768Ssam if ((*active_dev->xmit) (active_dev, buf, len) > 0) 864146768Ssam rc = len; 865146768Ssam 866146768Ssam if (pcap_pkt_debug > 0) 867146768Ssam dbug_write (rc ? "ok\n" : "fail\n"); 868146768Ssam return (rc); 869146768Ssam} 870146768Ssam#endif 871146768Ssam 872146768Ssamstatic int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len) 873146768Ssam{ 874146768Ssam struct device *dev = p ? get_device(p->fd) : NULL; 875146768Ssam 876146768Ssam if (!dev || !dev->xmit) 877146768Ssam return (-1); 878146768Ssam return (*dev->xmit) (dev, buf, len); 879146768Ssam} 880146768Ssam 881146768Ssam/* 882146768Ssam * This function is called by Watt-32 in tcp_post_init(). 883146768Ssam * We should prevent Watt-32 from using BOOTP/DHCP/RARP etc. 884146768Ssam */ 885146768Ssamstatic void (*prev_post_hook) (void); 886146768Ssam 887146768Ssamstatic void pcap_init_hook (void) 888146768Ssam{ 889146768Ssam _w32__bootp_on = _w32__dhcp_on = _w32__rarp_on = 0; 890146768Ssam _w32__do_mask_req = 0; 891146768Ssam _w32_dynamic_host = 0; 892146768Ssam if (prev_post_hook) 893146768Ssam (*prev_post_hook)(); 894146768Ssam} 895146768Ssam 896146768Ssam/* 897146768Ssam * Supress PRINT message from Watt-32's sock_init() 898146768Ssam */ 899146768Ssamstatic void null_print (void) {} 900146768Ssam 901146768Ssam/* 902146768Ssam * To use features of Watt-32 (netdb functions and socket etc.) 903146768Ssam * we must call sock_init(). But we set various hooks to prevent 904146768Ssam * using normal PKTDRVR functions in pcpkt.c. This should hopefully 905146768Ssam * make Watt-32 and pcap co-operate. 906146768Ssam */ 907146768Ssamstatic int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf) 908146768Ssam{ 909146768Ssam char *env; 910146768Ssam int rc, MTU, has_ip_addr; 911146768Ssam int using_pktdrv = 1; 912146768Ssam 913146768Ssam /* If user called sock_init() first, we need to reinit in 914146768Ssam * order to open debug/trace-file properly 915146768Ssam */ 916146768Ssam if (_watt_is_init) 917146768Ssam sock_exit(); 918146768Ssam 919146768Ssam env = getenv ("PCAP_DEBUG"); 920146768Ssam if (env && atoi(env) > 0 && 921146768Ssam pcap_pkt_debug < 0) /* if not already set */ 922146768Ssam { 923146768Ssam dbug_init(); 924146768Ssam pcap_pkt_debug = atoi (env); 925146768Ssam } 926146768Ssam 927146768Ssam _watt_do_exit = 0; /* prevent sock_init() calling exit() */ 928146768Ssam prev_post_hook = _w32_usr_post_init; 929146768Ssam _w32_usr_post_init = pcap_init_hook; 930146768Ssam _w32_print_hook = null_print; 931146768Ssam 932146768Ssam if (dev_name && strncmp(dev_name,"pkt",3)) 933146768Ssam using_pktdrv = FALSE; 934146768Ssam 935146768Ssam rc = sock_init(); 936146768Ssam has_ip_addr = (rc != 8); /* IP-address assignment failed */ 937146768Ssam 938146768Ssam /* if pcap is using a 32-bit driver w/o a pktdrvr loaded, we 939146768Ssam * just pretend Watt-32 is initialised okay. 940146768Ssam * 941146768Ssam * !! fix-me: The Watt-32 config isn't done if no pktdrvr 942146768Ssam * was found. In that case my_ip_addr + sin_mask 943146768Ssam * have default values. Should be taken from another 944146768Ssam * ini-file/environment in any case (ref. tcpdump.ini) 945146768Ssam */ 946146768Ssam _watt_is_init = 1; 947146768Ssam 948146768Ssam if (!using_pktdrv || !has_ip_addr) /* for now .... */ 949146768Ssam { 950146768Ssam static const char myip[] = "192.168.0.1"; 951146768Ssam static const char mask[] = "255.255.255.0"; 952146768Ssam 953146768Ssam printf ("Just guessing, using IP %s and netmask %s\n", myip, mask); 954146768Ssam my_ip_addr = aton (myip); 955146768Ssam _w32_sin_mask = aton (mask); 956146768Ssam } 957146768Ssam else if (rc && using_pktdrv) 958146768Ssam { 959146768Ssam sprintf (err_buf, "sock_init() failed, code %d", rc); 960146768Ssam return (0); 961146768Ssam } 962146768Ssam 963146768Ssam /* Set recv-hook for peeking in _eth_arrived(). 964146768Ssam */ 965146768Ssam#if (WATTCP_VER >= 0x0224) 966146768Ssam _eth_recv_hook = pcap_recv_hook; 967146768Ssam _eth_xmit_hook = pcap_xmit_hook; 968146768Ssam#endif 969146768Ssam 970146768Ssam /* Free the pkt-drvr handle allocated in pkt_init(). 971146768Ssam * The above hooks should thus use the handle reopened in open_driver() 972146768Ssam */ 973146768Ssam if (using_pktdrv) 974146768Ssam { 975146768Ssam _eth_release(); 976146768Ssam/* _eth_is_init = 1; */ /* hack to get Rx/Tx-hooks in Watt-32 working */ 977146768Ssam } 978146768Ssam 979146768Ssam memcpy (&pcap_save, pcap, sizeof(pcap_save)); 980146768Ssam MTU = pkt_get_mtu(); 981146768Ssam pcap_save.fcode.bf_insns = NULL; 982146768Ssam pcap_save.linktype = _eth_get_hwtype (NULL, NULL); 983146768Ssam pcap_save.snapshot = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */ 984146768Ssam 985146768Ssam#if 1 986146768Ssam /* prevent use of resolve() and resolve_ip() 987146768Ssam */ 988146768Ssam last_nameserver = 0; 989146768Ssam#endif 990146768Ssam return (1); 991146768Ssam} 992146768Ssam 993146768Ssamint EISA_bus = 0; /* Where is natural place for this? */ 994146768Ssam 995146768Ssam/* 996146768Ssam * Application config hooks to set various driver parameters. 997146768Ssam */ 998146768Ssam 999190225Srpaulostatic const struct config_table debug_tab[] = { 1000146768Ssam { "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug }, 1001146768Ssam { "PKT.VECTOR", ARG_ATOX_W, NULL }, 1002146768Ssam { "NDIS.DEBUG", ARG_ATOI, NULL }, 1003146768Ssam#ifdef USE_32BIT_DRIVERS 1004146768Ssam { "3C503.DEBUG", ARG_ATOI, &ei_debug }, 1005146768Ssam { "3C503.IO_BASE", ARG_ATOX_W, &el2_dev.base_addr }, 1006146768Ssam { "3C503.MEMORY", ARG_ATOX_W, &el2_dev.mem_start }, 1007146768Ssam { "3C503.IRQ", ARG_ATOI, &el2_dev.irq }, 1008146768Ssam { "3C505.DEBUG", ARG_ATOI, NULL }, 1009146768Ssam { "3C505.BASE", ARG_ATOX_W, NULL }, 1010146768Ssam { "3C507.DEBUG", ARG_ATOI, NULL }, 1011146768Ssam { "3C509.DEBUG", ARG_ATOI, &el3_debug }, 1012146768Ssam { "3C509.ILOOP", ARG_ATOI, &el3_max_loop }, 1013146768Ssam { "3C529.DEBUG", ARG_ATOI, NULL }, 1014146768Ssam { "3C575.DEBUG", ARG_ATOI, &debug_3c575 }, 1015146768Ssam { "3C59X.DEBUG", ARG_ATOI, &vortex_debug }, 1016146768Ssam { "3C59X.IFACE0", ARG_ATOI, &vortex_options[0] }, 1017146768Ssam { "3C59X.IFACE1", ARG_ATOI, &vortex_options[1] }, 1018146768Ssam { "3C59X.IFACE2", ARG_ATOI, &vortex_options[2] }, 1019146768Ssam { "3C59X.IFACE3", ARG_ATOI, &vortex_options[3] }, 1020146768Ssam { "3C90X.DEBUG", ARG_ATOX_W, &tc90xbc_debug }, 1021146768Ssam { "ACCT.DEBUG", ARG_ATOI, ðpk_debug }, 1022146768Ssam { "CS89.DEBUG", ARG_ATOI, &cs89_debug }, 1023146768Ssam { "RTL8139.DEBUG", ARG_ATOI, &rtl8139_debug }, 1024146768Ssam /* { "RTL8139.FDUPLEX", ARG_ATOI, &rtl8139_options }, */ 1025146768Ssam { "SMC.DEBUG", ARG_ATOI, &ei_debug }, 1026146768Ssam /* { "E100.DEBUG", ARG_ATOI, &e100_debug }, */ 1027146768Ssam { "PCI.DEBUG", ARG_ATOI, &pci_debug }, 1028146768Ssam { "BIOS32.DEBUG", ARG_ATOI, &bios32_debug }, 1029146768Ssam { "IRQ.DEBUG", ARG_ATOI, &irq_debug }, 1030146768Ssam { "TIMER.IRQ", ARG_ATOI, &timer_irq }, 1031146768Ssam#endif 1032146768Ssam { NULL } 1033146768Ssam }; 1034146768Ssam 1035146768Ssam/* 1036146768Ssam * pcap_config_hook() is an extension to application's config 1037146768Ssam * handling. Uses Watt-32's config-table function. 1038146768Ssam */ 1039146768Ssamint pcap_config_hook (const char *name, const char *value) 1040146768Ssam{ 1041146768Ssam return parse_config_table (debug_tab, NULL, name, value); 1042146768Ssam} 1043146768Ssam 1044146768Ssam/* 1045146768Ssam * Linked list of supported devices 1046146768Ssam */ 1047146768Ssamstruct device *active_dev = NULL; /* the device we have opened */ 1048146768Ssamstruct device *probed_dev = NULL; /* the device we have probed */ 1049146768Ssamconst struct device *dev_base = &pkt_dev; /* list of network devices */ 1050146768Ssam 1051146768Ssam/* 1052146768Ssam * PKTDRVR device functions 1053146768Ssam */ 1054146768Ssamint pcap_pkt_debug = -1; 1055146768Ssam 1056146768Ssamstatic void pkt_close (struct device *dev) 1057146768Ssam{ 1058146768Ssam BOOL okay = PktExitDriver(); 1059146768Ssam 1060146768Ssam if (pcap_pkt_debug > 1) 1061146768Ssam fprintf (stderr, "pkt_close(): %d\n", okay); 1062146768Ssam 1063146768Ssam if (dev->priv) 1064146768Ssam free (dev->priv); 1065146768Ssam dev->priv = NULL; 1066146768Ssam} 1067146768Ssam 1068146768Ssamstatic int pkt_open (struct device *dev) 1069146768Ssam{ 1070146768Ssam PKT_RX_MODE mode; 1071146768Ssam 1072146768Ssam if (dev->flags & IFF_PROMISC) 1073146768Ssam mode = PDRX_ALL_PACKETS; 1074146768Ssam else mode = PDRX_BROADCAST; 1075146768Ssam 1076146768Ssam if (!PktInitDriver(mode)) 1077146768Ssam return (0); 1078146768Ssam 1079146768Ssam PktResetStatistics (pktInfo.handle); 1080146768Ssam PktQueueBusy (FALSE); 1081146768Ssam return (1); 1082146768Ssam} 1083146768Ssam 1084146768Ssamstatic int pkt_xmit (struct device *dev, const void *buf, int len) 1085146768Ssam{ 1086146768Ssam struct net_device_stats *stats = (struct net_device_stats*) dev->priv; 1087146768Ssam 1088146768Ssam if (pcap_pkt_debug > 0) 1089146768Ssam dbug_write ("pcap_xmit\n"); 1090146768Ssam 1091146768Ssam if (!PktTransmit(buf,len)) 1092146768Ssam { 1093146768Ssam stats->tx_errors++; 1094146768Ssam return (0); 1095146768Ssam } 1096146768Ssam return (len); 1097146768Ssam} 1098146768Ssam 1099146768Ssamstatic void *pkt_stats (struct device *dev) 1100146768Ssam{ 1101146768Ssam struct net_device_stats *stats = (struct net_device_stats*) dev->priv; 1102146768Ssam 1103146768Ssam if (!stats || !PktSessStatistics(pktInfo.handle)) 1104146768Ssam return (NULL); 1105146768Ssam 1106146768Ssam stats->rx_packets = pktStat.inPackets; 1107146768Ssam stats->rx_errors = pktStat.lost; 1108146768Ssam stats->rx_missed_errors = PktRxDropped(); 1109146768Ssam return (stats); 1110146768Ssam} 1111146768Ssam 1112146768Ssamstatic int pkt_probe (struct device *dev) 1113146768Ssam{ 1114146768Ssam if (!PktSearchDriver()) 1115146768Ssam return (0); 1116146768Ssam 1117146768Ssam dev->open = pkt_open; 1118146768Ssam dev->xmit = pkt_xmit; 1119146768Ssam dev->close = pkt_close; 1120146768Ssam dev->get_stats = pkt_stats; 1121146768Ssam dev->copy_rx_buf = PktReceive; /* farmem peek and copy routine */ 1122146768Ssam dev->get_rx_buf = NULL; 1123146768Ssam dev->peek_rx_buf = NULL; 1124146768Ssam dev->release_rx_buf = NULL; 1125146768Ssam dev->priv = calloc (sizeof(struct net_device_stats), 1); 1126146768Ssam if (!dev->priv) 1127146768Ssam return (0); 1128146768Ssam return (1); 1129146768Ssam} 1130146768Ssam 1131146768Ssam/* 1132146768Ssam * NDIS device functions 1133146768Ssam */ 1134146768Ssamstatic void ndis_close (struct device *dev) 1135146768Ssam{ 1136146768Ssam#ifdef USE_NDIS2 1137146768Ssam NdisShutdown(); 1138146768Ssam#endif 1139146768Ssam ARGSUSED (dev); 1140146768Ssam} 1141146768Ssam 1142146768Ssamstatic int ndis_open (struct device *dev) 1143146768Ssam{ 1144146768Ssam int promis = (dev->flags & IFF_PROMISC); 1145146768Ssam 1146146768Ssam#ifdef USE_NDIS2 1147146768Ssam if (!NdisInit(promis)) 1148146768Ssam return (0); 1149146768Ssam return (1); 1150146768Ssam#else 1151146768Ssam ARGSUSED (promis); 1152146768Ssam return (0); 1153146768Ssam#endif 1154146768Ssam} 1155146768Ssam 1156146768Ssamstatic void *ndis_stats (struct device *dev) 1157146768Ssam{ 1158146768Ssam static struct net_device_stats stats; 1159146768Ssam 1160146768Ssam /* to-do */ 1161146768Ssam ARGSUSED (dev); 1162146768Ssam return (&stats); 1163146768Ssam} 1164146768Ssam 1165146768Ssamstatic int ndis_probe (struct device *dev) 1166146768Ssam{ 1167146768Ssam#ifdef USE_NDIS2 1168146768Ssam if (!NdisOpen()) 1169146768Ssam return (0); 1170146768Ssam#endif 1171146768Ssam 1172146768Ssam dev->open = ndis_open; 1173146768Ssam dev->xmit = NULL; 1174146768Ssam dev->close = ndis_close; 1175146768Ssam dev->get_stats = ndis_stats; 1176146768Ssam dev->copy_rx_buf = NULL; /* to-do */ 1177146768Ssam dev->get_rx_buf = NULL; /* upcall is from rmode driver */ 1178146768Ssam dev->peek_rx_buf = NULL; 1179146768Ssam dev->release_rx_buf = NULL; 1180146768Ssam return (0); 1181146768Ssam} 1182146768Ssam 1183146768Ssam/* 1184146768Ssam * Search & probe for supported 32-bit (pmode) pcap devices 1185146768Ssam */ 1186146768Ssam#if defined(USE_32BIT_DRIVERS) 1187146768Ssam 1188146768Ssamstruct device el2_dev LOCKED_VAR = { 1189146768Ssam "3c503", 1190146768Ssam "EtherLink II", 1191146768Ssam 0, 1192146768Ssam 0,0,0,0,0,0, 1193146768Ssam NULL, 1194146768Ssam el2_probe 1195146768Ssam }; 1196146768Ssam 1197146768Ssamstruct device el3_dev LOCKED_VAR = { 1198146768Ssam "3c509", 1199146768Ssam "EtherLink III", 1200146768Ssam 0, 1201146768Ssam 0,0,0,0,0,0, 1202146768Ssam &el2_dev, 1203146768Ssam el3_probe 1204146768Ssam }; 1205146768Ssam 1206146768Ssamstruct device tc515_dev LOCKED_VAR = { 1207146768Ssam "3c515", 1208146768Ssam "EtherLink PCI", 1209146768Ssam 0, 1210146768Ssam 0,0,0,0,0,0, 1211146768Ssam &el3_dev, 1212146768Ssam tc515_probe 1213146768Ssam }; 1214146768Ssam 1215146768Ssamstruct device tc59_dev LOCKED_VAR = { 1216146768Ssam "3c59x", 1217146768Ssam "EtherLink PCI", 1218146768Ssam 0, 1219146768Ssam 0,0,0,0,0,0, 1220146768Ssam &tc515_dev, 1221146768Ssam tc59x_probe 1222146768Ssam }; 1223146768Ssam 1224146768Ssamstruct device tc90xbc_dev LOCKED_VAR = { 1225146768Ssam "3c90x", 1226146768Ssam "EtherLink 90X", 1227146768Ssam 0, 1228146768Ssam 0,0,0,0,0,0, 1229146768Ssam &tc59_dev, 1230146768Ssam tc90xbc_probe 1231146768Ssam }; 1232146768Ssam 1233146768Ssamstruct device wd_dev LOCKED_VAR = { 1234146768Ssam "wd", 1235146768Ssam "Westen Digital", 1236146768Ssam 0, 1237146768Ssam 0,0,0,0,0,0, 1238146768Ssam &tc90xbc_dev, 1239146768Ssam wd_probe 1240146768Ssam }; 1241146768Ssam 1242146768Ssamstruct device ne_dev LOCKED_VAR = { 1243146768Ssam "ne", 1244146768Ssam "NEx000", 1245146768Ssam 0, 1246146768Ssam 0,0,0,0,0,0, 1247146768Ssam &wd_dev, 1248146768Ssam ne_probe 1249146768Ssam }; 1250146768Ssam 1251146768Ssamstruct device acct_dev LOCKED_VAR = { 1252146768Ssam "acct", 1253146768Ssam "Accton EtherPocket", 1254146768Ssam 0, 1255146768Ssam 0,0,0,0,0,0, 1256146768Ssam &ne_dev, 1257146768Ssam ethpk_probe 1258146768Ssam }; 1259146768Ssam 1260146768Ssamstruct device cs89_dev LOCKED_VAR = { 1261146768Ssam "cs89", 1262146768Ssam "Crystal Semiconductor", 1263146768Ssam 0, 1264146768Ssam 0,0,0,0,0,0, 1265146768Ssam &acct_dev, 1266146768Ssam cs89x0_probe 1267146768Ssam }; 1268146768Ssam 1269146768Ssamstruct device rtl8139_dev LOCKED_VAR = { 1270146768Ssam "rtl8139", 1271146768Ssam "RealTek PCI", 1272146768Ssam 0, 1273146768Ssam 0,0,0,0,0,0, 1274146768Ssam &cs89_dev, 1275146768Ssam rtl8139_probe /* dev->probe routine */ 1276146768Ssam }; 1277146768Ssam 1278146768Ssam/* 1279146768Ssam * Dequeue routine is called by polling. 1280146768Ssam * NOTE: the queue-element is not copied, only a pointer is 1281146768Ssam * returned at '*buf' 1282146768Ssam */ 1283146768Ssamint peek_rxbuf (BYTE **buf) 1284146768Ssam{ 1285146768Ssam struct rx_elem *tail, *head; 1286146768Ssam 1287146768Ssam PCAP_ASSERT (pktq_check (&active_dev->queue)); 1288146768Ssam 1289146768Ssam DISABLE(); 1290146768Ssam tail = pktq_out_elem (&active_dev->queue); 1291146768Ssam head = pktq_in_elem (&active_dev->queue); 1292146768Ssam ENABLE(); 1293146768Ssam 1294146768Ssam if (head != tail) 1295146768Ssam { 1296146768Ssam PCAP_ASSERT (tail->size < active_dev->queue.elem_size-4-2); 1297146768Ssam 1298146768Ssam *buf = &tail->data[0]; 1299146768Ssam return (tail->size); 1300146768Ssam } 1301146768Ssam *buf = NULL; 1302146768Ssam return (0); 1303146768Ssam} 1304146768Ssam 1305146768Ssam/* 1306146768Ssam * Release buffer we peeked at above. 1307146768Ssam */ 1308146768Ssamint release_rxbuf (BYTE *buf) 1309146768Ssam{ 1310146768Ssam#ifndef NDEBUG 1311146768Ssam struct rx_elem *tail = pktq_out_elem (&active_dev->queue); 1312146768Ssam 1313146768Ssam PCAP_ASSERT (&tail->data[0] == buf); 1314146768Ssam#else 1315146768Ssam ARGSUSED (buf); 1316146768Ssam#endif 1317146768Ssam pktq_inc_out (&active_dev->queue); 1318146768Ssam return (1); 1319146768Ssam} 1320146768Ssam 1321146768Ssam/* 1322146768Ssam * get_rxbuf() routine (in locked code) is called from IRQ handler 1323146768Ssam * to request a buffer. Interrupts are disabled and we have a 32kB stack. 1324146768Ssam */ 1325146768SsamBYTE *get_rxbuf (int len) 1326146768Ssam{ 1327146768Ssam int idx; 1328146768Ssam 1329146768Ssam if (len < ETH_MIN || len > ETH_MAX) 1330146768Ssam return (NULL); 1331146768Ssam 1332146768Ssam idx = pktq_in_index (&active_dev->queue); 1333146768Ssam 1334146768Ssam#ifdef DEBUG 1335146768Ssam { 1336146768Ssam static int fan_idx LOCKED_VAR = 0; 1337146768Ssam writew ("-\\|/"[fan_idx++] | (15 << 8), /* white on black colour */ 1338146768Ssam 0xB8000 + 2*79); /* upper-right corner, 80-col colour screen */ 1339146768Ssam fan_idx &= 3; 1340146768Ssam } 1341146768Ssam/* writew (idx + '0' + 0x0F00, 0xB8000 + 2*78); */ 1342146768Ssam#endif 1343146768Ssam 1344146768Ssam if (idx != active_dev->queue.out_index) 1345146768Ssam { 1346146768Ssam struct rx_elem *head = pktq_in_elem (&active_dev->queue); 1347146768Ssam 1348146768Ssam head->size = len; 1349146768Ssam active_dev->queue.in_index = idx; 1350146768Ssam return (&head->data[0]); 1351146768Ssam } 1352146768Ssam 1353146768Ssam /* !!to-do: drop 25% of the oldest element 1354146768Ssam */ 1355146768Ssam pktq_clear (&active_dev->queue); 1356146768Ssam return (NULL); 1357146768Ssam} 1358146768Ssam 1359146768Ssam/* 1360146768Ssam * Simple ring-buffer queue handler for reception of packets 1361146768Ssam * from network driver. 1362146768Ssam */ 1363146768Ssam#define PKTQ_MARKER 0xDEADBEEF 1364146768Ssam 1365146768Ssamstatic int pktq_check (struct rx_ringbuf *q) 1366146768Ssam{ 1367146768Ssam#ifndef NDEBUG 1368146768Ssam int i; 1369146768Ssam char *buf; 1370146768Ssam#endif 1371146768Ssam 1372146768Ssam if (!q || !q->num_elem || !q->buf_start) 1373146768Ssam return (0); 1374146768Ssam 1375146768Ssam#ifndef NDEBUG 1376146768Ssam buf = q->buf_start; 1377146768Ssam 1378146768Ssam for (i = 0; i < q->num_elem; i++) 1379146768Ssam { 1380146768Ssam buf += q->elem_size; 1381146768Ssam if (*(DWORD*)(buf - sizeof(DWORD)) != PKTQ_MARKER) 1382146768Ssam return (0); 1383146768Ssam } 1384146768Ssam#endif 1385146768Ssam return (1); 1386146768Ssam} 1387146768Ssam 1388146768Ssamstatic int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool) 1389146768Ssam{ 1390146768Ssam int i; 1391146768Ssam 1392146768Ssam q->elem_size = size; 1393146768Ssam q->num_elem = num; 1394146768Ssam q->buf_start = pool; 1395146768Ssam q->in_index = 0; 1396146768Ssam q->out_index = 0; 1397146768Ssam 1398146768Ssam PCAP_ASSERT (size >= sizeof(struct rx_elem) + sizeof(DWORD)); 1399146768Ssam PCAP_ASSERT (num); 1400146768Ssam PCAP_ASSERT (pool); 1401146768Ssam 1402146768Ssam for (i = 0; i < num; i++) 1403146768Ssam { 1404146768Ssam#if 0 1405146768Ssam struct rx_elem *elem = (struct rx_elem*) pool; 1406146768Ssam 1407146768Ssam /* assert dword aligned elements 1408146768Ssam */ 1409146768Ssam PCAP_ASSERT (((unsigned)(&elem->data[0]) & 3) == 0); 1410146768Ssam#endif 1411146768Ssam pool += size; 1412146768Ssam *(DWORD*) (pool - sizeof(DWORD)) = PKTQ_MARKER; 1413146768Ssam } 1414146768Ssam return (1); 1415146768Ssam} 1416146768Ssam 1417146768Ssam/* 1418146768Ssam * Increment the queue 'out_index' (tail). 1419146768Ssam * Check for wraps. 1420146768Ssam */ 1421146768Ssamstatic int pktq_inc_out (struct rx_ringbuf *q) 1422146768Ssam{ 1423146768Ssam q->out_index++; 1424146768Ssam if (q->out_index >= q->num_elem) 1425146768Ssam q->out_index = 0; 1426146768Ssam return (q->out_index); 1427146768Ssam} 1428146768Ssam 1429146768Ssam/* 1430146768Ssam * Return the queue's next 'in_index' (head). 1431146768Ssam * Check for wraps. 1432146768Ssam */ 1433146768Ssamstatic int pktq_in_index (struct rx_ringbuf *q) 1434146768Ssam{ 1435146768Ssam volatile int index = q->in_index + 1; 1436146768Ssam 1437146768Ssam if (index >= q->num_elem) 1438146768Ssam index = 0; 1439146768Ssam return (index); 1440146768Ssam} 1441146768Ssam 1442146768Ssam/* 1443146768Ssam * Return the queue's head-buffer. 1444146768Ssam */ 1445146768Ssamstatic struct rx_elem *pktq_in_elem (struct rx_ringbuf *q) 1446146768Ssam{ 1447146768Ssam return (struct rx_elem*) (q->buf_start + (q->elem_size * q->in_index)); 1448146768Ssam} 1449146768Ssam 1450146768Ssam/* 1451146768Ssam * Return the queue's tail-buffer. 1452146768Ssam */ 1453146768Ssamstatic struct rx_elem *pktq_out_elem (struct rx_ringbuf *q) 1454146768Ssam{ 1455146768Ssam return (struct rx_elem*) (q->buf_start + (q->elem_size * q->out_index)); 1456146768Ssam} 1457146768Ssam 1458146768Ssam/* 1459146768Ssam * Clear the queue ring-buffer by setting head=tail. 1460146768Ssam */ 1461146768Ssamstatic void pktq_clear (struct rx_ringbuf *q) 1462146768Ssam{ 1463146768Ssam q->in_index = q->out_index; 1464146768Ssam} 1465146768Ssam 1466146768Ssam/* 1467146768Ssam * Symbols that must be linkable for "gcc -O0" 1468146768Ssam */ 1469146768Ssam#undef __IOPORT_H 1470146768Ssam#undef __DMA_H 1471146768Ssam 1472146768Ssam#define extern 1473146768Ssam#define __inline__ 1474146768Ssam 1475146768Ssam#include "msdos/pm_drvr/ioport.h" 1476146768Ssam#include "msdos/pm_drvr/dma.h" 1477146768Ssam 1478146768Ssam#endif /* USE_32BIT_DRIVERS */ 1479146768Ssam 1480