X-Git-Url: https://git.tcpdump.org/libpcap/blobdiff_plain/f8a76d1d7613b5c4708e8ed8cfbdd19906672bba..cc3ca65d6519faf3a0e4609b5150757c14af36e9:/pcap-dos.c diff --git a/pcap-dos.c b/pcap-dos.c index 26a925b3..ea6b225a 100644 --- a/pcap-dos.c +++ b/pcap-dos.c @@ -1,11 +1,9 @@ /* * This file is part of DOS-libpcap - * Ported to DOS/DOSX by G. Vanem + * Ported to DOS/DOSX by G. Vanem * * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode * network drivers. - * - * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1 2004-12-18 08:52:10 guy Exp $ (LBL) */ #include @@ -97,9 +95,10 @@ static volatile BOOL exc_occured = 0; static struct device *handle_to_device [20]; +static int pcap_activate_dos (pcap_t *p); static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data); -static void pcap_close_dos (pcap_t *p); +static void pcap_cleanup_dos (pcap_t *p); static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps); static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len); static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp); @@ -143,57 +142,74 @@ static struct device *get_device (int fd) } /* - * Open MAC-driver with name 'device_name' for live capture of - * network packets. + * Private data for capturing on MS-DOS. */ -pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc, - int timeout_ms, char *errbuf) -{ - struct pcap *pcap; +struct pcap_dos { + void (*wait_proc)(void); /* call proc while waiting */ + struct pcap_stat stat; +}; - if (snaplen < ETH_MIN) - snaplen = ETH_MIN; +pcap_t *pcap_create_interface (const char *device _U_, char *ebuf) +{ + pcap_t *p; - if (snaplen > ETH_MAX) /* silently accept and truncate large MTUs */ - snaplen = ETH_MAX; + p = pcap_create_common(ebuf, sizeof (struct pcap_dos)); + if (p == NULL) + return (NULL); - pcap = calloc (sizeof(*pcap), 1); - if (!pcap) - { - strcpy (errbuf, "Not enough memory (pcap)"); - return (NULL); + p->activate_op = pcap_activate_dos; + return (p); +} + +/* + * Open MAC-driver with name 'device_name' for live capture of + * network packets. + */ +static int pcap_activate_dos (pcap_t *pcap) +{ + if (pcap->opt.rfmon) { + /* + * No monitor mode on DOS. + */ + return (PCAP_ERROR_RFMON_NOTSUP); } - pcap->snapshot = max (ETH_MIN+8, snaplen); + if (pcap->snapshot < ETH_MIN+8) + pcap->snapshot = ETH_MIN+8; + + if (pcap->snapshot > ETH_MAX) /* silently accept and truncate large MTUs */ + pcap->snapshot = ETH_MAX; + pcap->linktype = DLT_EN10MB; /* !! */ - pcap->inter_packet_wait = timeout_ms; - pcap->close_op = pcap_close_dos; + pcap->cleanup_op = pcap_cleanup_dos; pcap->read_op = pcap_read_dos; pcap->stats_op = pcap_stats_dos; pcap->inject_op = pcap_sendpacket_dos; pcap->setfilter_op = pcap_setfilter_dos; + pcap->setdirection_op = NULL; /* Not implemented.*/ pcap->fd = ++ref_count; + pcap->bufsize = ETH_MAX+100; /* add some margin */ + pcap->buffer = calloc (pcap->bufsize, 1); + if (pcap->fd == 1) /* first time we're called */ { - if (!init_watt32(pcap, device_name, errbuf) || - !first_init(device_name, errbuf, promisc)) + if (!init_watt32(pcap, pcap->opt.device, pcap->errbuf) || + !first_init(pcap->opt.device, pcap->errbuf, pcap->opt.promisc)) { - free (pcap); - return (NULL); - } + return (PCAP_ERROR); + } atexit (close_driver); } - else if (stricmp(active_dev->name,device_name)) + else if (stricmp(active_dev->name,pcap->opt.device)) { - snprintf (errbuf, PCAP_ERRBUF_SIZE, - "Cannot use different devices simultaneously " - "(`%s' vs. `%s')", active_dev->name, device_name); - free (pcap); - pcap = NULL; + pcap_snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE, + "Cannot use different devices simultaneously " + "(`%s' vs. `%s')", active_dev->name, pcap->opt.device); + return (PCAP_ERROR); } handle_to_device [pcap->fd-1] = active_dev; - return (pcap); + return (0); } /* @@ -203,16 +219,15 @@ pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc, static int pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) { + struct pcap_dos *pd = p->priv; struct pcap_pkthdr pcap; - struct bpf_insn *fcode = p->fcode.bf_insns; - struct timeval now, expiry; - BYTE *rx_buf; + struct timeval now, expiry = { 0,0 }; int rx_len = 0; - if (p->inter_packet_wait > 0) + if (p->opt.timeout > 0) { gettimeofday2 (&now, NULL); - expiry.tv_usec = now.tv_usec + 1000UL * p->inter_packet_wait; + expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout; expiry.tv_sec = now.tv_sec; while (expiry.tv_usec >= 1000000L) { @@ -238,13 +253,11 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) if (dev->peek_rx_buf) { PCAP_ASSERT (dev->release_rx_buf); - rx_len = (*dev->peek_rx_buf) (&rx_buf); + rx_len = (*dev->peek_rx_buf) (&p->buffer); } else { - BYTE buf [ETH_MAX+100]; /* add some margin */ - rx_len = (*dev->copy_rx_buf) (buf, p->snapshot); - rx_buf = buf; + rx_len = (*dev->copy_rx_buf) (p->buffer, p->snapshot); } if (rx_len > 0) /* got a packet */ @@ -257,7 +270,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) pcap.len = rx_len; if (callback && - (!fcode || bpf_filter(fcode, rx_buf, pcap.len, pcap.caplen))) + (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen))) { filter_count++; @@ -265,11 +278,11 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) * capture. */ gettimeofday2 (&pcap.ts, NULL); - (*callback) (data, &pcap, rx_buf); + (*callback) (data, &pcap, p->buffer); } if (dev->release_rx_buf) - (*dev->release_rx_buf) (rx_buf); + (*dev->release_rx_buf) (p->buffer); if (pcap_pkt_debug > 0) { @@ -281,10 +294,22 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) return (1); } - /* If not to wait for a packet or pcap_close() called from + /* Has "pcap_breakloop()" been called? + */ + if (p->break_loop) { + /* + * Yes - clear the flag that indicates that it + * has, and return -2 to indicate that we were + * told to break out of the loop. + */ + p->break_loop = 0; + return (-2); + } + + /* If not to wait for a packet or pcap_cleanup_dos() called from * e.g. SIGINT handler, exit loop now. */ - if (p->inter_packet_wait <= 0 || (volatile int)p->fd <= 0) + if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0) break; gettimeofday2 (&now, NULL); @@ -296,13 +321,13 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) kbhit(); /* a real CPU hog */ #endif - if (p->wait_proc) - (*p->wait_proc)(); /* call yield func */ + if (pd->wait_proc) + (*pd->wait_proc)(); /* call yield func */ } if (rx_len < 0) /* receive error */ { - p->md.stat.ps_drop++; + pd->stat.ps_drop++; #ifdef USE_32BIT_DRIVERS if (pcap_pkt_debug > 1) printk ("pkt-err %s\n", pktInfo.error); @@ -317,7 +342,7 @@ pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data) { int rc, num = 0; - while (num <= cnt || (cnt < 0)) + while (num <= cnt || PACKET_COUNT_IS_UNLIMITED(cnt)) { if (p->fd <= 0) return (-1); @@ -337,6 +362,7 @@ pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data) static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps) { struct net_device_stats *stats; + struct pcap_dos *pd; struct device *dev = p ? get_device(p->fd) : NULL; if (!dev) @@ -353,12 +379,13 @@ static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps) FLUSHK(); - p->md.stat.ps_recv = stats->rx_packets; - p->md.stat.ps_drop += stats->rx_missed_errors; - p->md.stat.ps_ifdrop = stats->rx_dropped + /* queue full */ + pd = p->priv; + pd->stat.ps_recv = stats->rx_packets; + pd->stat.ps_drop += stats->rx_missed_errors; + pd->stat.ps_ifdrop = stats->rx_dropped + /* queue full */ stats->rx_errors; /* HW errors */ if (ps) - *ps = p->md.stat; + *ps = pd->stat; return (0); } @@ -383,7 +410,7 @@ int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se) strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics", PCAP_ERRBUF_SIZE); return (-1); - } + } memcpy (se, (*dev->get_stats)(dev), sizeof(*se)); return (0); } @@ -420,12 +447,15 @@ u_long pcap_filter_packets (void) /* * Close pcap device. Not called for offline captures. */ -static void pcap_close_dos (pcap_t *p) +static void pcap_cleanup_dos (pcap_t *p) { - if (p && !exc_occured) + struct pcap_dos *pd; + + if (!exc_occured) { + pd = p->priv; if (pcap_stats(p,NULL) < 0) - p->md.stat.ps_drop = 0; + pd->stat.ps_drop = 0; if (!get_device(p->fd)) return; @@ -474,47 +504,52 @@ char *pcap_lookupdev (char *ebuf) int pcap_lookupnet (const char *device, bpf_u_int32 *localnet, bpf_u_int32 *netmask, char *errbuf) { + DWORD mask, net; + if (!_watt_is_init) { - strcpy (errbuf, "pcap_open_offline() or pcap_open_live() must be " + strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be " "called first"); return (-1); } - *netmask = _w32_sin_mask; - *localnet = my_ip_addr & *netmask; - if (*localnet == 0) + mask = _w32_sin_mask; + net = my_ip_addr & mask; + if (net == 0) { if (IN_CLASSA(*netmask)) - *localnet = IN_CLASSA_NET; + net = IN_CLASSA_NET; else if (IN_CLASSB(*netmask)) - *localnet = IN_CLASSB_NET; + net = IN_CLASSB_NET; else if (IN_CLASSC(*netmask)) - *localnet = IN_CLASSC_NET; + net = IN_CLASSC_NET; else { - sprintf (errbuf, "inet class for 0x%lx unknown", *netmask); + pcap_snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask); return (-1); } } + *localnet = htonl (net); + *netmask = htonl (mask); + ARGSUSED (device); return (0); -} +} /* * Get a list of all interfaces that are present and that we probe okay. * Returns -1 on error, 0 otherwise. - * The list, as returned through "alldevsp", may be null if no interfaces + * The list, as returned through "alldevsp", may be NULL if no interfaces * were up and could be opened. */ -int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf) +int pcap_platform_finddevs (pcap_if_t **alldevsp, char *errbuf) { struct device *dev; - struct sockaddr_ll sa_ll_1, sa_ll_2; + struct sockaddr_in sa_ll_1, sa_ll_2; struct sockaddr *addr, *netmask, *broadaddr, *dstaddr; pcap_if_t *devlist = NULL; int ret = 0; - size_t addr_size = sizeof(struct sockaddr_ll); + size_t addr_size = sizeof(*addr); for (dev = (struct device*)dev_base; dev; dev = dev->next) { @@ -529,14 +564,14 @@ int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf) memset (&sa_ll_1, 0, sizeof(sa_ll_1)); memset (&sa_ll_2, 0, sizeof(sa_ll_2)); - sa_ll_1.sll_family = AF_PACKET; - sa_ll_2.sll_family = AF_PACKET; + sa_ll_1.sin_family = AF_INET; + sa_ll_2.sin_family = AF_INET; addr = (struct sockaddr*) &sa_ll_1; netmask = (struct sockaddr*) &sa_ll_1; dstaddr = (struct sockaddr*) &sa_ll_1; broadaddr = (struct sockaddr*) &sa_ll_2; - memset (&sa_ll_2.sll_addr, 0xFF, sizeof(sa_ll_2.sll_addr)); + memset (&sa_ll_2.sin_addr, 0xFF, sizeof(sa_ll_2.sin_addr)); if (pcap_add_if(&devlist, dev->name, dev->flags, dev->long_name, errbuf) < 0) @@ -544,13 +579,15 @@ int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf) ret = -1; break; } - if (add_addr_to_iflist(&devlist,dev->name, dev->flags, addr, addr_size, +#if 0 /* Pkt drivers should have no addresses */ + if (add_addr_to_iflist(&devlist, dev->name, dev->flags, addr, addr_size, netmask, addr_size, broadaddr, addr_size, dstaddr, addr_size, errbuf) < 0) { ret = -1; break; } +#endif } if (devlist && ret < 0) @@ -586,8 +623,10 @@ void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait) { if (p) { - p->wait_proc = yield; - p->inter_packet_wait = wait; + struct pcap_dos *pd = p->priv; + + pd->wait_proc = yield; + p->opt.timeout = wait; } } @@ -612,7 +651,7 @@ open_driver (const char *dev_name, char *ebuf, int promisc) if (!(*dev->probe)(dev)) /* call the xx_probe() function */ { - sprintf (ebuf, "failed to detect device `%s'", dev_name); + pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to detect device `%s'", dev_name); return (NULL); } probed_dev = dev; /* device is probed okay and may be used */ @@ -634,7 +673,7 @@ open_driver (const char *dev_name, char *ebuf, int promisc) if (!(*dev->open)(dev)) { - sprintf (ebuf, "failed to activate device `%s'", dev_name); + pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name); if (pktInfo.error && !strncmp(dev->name,"pkt",3)) { strcat (ebuf, ": "); @@ -656,14 +695,14 @@ open_driver (const char *dev_name, char *ebuf, int promisc) */ if (!dev) { - sprintf (ebuf, "device `%s' not supported", dev_name); + pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name); return (NULL); } not_probed: if (!probed_dev) { - sprintf (ebuf, "device `%s' not probed", dev_name); + pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name); return (NULL); } return (dev); @@ -733,13 +772,13 @@ static void exc_handler (int sig) fprintf (stderr, "Catching signal %d.\n", sig); } exc_occured = 1; - pcap_close_dos (NULL); + close_driver(); } #endif /* __DJGPP__ */ /* - * Open the pcap device for the first client calling pcap_open_live() + * Open the pcap device for the first client calling pcap_activate() */ static int first_init (const char *name, char *ebuf, int promisc) { @@ -910,7 +949,7 @@ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf) if (_watt_is_init) sock_exit(); - env = getenv ("PCAP_DEBUG"); + env = getenv ("PCAP_TRACE"); if (env && atoi(env) > 0 && pcap_pkt_debug < 0) /* if not already set */ { @@ -937,7 +976,7 @@ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf) * have default values. Should be taken from another * ini-file/environment in any case (ref. tcpdump.ini) */ - _watt_is_init = 1; + _watt_is_init = 1; if (!using_pktdrv || !has_ip_addr) /* for now .... */ { @@ -950,7 +989,7 @@ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf) } else if (rc && using_pktdrv) { - sprintf (err_buf, "sock_init() failed, code %d", rc); + pcap_snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc); return (0); } @@ -990,7 +1029,7 @@ int EISA_bus = 0; /* Where is natural place for this? */ * Application config hooks to set various driver parameters. */ -static struct config_table debug_tab[] = { +static const struct config_table debug_tab[] = { { "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug }, { "PKT.VECTOR", ARG_ATOX_W, NULL }, { "NDIS.DEBUG", ARG_ATOI, NULL }, @@ -1030,9 +1069,9 @@ static struct config_table debug_tab[] = { * pcap_config_hook() is an extension to application's config * handling. Uses Watt-32's config-table function. */ -int pcap_config_hook (const char *name, const char *value) +int pcap_config_hook (const char *keyword, const char *value) { - return parse_config_table (debug_tab, NULL, name, value); + return parse_config_table (debug_tab, NULL, keyword, value); } /* @@ -1069,7 +1108,7 @@ static int pkt_open (struct device *dev) if (!PktInitDriver(mode)) return (0); - + PktResetStatistics (pktInfo.handle); PktQueueBusy (FALSE); return (1); @@ -1267,7 +1306,7 @@ struct device rtl8139_dev LOCKED_VAR = { 0,0,0,0,0,0, &cs89_dev, rtl8139_probe /* dev->probe routine */ - }; + }; /* * Dequeue routine is called by polling.