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