⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcap-pf.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		snprintf(ebuf, PCAP_ERRBUF_SIZE,		    "pcap_open_live: %s", pcap_strerror(errno));		return (0);	}	memset(p, 0, sizeof(*p));	/*	 * Initially try a read/write open (to allow the inject	 * method to work).  If that fails due to permission	 * issues, fall back to read-only.  This allows a	 * non-root user to be granted specific access to pcap	 * capabilities via file permissions.	 *	 * XXX - we should have an API that has a flag that	 * controls whether to open read-only or read-write,	 * so that denial of permission to send (or inability	 * to send, if sending packets isn't supported on	 * the device in question) can be indicated at open	 * time.	 *	 * XXX - we assume here that "pfopen()" does not, in fact, modify	 * its argument, even though it takes a "char *" rather than a	 * "const char *" as its first argument.  That appears to be	 * the case, at least on Digital UNIX 4.0.	 */	p->fd = pfopen(device, O_RDWR);	if (p->fd == -1 && errno == EACCES)		p->fd = pfopen(device, O_RDONLY);	if (p->fd < 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\your system may not be properly configured; see the packetfilter(4) man page\n",			device, pcap_strerror(errno));		goto bad;	}	p->md.OrigMissed = -1;	enmode = ENTSTAMP|ENBATCH|ENNONEXCL;	if (promisc)		enmode |= ENPROMISC;	if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s",		    pcap_strerror(errno));		goto bad;	}#ifdef	ENCOPYALL	/* Try to set COPYALL mode so that we see packets to ourself */	enmode = ENCOPYALL;	(void)ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode);/* OK if this fails */#endif	/* set the backlog */	if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s",		    pcap_strerror(errno));		goto bad;	}	/* discover interface type */	if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s",		    pcap_strerror(errno));		goto bad;	}	/* HACK: to compile prior to Ultrix 4.2 */#ifndef	ENDT_FDDI#define	ENDT_FDDI	4#endif	switch (devparams.end_dev_type) {	case ENDT_10MB:		p->linktype = DLT_EN10MB;		p->offset = 2;		/*		 * This is (presumably) a real Ethernet capture; give it a		 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so		 * that an application can let you choose it, in case you're		 * capturing DOCSIS traffic that a Cisco Cable Modem		 * Termination System is putting out onto an Ethernet (it		 * doesn't put an Ethernet header onto the wire, it puts raw		 * DOCSIS frames out on the wire inside the low-level		 * Ethernet framing).		 */		p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);		/*		 * If that fails, just leave the list empty.		 */		if (p->dlt_list != NULL) {			p->dlt_list[0] = DLT_EN10MB;			p->dlt_list[1] = DLT_DOCSIS;			p->dlt_count = 2;		}		break;	case ENDT_FDDI:		p->linktype = DLT_FDDI;		break;#ifdef ENDT_SLIP	case ENDT_SLIP:		p->linktype = DLT_SLIP;		break;#endif#ifdef ENDT_PPP	case ENDT_PPP:		p->linktype = DLT_PPP;		break;#endif#ifdef ENDT_LOOPBACK	case ENDT_LOOPBACK:		/*		 * It appears to use Ethernet framing, at least on		 * Digital UNIX 4.0.		 */		p->linktype = DLT_EN10MB;		p->offset = 2;		break;#endif#ifdef ENDT_TRN	case ENDT_TRN:		p->linktype = DLT_IEEE802;		break;#endif	default:		/*		 * XXX - what about ENDT_IEEE802?  The pfilt.h header		 * file calls this "IEEE 802 networks (non-Ethernet)",		 * but that doesn't specify a specific link layer type;		 * it could be 802.4, or 802.5 (except that 802.5 is		 * ENDT_TRN), or 802.6, or 802.11, or....  That's why		 * DLT_IEEE802 was hijacked to mean Token Ring in various		 * BSDs, and why we went along with that hijacking.		 *		 * XXX - what about ENDT_HDLC and ENDT_NULL?		 * Presumably, as ENDT_OTHER is just "Miscellaneous		 * framing", there's not much we can do, as that		 * doesn't specify a particular type of header.		 */		snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown data-link type %u",		    devparams.end_dev_type);		goto bad;	}	/* set truncation */#ifdef PCAP_FDDIPAD	if (p->linktype == DLT_FDDI) {		p->fddipad = PCAP_FDDIPAD;		/* packetfilter includes the padding in the snapshot */		snaplen += PCAP_FDDIPAD;	} else		p->fddipad = 0;#endif	if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",		    pcap_strerror(errno));		goto bad;	}	p->snapshot = snaplen;	/* accept all packets */	memset(&Filter, 0, sizeof(Filter));	Filter.enf_Priority = 37;	/* anything > 2 */	Filter.enf_FilterLen = 0;	/* means "always true" */	if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s",		    pcap_strerror(errno));		goto bad;	}	if (to_ms != 0) {		struct timeval timeout;		timeout.tv_sec = to_ms / 1000;		timeout.tv_usec = (to_ms * 1000) % 1000000;		if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {			snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s",				pcap_strerror(errno));			goto bad;		}	}	p->bufsize = BUFSPACE;	p->buffer = (u_char*)malloc(p->bufsize + p->offset);	if (p->buffer == NULL) {		strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);		goto bad;	}	/*	 * "select()" and "poll()" work on packetfilter devices.	 */	p->selectable_fd = p->fd;	p->read_op = pcap_read_pf;	p->inject_op = pcap_inject_pf;	p->setfilter_op = pcap_setfilter_pf;	p->setdirection_op = NULL;	/* Not implemented. */	p->set_datalink_op = NULL;	/* can't change data link type */	p->getnonblock_op = pcap_getnonblock_fd;	p->setnonblock_op = pcap_setnonblock_fd;	p->stats_op = pcap_stats_pf;	p->close_op = pcap_close_common;	return (p); bad:	if (p->fd >= 0)		close(p->fd);	/*	 * Get rid of any link-layer type list we allocated.	 */	if (p->dlt_list != NULL)		free(p->dlt_list);	free(p);	return (NULL);}intpcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf){	return (0);}static intpcap_setfilter_pf(pcap_t *p, struct bpf_program *fp){	struct bpf_version bv;	/*	 * See if BIOCVERSION works.  If not, we assume the kernel doesn't	 * support BPF-style filters (it's not documented in the bpf(7)	 * or packetfiler(7) man pages, but the code used to fail if	 * BIOCSETF worked but BIOCVERSION didn't, and I've seen it do	 * kernel filtering in DU 4.0, so presumably BIOCVERSION works	 * there, at least).	 */	if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) >= 0) {		/*		 * OK, we have the version of the BPF interpreter;		 * is it the same major version as us, and the same		 * or better minor version?		 */		if (bv.bv_major == BPF_MAJOR_VERSION &&		    bv.bv_minor >= BPF_MINOR_VERSION) {			/*			 * Yes.  Try to install the filter.			 */			if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {				snprintf(p->errbuf, sizeof(p->errbuf),				    "BIOCSETF: %s", pcap_strerror(errno));				return (-1);			}			/*			 * OK, that succeeded.  We're doing filtering in			 * the kernel.  (We assume we don't have a			 * userland filter installed - that'd require			 * a previous version check to have failed but			 * this one to succeed.)			 *			 * XXX - this message should be supplied to the			 * application as a warning of some sort,			 * except that if it's a GUI application, it's			 * not clear that it should be displayed in			 * a window to annoy the user.			 */			fprintf(stderr, "tcpdump: Using kernel BPF filter\n");			p->md.use_bpf = 1;			/*			 * Discard any previously-received packets,			 * as they might have passed whatever filter			 * was formerly in effect, but might not pass			 * this filter (BIOCSETF discards packets buffered			 * in the kernel, so you can lose packets in any			 * case).			 */			p->cc = 0;			return (0);		}		/*		 * We can't use the kernel's BPF interpreter; don't give		 * up, just log a message and be inefficient.		 *		 * XXX - this should really be supplied to the application		 * as a warning of some sort.		 */		fprintf(stderr,	    "tcpdump: Requires BPF language %d.%d or higher; kernel is %d.%d\n",		    BPF_MAJOR_VERSION, BPF_MINOR_VERSION,		    bv.bv_major, bv.bv_minor);	}	/*	 * We couldn't do filtering in the kernel; do it in userland.	 */	if (install_bpf_program(p, fp) < 0)		return (-1);	/*	 * XXX - this message should be supplied by the application as	 * a warning of some sort.	 */	fprintf(stderr, "tcpdump: Filtering in user process\n");	p->md.use_bpf = 0;	return (0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -