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

📄 net-pcap.cc

📁 柯老师网站上找到的
💻 CC
📖 第 1 页 / 共 2 页
字号:
	dlink_type_ = pcap_datalink(pcap_);	pfd_ = pcap_fileno(pcap_);	strncpy(srcname_, devname, sizeof(srcname_)-1);	{		// use SIOCGIFADDR hook in bpf to get link addr		struct ifreq ifr;		struct sockaddr *sa = &ifr.ifr_addr;#ifdef HAVE_SIOCGIFHWADDR		memset(&ifr, 0, sizeof(struct ifreq));		strcpy(ifr.ifr_name, devname);		if (ioctl(pfd_, SIOCGIFHWADDR, &ifr) < 0) {			fprintf(stderr,			  "pcap/live (%s) SIOCGIFHWADDR on bpf fd %d\n",			  name(), pfd_);		}#else		if (ioctl(pfd_, SIOCGIFADDR, &ifr) < 0) {			fprintf(stderr,			  "pcap/live (%s) SIOCGIFADDR on bpf fd %d\n",			  name(), pfd_);		}#endif		if (dlink_type_ != DLT_EN10MB) {			fprintf(stderr,				"sorry, only ethernet supported\n");			return -1;		}		linkaddr_.len_ = ETHER_ADDR_LEN;	// for now		memcpy(linkaddr_.addr_, sa->sa_data, linkaddr_.len_);	}	(void) devtonaddr(devname, netaddr_);	state_ = PNET_PSTATE_ACTIVE;	if (pcap_lookupnet(srcname_, &local_net_, &local_netmask_, errbuf_) < 0) {		fprintf(stderr,		  "warning: pcap/live (%s) couldn't get local IP network info: %s\n",		  name(), errbuf_) ;	}	{		int immed = 1;		if (ioctl(pfd_, BIOCIMMEDIATE, &immed) < 0) {			fprintf(stderr,				"warning: pcap/live (%s) couldn't set immed\n",				name());			perror("ioctl(BIOCIMMEDIATE)");		}	}	return 0;}/* * how many bytes of link-hdr to skip before net-layer hdr */intPcapLiveNetwork::skiphdr(){	switch (dlink_type_) {	case DLT_NULL:		return 0;	case DLT_EN10MB:		return ETHER_HDR_LEN;	default:		fprintf(stderr,		    "Network/Pcap/Live(%s): unknown link type: %d\n",			name(), dlink_type_);	}	return -1;}const char *PcapLiveNetwork::autodevname(){	const char *dname;	if ((dname = pcap_lookupdev(errbuf_)) == NULL) {		fprintf(stderr, "warning: PcapNet/Live(%s) : %s\n",			name(), errbuf_);		return (NULL);	}	return (dname);	// ptr to static data in pcap library}/* * devtonaddr -- map device name to its IP/Network layer address * this routine wouldn't be necessary if pcap_lookupnet gave * out the info it gets anyhow */#include <netinet/in.h>intPcapLiveNetwork::devtonaddr(const char *devname, NetworkAddress& na){        register int fd;        ifreq ifr;                                        fd = socket(AF_INET, SOCK_DGRAM, 0);        if (fd < 0) {                       fprintf(stderr,			"PcapLiveNet(%s): devtoaddr: couldn't create sock\n",			name());                return (-1);        }        memset(&ifr, 0, sizeof(ifr));#ifdef linux        /* XXX Work around Linux kernel bug */        ifr.ifr_addr.sa_family = AF_INET;#endif           (void)strncpy(ifr.ifr_name, devname, sizeof(ifr.ifr_name));        if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {                fprintf(stderr, "PcapLiveNetwork(%s): devtoaddr: no addr\n",			name());                (void)::close(fd);                   return (-1);        }               	sockaddr* sa = &ifr.ifr_addr;	if (sa->sa_family != AF_INET) {                fprintf(stderr,			"PcapLiveNet(%s): af not AF_INET (%d)\n",			name(), sa->sa_family);	}	sockaddr_in* sin = (sockaddr_in*) sa;	na.len_ = 4;				// for now, assump IPv4	memset(na.addr_, 0, sizeof(na.addr_));	unsigned sz = sizeof(na.addr_);	if (sizeof(ifr) < sz)		sz = sizeof(ifr);	memcpy(na.addr_, &sin->sin_addr, sz);	return (0);}voidPcapLiveNetwork::bindvars(){	bind("snaplen_", &snaplen_);	bind_bool("promisc_", &promisc_);	bind_time("timeout_", &timeout_);	bind("offset_", &offset_);	PcapNetwork::bindvars();}voidPcapFileNetwork::bindvars(){	bind("offset_", &offset_);}intPcapLiveNetwork::open(int mode){	return (open(mode, autodevname()));}int PcapLiveNetwork::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 2) {		if (strcmp(argv[1], "linkaddr") == 0) {			/// XXX: only for ethernet now			tcl.result(Ethernet::etheraddr_string(linkaddr_.addr_));			return (TCL_OK);		}		if (strcmp(argv[1], "netaddr") == 0) {			if (netaddr_.len_ != 4) {				fprintf(stderr,				  "PcapLive(%s): net addr not len 4 (%d)\n",					name(), netaddr_.len_);				return (TCL_ERROR);			}			tcl.resultf("%d.%d.%d.%d",				netaddr_.addr_[0],				netaddr_.addr_[1],				netaddr_.addr_[2],				netaddr_.addr_[3]);			return (TCL_OK);		}	} else if (argc == 3) {		// $obj open mode		if (strcmp(argv[1], "open") == 0) {			int mode = parsemode(argv[2]);			if (open(mode) < 0)				return (TCL_ERROR);			tcl.result(srcname_);			return (TCL_OK);		}	} else if (argc == 4) {		// $obj open mode devicename		if (strcmp(argv[1], "open") == 0) {			int mode = parsemode(argv[2]);			if (open(mode, argv[3]) < 0)				return (TCL_ERROR);			tcl.result(srcname_);			return (TCL_OK);		}	}	return (PcapNetwork::command(argc, argv));}//// defs for PcapFileNetwork// use a file instead of a live network//intPcapFileNetwork::open(int /*mode*/, const char *filename){	close();	pcap_ = pcap_open_offline((char*) filename, errbuf_);	if (pcap_ == NULL) {		fprintf(stderr,		  "pcap/file object (%s) couldn't open packet source %s: %s\n",			name(), filename, errbuf_);		return -1;	}	mode_ = O_RDONLY;	// sorry, that's all for now	//	// pcap only ever puts -1 in the pcap_fileno, which	// isn't so convenient, so do this instead:	// pfd_ = pcap_fileno(pcap_);	pfd_ = fileno(pcap_file(pcap_));	strncpy(srcname_, filename, sizeof(srcname_)-1);	state_ = PNET_PSTATE_ACTIVE;	return 0;}int PcapFileNetwork::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 4) {		// $obj open mode filename		if (strcmp(argv[1], "open") == 0) {			int mode = parsemode(argv[2]);			if (open(mode, argv[3]) < 0)				return (TCL_ERROR);			tcl.resultf("%s", argv[3]);			return (TCL_OK);		}	}	return (PcapNetwork::command(argc, argv));}//// XXX: the following routines are unfortunately necessary, //	because libpcap has no obvious was of making the bpf fd//	be read-write :(.  The implication here is nasty://		our own version of bpf_open and pcap_open_live//		and the later routine requires the struct pcap internal state/*    * Savefile */  struct pcap_sf {        FILE *rfile;         int swapped;        int version_major;        int version_minor;        u_char *base;};        struct pcap_md {        struct pcap_stat stat;        /*XXX*/         int use_bpf;        u_long  TotPkts;        /* can't oflow for 79 hrs on ether */        u_long  TotAccepted;    /* count accepted by filter */        u_long  TotDrops;       /* count of dropped packets */        long    TotMissed;      /* missed by i/f during this run */        long    OrigMissed;     /* missed by i/f before this run */#ifdef linux        int pad;        int skip;        char *device;#endif};   struct pcap {        int fd;        int snapshot;        int linktype;        int tzoff;              /* timezone offset */        int offset;             /* offset for proper alignment */        struct pcap_sf sf;        struct pcap_md md;        /*         * Read buffer.         */        int bufsize;        u_char *buffer;        u_char *bp;        int cc;        /*         * Place holder for pcap_next().         */        u_char *pkt;                /*         * Placeholder for filter code if bpf not in kernel.         */        struct bpf_program fcode;        char errbuf[PCAP_ERRBUF_SIZE];};/* * the routines bpf_open and pcap_open_live really * should not be here, and instead should be part of the * pcap library.  Unfortunately, if we ever want to writes to * the bpf fd, we need to open it r/w, and the normal pcap * library does not permit us to do this.  So for now, here * are these routines. */#include <net/if.h>#ifdef MY_OWN_PCAPintPcapLiveNetwork::bpf_open(pcap_t *, char *errbuf, int how){        int fd;        int n = 0;        char device[sizeof "/dev/bpf000"];        /*         * Go through all the minors and find one that isn't in use.         */        do {                (void)sprintf(device, "/dev/bpf%d", n++);                fd = ::open(device, how, 0);        } while (fd < 0 && n < 1000 && errno == EBUSY);        /*         * XXX better message for all minors used         */        if (fd < 0)                sprintf(errbuf, "%s: %s", device, pcap_strerror(errno));        return (fd);}pcap_t *PcapLiveNetwork::pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf, int how){        int fd;        struct ifreq ifr;        struct bpf_version bv;        u_int v;        pcap_t *p;        p = (pcap_t *)malloc(sizeof(*p));        if (p == NULL) {                sprintf(ebuf, "malloc: %s", pcap_strerror(errno));                return (NULL);        }        bzero(p, sizeof(*p));        fd = bpf_open(p, ebuf, how);        if (fd < 0)                goto bad;        p->fd = fd;        p->snapshot = snaplen;        if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {                sprintf(ebuf, "BIOCVERSION: %s", pcap_strerror(errno));                goto bad;        }        if (bv.bv_major != BPF_MAJOR_VERSION ||            bv.bv_minor < BPF_MINOR_VERSION) {                sprintf(ebuf, "kernel bpf filter out of date");                goto bad;        }        (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));        if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {                sprintf(ebuf, "%s: %s", device, pcap_strerror(errno));                goto bad;        }        /* Get the data link layer type. */        if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {                sprintf(ebuf, "BIOCGDLT: %s", pcap_strerror(errno));                goto bad;        }#if _BSDI_VERSION - 0 >= 199510        /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */        switch (v) {        case DLT_SLIP:                v = DLT_SLIP_BSDOS;                break;        case DLT_PPP:                v = DLT_PPP_BSDOS;                break;        }#endif          p->linktype = v;        /* set timeout */        if (to_ms != 0) {                struct timeval to;                to.tv_sec = to_ms / 1000;                to.tv_usec = (to_ms * 1000) % 1000000;                if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {                        sprintf(ebuf, "BIOCSRTIMEOUT: %s",                                pcap_strerror(errno));                        goto bad;                }        }        if (promisc)                /* set promiscuous mode, okay if it fails */                (void)ioctl(p->fd, BIOCPROMISC, NULL);         if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {                sprintf(ebuf, "BIOCGBLEN: %s", pcap_strerror(errno));                goto bad;        }           p->bufsize = v;        p->buffer = (u_char *)malloc(p->bufsize);        if (p->buffer == NULL) {                sprintf(ebuf, "malloc: %s", pcap_strerror(errno));                goto bad;        }               return (p); bad:           ::close(fd);        free(p);        return (NULL);}#endif // MY_OWN_PCAP

⌨️ 快捷键说明

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