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

📄 net-pcap.cc

📁 柯老师网站上找到的
💻 CC
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 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 the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by the University of *      California, Berkeley and the Network Research Group at *      Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used *    to endorse or promote products derived from this software without *    specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic const char rcsid[] =    "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/emulate/net-pcap.cc,v 1.17 2000/02/08 23:35:13 salehi Exp $ (LBL)";#endif#include <stdio.h>#ifndef WIN32#include <unistd.h>#endif#include <time.h>#include <errno.h>#include <string.h>#ifdef WIN32#include <io.h>#define close closesocket#else#include <sys/param.h>#include <sys/socket.h>#include <sys/ioctl.h>#endif#if defined(sun) && defined(__svr4__)#include <sys/systeminfo.h>#endif#ifdef __cplusplusextern "C" {#include <pcap.h>}#else#include <pcap.h>#endif#include "config.h"#include "scheduler.h"#include "net.h"#include "tclcl.h"/* * observations about pcap library *	device name is in the ifreq struct sense, should be doc'd *	pcap_lookupdev returns a ptr to static data *	q: does lookupdev only return devs in the AF_INET addr family? *	why does pcap_compile require a netmask? seems odd *	would like some way to tell it what buffer to use *	arriving packets have the link layer hdr at the beginning, doc *	not convenient/possible to open bpf read/write *	no real way to know what file (/dev/bpf?) it is using *		would be nice if pcap_lookdev helped out more by *		returning ifnet or ifreq or whatever structure *	pcap_lookupnet makes calls to get our addr, but *		then tosses it anyhow, should get us addr and netmask *	interface type codes could be via rfc1573 *		see freebsd net/if_types.h *	want a way to set immed mode *	pcap_next masks errors by returning 0 if pcap_dispatch fails *	a pcap_t carries it's own internal buffer, and *		_dispatch gives pointers into it when invoked [eek] *	when you open pcap using a file, pcap_fileno always *		returns -1; not so convenient *	 */#define	PNET_PSTATE_INACTIVE	0#define	PNET_PSTATE_ACTIVE	1//// PcapNetwork: a "network" (source or possibly sink of packets)//	this is a base class only-- the derived classes are://	PcapLiveNetwork [a live net; currently bpf + ethernet]//	PcapFileNetwork [packets from a tcpdump-style trace file]//class PcapNetwork : public Network {public:	PcapNetwork() : t_firstpkt_(0.0),		pfd_(-1), pcnt_(0), local_netmask_(0) { }	int rchannel() { return(pfd_); }	int schannel() { return(pfd_); }	virtual int command(int argc, const char*const* argv);	virtual int open(int mode, const char *) = 0;	virtual int skiphdr() = 0;	virtual double gents(pcap_pkthdr*) = 0;		// generate timestamp	int recv(u_char *buf, int len, sockaddr&, double&); // get from net	int send(u_char *buf, int len);			// write to net	void close();	void reset();	int filter(const char*);	// compile + install a filter	int stat_pkts();	int stat_pdrops();	double offset_;			// time offset to 1st pkt in a trace	double t_firstpkt_;		// ts of 1st pkt recvdprotected:	static void phandler(u_char* u, pcap_pkthdr* h, u_char* p);	virtual void bindvars() = 0;	char errbuf_[PCAP_ERRBUF_SIZE];		// place to put err msgs	char srcname_[PATH_MAX];		// device or file name	int pfd_;				// pcap fd	int pcnt_;				// # pkts counted	int state_;				// PNET_PSTATE_xxx (above)	int optimize_;				// bpf optimizer enable	pcap_t* pcap_;				// reference to pcap state	struct bpf_program bpfpgm_;		// generated program	struct pcap_stat pcs_;			// status	unsigned int local_netmask_;	// seems shouldn't be necessary :(};//// PcapLiveNetwork: a live network tap//struct NetworkAddress {        u_int   len_;        u_char  addr_[16];	// enough for IPv6 ip addr};class PcapLiveNetwork : public PcapNetwork {public:	PcapLiveNetwork() : local_net_(0), dlink_type_(-1) {		linkaddr_.len_ = 0;		netaddr_.len_ = 0;		bindvars(); reset();	}	NetworkAddress& laddr() { return (linkaddr_); }	NetworkAddress& naddr() { return (netaddr_); }protected:	double gents(pcap_pkthdr*) {		return Scheduler::instance().clock();	}	int devtonaddr(const char* name, NetworkAddress&);	int open(int mode);	int open(int mode, const char*);	int command(int argc, const char*const* argv);	int skiphdr();	const char*	autodevname();	void		bindvars();	int snaplen_;		// # of bytes to grab	int promisc_;		// put intf into promisc mode?	double timeout_;	NetworkAddress	linkaddr_;	// link-layer address	NetworkAddress	netaddr_;	// network-layer (IP) address	unsigned int local_net_;	int dlink_type_;		// data link type (see pcap)private:	// XXX somewhat specific to bpf-- this stuff is  a hack until pcap	// can be fixed to allow for opening the bpf r/w#ifdef MT_OWN_PCAP	pcap_t * pcap_open_live(char *, int slen, int prom, int, char *, int);	int bpf_open(pcap_t *p, char *errbuf, int how);#endif};class PcapFileNetwork : public PcapNetwork {public:	int open(int mode, const char *);	int skiphdr() { return 0; }	// XXX check meprotected:	double gents(pcap_pkthdr* p) {		// time stamp of packet is its relative time		// in the trace file, plus sim start time, plus offset		double pts = p->ts.tv_sec + p->ts.tv_usec * 0.000001;		pts -= t_firstpkt_;		pts += offset_ + Scheduler::instance().clock();		return (pts);	}	void bindvars();	int command(int argc, const char*const* argv);};static class PcapLiveNetworkClass : public TclClass {public:	PcapLiveNetworkClass() : TclClass("Network/Pcap/Live") {}	TclObject* create(int, const char*const*) {		return (new PcapLiveNetwork);	}} net_pcaplive;static class PcapFileNetworkClass : public TclClass {public:	PcapFileNetworkClass() : TclClass("Network/Pcap/File") {}	TclObject* create(int, const char*const*) {		return (new PcapFileNetwork);	}} net_pcapfile;//// defs for base PcapNetwork class//voidPcapNetwork::bindvars(){	bind_bool("optimize_", &optimize_);}voidPcapNetwork::reset(){	state_ = PNET_PSTATE_INACTIVE;	pfd_ = -1;	pcap_ = NULL;	*errbuf_ = '\0';	*srcname_ = '\0';	pcnt_ = 0;}voidPcapNetwork::close(){	if (state_ == PNET_PSTATE_ACTIVE && pcap_)		pcap_close(pcap_);	reset();}/* compile up a bpf program *//* XXXwe aren't using 'bcast', so don't care about mask... sigh */intPcapNetwork::filter(const char *pgm){	if (pcap_compile(pcap_, &bpfpgm_, (char *)pgm,	    optimize_, local_netmask_) < 0) {		fprintf(stderr, "pcapnet obj(%s): couldn't compile filter pgm",			name());		return -1;	}	if (pcap_setfilter(pcap_, &bpfpgm_) < 0) {		fprintf(stderr, "pcapnet obj(%s): couldn't set filter pgm",			name());		return -1;	}	return(bpfpgm_.bf_len);}/* return number of pkts received */intPcapNetwork::stat_pkts(){	if (pcap_stats(pcap_, &pcs_) < 0)		return (-1);	return (pcs_.ps_recv);}/* return number of pkts dropped */intPcapNetwork::stat_pdrops(){	if (pcap_stats(pcap_, &pcs_) < 0)		return (-1);	return (pcs_.ps_drop);}#ifndef MIN#define MIN(x, y) ((x)<(y) ? (x) : (y))#endif#include "ether.h"/* recv is what others call to grab a packet from the pfilter */struct pcap_singleton {        struct pcap_pkthdr *hdr;        const u_char *pkt;};   voidPcapNetwork::phandler(u_char* userdata, pcap_pkthdr* ph, u_char* pkt){	pcap_singleton *ps = (pcap_singleton*) userdata;	ps->hdr = ph;	ps->pkt = pkt;}intPcapNetwork::recv(u_char *buf, int len, sockaddr& /*fromaddr*/, double &ts){	if (state_ != PNET_PSTATE_ACTIVE) {		fprintf(stderr, "warning: net/pcap obj(%s) read-- not active\n",			name());		return -1;	}	int pktcnt = 1;		// all in buffer, or until error	int np;			// counts # of pkts dispatched	pcap_singleton ps = { 0, 0 };	np = pcap_dispatch(pcap_, pktcnt, phandler, (u_char*) &ps);	if (np < 0) {		fprintf(stderr,			"PcapNetwork(%s): recv: pcap_dispatch: %s\n",			    name(), pcap_strerror(errno));		return (np);	} else if (np == 0) {		/* we get here on EOF of a Pcap/File Network */		return (np);	} else if (np != pktcnt) {		fprintf(stderr,			"PcapNetwork(%s): warning: recv: pcap_dispatch: requested pktcnt (%d) doesn't match actual (%d)\n",			    name(), pktcnt, np);	}	pcap_pkthdr* ph = ps.hdr;	if (ph == NULL || ps.pkt == NULL) {		fprintf(stderr,			"PcapNetwork(%s): recv: pcap_dispatch: no packet present\n",			    name());		return (-1);	}	if (++pcnt_ == 1) {		// mark time stamp of first pkt		t_firstpkt_ = ph->ts.tv_sec + ph->ts.tv_usec * 0.000001;	}	int n = MIN(ph->caplen, (unsigned)len);	ts = gents(ph);	// mark with timestamp	// link layer header will be placed at the beginning from pcap	int s = skiphdr();	// go to IP header	memcpy(buf, ps.pkt + s, n - s);	return n - s;}/* send a packet out through the packet filter */intPcapNetwork::send(u_char *buf, int len){	int n;	if ((n = write(pfd_, buf, len)) < 0)		perror("write to pcap fd");	return n;}int PcapNetwork::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 2) {		if (strcmp(argv[1], "close") == 0) {			close();			return (TCL_OK);		}		if (strcmp(argv[1], "srcname") == 0) {			tcl.result(srcname_);			return (TCL_OK);		}		if (strcmp(argv[1], "pkts") == 0) {			tcl.resultf("%d", stat_pkts());			return (TCL_OK);		}		if (strcmp(argv[1], "pdrops") == 0) {			tcl.resultf("%d", stat_pdrops());			return (TCL_OK);		}	} else if (argc == 3) {		if (strcmp(argv[1], "filter") == 0) {			if (state_ != PNET_PSTATE_ACTIVE) {				fprintf(stderr, "net/pcap obj(%s): can't install filter prior to opening data source\n",					name());				return (TCL_ERROR);			}			int plen;			if ((plen = filter(argv[2])) < 0) {				fprintf(stderr, "problem compiling/installing filter program\n");				return (TCL_ERROR);			}			tcl.resultf("%d", plen);			return (TCL_OK);		}	}	return (Network::command(argc, argv));}//// defs for PcapLiveNetwork//#include <fcntl.h>#include <net/if.h>intPcapLiveNetwork::open(int mode, const char *devname){	close();#ifdef MY_OWN_PCAP	pcap_ = pcap_open_live((char*) devname, snaplen_, promisc_,			       int(timeout_ * 1000.), errbuf_, mode);#else	pcap_ = pcap_open_live((char*) devname, snaplen_, promisc_,			       int(timeout_ * 1000.), errbuf_);#endif // MY_OWN_PCAP	if (pcap_ == NULL) {		fprintf(stderr,		  "pcap/live object (%s) couldn't open packet source %s: %s\n",			name(), devname, errbuf_);		return -1;	}	mode_ = mode;

⌨️ 快捷键说明

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