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

📄 pcap-bpf.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1993, 1994, 1995, 1996, 1998 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#ifndef lintstatic const char rcsid[] _U_ =    "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.86.2.9 2006/01/22 05:28:34 guy Exp $ (LBL)";#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <sys/param.h>			/* optionally get BSD define */#include <sys/time.h>#include <sys/timeb.h>#include <sys/socket.h>#include <sys/file.h>#include <sys/ioctl.h>#include <sys/utsname.h>#include <net/if.h>#ifdef _AIX/* * Make "pcap.h" not include "pcap-bpf.h"; we are going to include the * native OS version, as we need "struct bpf_config" from it. */#define PCAP_DONT_INCLUDE_PCAP_BPF_H#include <sys/types.h>/* * Prevent bpf.h from redefining the DLT_ values to their * IFT_ values, as we're going to return the standard libpcap * values, not IBM's non-standard IFT_ values. */#undef _AIX#include <net/bpf.h>#define _AIX#include <net/if_types.h>		/* for IFT_ values */#include <sys/sysconfig.h>#include <sys/device.h>#include <sys/cfgodm.h>#include <cf.h>#ifdef __64BIT__#define domakedev makedev64#define getmajor major64#define bpf_hdr bpf_hdr32#else /* __64BIT__ */#define domakedev makedev#define getmajor major#endif /* __64BIT__ */#define BPF_NAME "bpf"#define BPF_MINORS 4#define DRIVER_PATH "/usr/lib/drivers"#define BPF_NODE "/dev/bpf"static int bpfloadedflag = 0;static int odmlockid = 0;#else /* _AIX */#include <net/bpf.h>#endif /* _AIX */#include <ctype.h>#include <errno.h>#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "pcap-int.h"#ifdef HAVE_DAG_API#include "pcap-dag.h"#endif /* HAVE_DAG_API */#ifdef HAVE_OS_PROTO_H#include "os-proto.h"#endif#ifdef HAVE_REMOTE#include <pcap-remote.h>#endif /* HAVE_REMOTE */#include "gencode.h"	/* for "no_optimize" */static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp);static int pcap_setdirection_bpf(pcap_t *, pcap_direction_t);static int pcap_set_datalink_bpf(pcap_t *p, int dlt);static intpcap_stats_bpf(pcap_t *p, struct pcap_stat *ps){	struct bpf_stat s;	/*	 * "ps_recv" counts packets handed to the filter, not packets	 * that passed the filter.  This includes packets later dropped	 * because we ran out of buffer space.	 *	 * "ps_drop" counts packets dropped inside the BPF device	 * because we ran out of buffer space.  It doesn't count	 * packets dropped by the interface driver.  It counts	 * only packets that passed the filter.	 *	 * Both statistics include packets not yet read from the kernel	 * by libpcap, and thus not yet seen by the application.	 */	if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",		    pcap_strerror(errno));		return (-1);	}	ps->ps_recv = s.bs_recv;	ps->ps_drop = s.bs_drop;	return (0);}static intpcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user){	int cc;	int n = 0;	register u_char *bp, *ep;	u_char *datap;	struct bpf_insn *fcode;#ifdef PCAP_FDDIPAD	register int pad;#endif	fcode = p->md.use_bpf ? NULL : p->fcode.bf_insns; again:	/*	 * 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);	}	cc = p->cc;	if (p->cc == 0) {		cc = read(p->fd, (char *)p->buffer, p->bufsize);		if (cc < 0) {			/* Don't choke when we get ptraced */			switch (errno) {			case EINTR:				goto again;#ifdef _AIX			case EFAULT:				/*				 * Sigh.  More AIX wonderfulness.				 *				 * For some unknown reason the uiomove()				 * operation in the bpf kernel extension				 * used to copy the buffer into user 				 * space sometimes returns EFAULT. I have				 * no idea why this is the case given that				 * a kernel debugger shows the user buffer 				 * is correct. This problem appears to 				 * be mostly mitigated by the memset of 				 * the buffer before it is first used. 				 * Very strange.... Shaun Clowes				 *				 * In any case this means that we shouldn't 				 * treat EFAULT as a fatal error; as we				 * don't have an API for returning				 * a "some packets were dropped since				 * the last packet you saw" indication,				 * we just ignore EFAULT and keep reading.				 */				goto again;#endif   			case EWOULDBLOCK:				return (0);#if defined(sun) && !defined(BSD)			/*			 * Due to a SunOS bug, after 2^31 bytes, the kernel			 * file offset overflows and read fails with EINVAL.			 * The lseek() to 0 will fix things.			 */			case EINVAL:				if (lseek(p->fd, 0L, SEEK_CUR) +				    p->bufsize < 0) {					(void)lseek(p->fd, 0L, SEEK_SET);					goto again;				}				/* fall through */#endif			}			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",			    pcap_strerror(errno));			return (-1);		}		bp = p->buffer;	} else		bp = p->bp;	/*	 * Loop through each packet.	 */#define bhp ((struct bpf_hdr *)bp)	ep = bp + cc;#ifdef PCAP_FDDIPAD	pad = p->fddipad;#endif	while (bp < ep) {		register int caplen, hdrlen;		/*		 * Has "pcap_breakloop()" been called?		 * If so, return immediately - if we haven't read any		 * packets, clear the flag and return -2 to indicate		 * that we were told to break out of the loop, otherwise		 * leave the flag set, so that the *next* call will break		 * out of the loop without having read any packets, and		 * return the number of packets we've processed so far.		 */		if (p->break_loop) {			if (n == 0) {				p->break_loop = 0;				return (-2);			} else {				p->bp = bp;				p->cc = ep - bp;				return (n);			}		}		caplen = bhp->bh_caplen;		hdrlen = bhp->bh_hdrlen;		datap = bp + hdrlen;		/*		 * Short-circuit evaluation: if using BPF filter		 * in kernel, no need to do it now.		 *#ifdef PCAP_FDDIPAD		 * Note: the filter code was generated assuming		 * that p->fddipad was the amount of padding		 * before the header, as that's what's required		 * in the kernel, so we run the filter before		 * skipping that padding.#endif		 */		if (fcode == NULL ||		    bpf_filter(fcode, datap, bhp->bh_datalen, caplen)) {			struct pcap_pkthdr pkthdr;			pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec;#ifdef _AIX			/*			 * AIX's BPF returns seconds/nanoseconds time			 * stamps, not seconds/microseconds time stamps.			 */			pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec/1000;#else			pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec;#endif#ifdef PCAP_FDDIPAD			if (caplen > pad)				pkthdr.caplen = caplen - pad;			else				pkthdr.caplen = 0;			if (bhp->bh_datalen > pad)				pkthdr.len = bhp->bh_datalen - pad;			else				pkthdr.len = 0;			datap += pad;#else			pkthdr.caplen = caplen;			pkthdr.len = bhp->bh_datalen;#endif			(*callback)(user, &pkthdr, datap);			bp += BPF_WORDALIGN(caplen + hdrlen);			if (++n >= cnt && cnt > 0) {				p->bp = bp;				p->cc = ep - bp;				return (n);			}		} else {			/*			 * Skip this packet.			 */			bp += BPF_WORDALIGN(caplen + hdrlen);		}	}#undef bhp	p->cc = 0;	return (n);}static intpcap_inject_bpf(pcap_t *p, const void *buf, size_t size){	int ret;	ret = write(p->fd, buf, size);#ifdef __APPLE__	if (ret == -1 && errno == EAFNOSUPPORT) {		/*		 * In Mac OS X, there's a bug wherein setting the		 * BIOCSHDRCMPLT flag causes writes to fail; see,		 * for example:		 *		 *	http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/BIOCSHDRCMPLT-10.3.3.patch		 *		 * So, if, on OS X, we get EAFNOSUPPORT from the write, we		 * assume it's due to that bug, and turn off that flag		 * and try again.  If we succeed, it either means that		 * somebody applied the fix from that URL, or other patches		 * for that bug from		 *		 *	http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/		 *		 * and are running a Darwin kernel with those fixes, or		 * that Apple fixed the problem in some OS X release.		 */		u_int spoof_eth_src = 0;		if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {			(void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,			    "send: can't turn off BIOCSHDRCMPLT: %s",			    pcap_strerror(errno));			return (-1);		}		/*		 * Now try the write again.		 */		ret = write(p->fd, buf, size);	}#endif /* __APPLE__ */	if (ret == -1) {		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",		    pcap_strerror(errno));		return (-1);	}	return (ret);}#ifdef _AIXstatic int bpf_odminit(char *errbuf){	char *errstr;	if (odm_initialize() == -1) {		if (odm_err_msg(odmerrno, &errstr) == -1)			errstr = "Unknown error";		snprintf(errbuf, PCAP_ERRBUF_SIZE,		    "bpf_load: odm_initialize failed: %s",		    errstr);		return (-1);	}	if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) {		if (odm_err_msg(odmerrno, &errstr) == -1)			errstr = "Unknown error";

⌨️ 快捷键说明

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