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

📄 pcap-linux.c

📁 Ubuntu packages of security software。 相当不错的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	int		arptype;	struct ifreq	ifr;	do {		/* Open the socket */		handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));		if (handle->fd == -1) {			snprintf(ebuf, PCAP_ERRBUF_SIZE,				 "socket: %s", pcap_strerror(errno));			break;		}		/* It worked - we are using the old interface */		handle->md.sock_packet = 1;		/* ...which means we get the link-layer header. */		handle->md.cooked = 0;		/* Bind to the given device */		if (!device) {		        strncpy(ebuf, "pcap_open_live: The \"any\" device isn't supported on 2.0[.x]-kernel systems",				PCAP_ERRBUF_SIZE);			break;		}		if (iface_bind_old(handle->fd, device, ebuf) == -1)			break;		/*		 * Try to get the link-layer type.		 */		arptype = iface_get_arptype(handle->fd, device, ebuf);		if (arptype == -1)			break;		/*		 * Try to find the DLT_ type corresponding to that		 * link-layer type.		 */		map_arphrd_to_dlt(handle, arptype, 0);		if (handle->linktype == -1) {			snprintf(ebuf, PCAP_ERRBUF_SIZE,				 "unknown arptype %d", arptype);			break;		}		/* Go to promisc mode if requested */		if (promisc) {			memset(&ifr, 0, sizeof(ifr));			strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));			if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {				snprintf(ebuf, PCAP_ERRBUF_SIZE,					 "SIOCGIFFLAGS: %s", pcap_strerror(errno));				break;			}			if ((ifr.ifr_flags & IFF_PROMISC) == 0) {				/*				 * Promiscuous mode isn't currently on,				 * so turn it on, and remember that				 * we should turn it off when the				 * pcap_t is closed.				 */				/*				 * If we haven't already done so, arrange				 * to have "pcap_close_all()" called when				 * we exit.				 */				if (!did_atexit) {					if (atexit(pcap_close_all) == -1) {						/*						 * "atexit()" failed; don't						 * put the interface in						 * promiscuous mode, just						 * give up.						 */						strncpy(ebuf, "atexit failed",							PCAP_ERRBUF_SIZE);						break;					}					did_atexit = 1;				}				ifr.ifr_flags |= IFF_PROMISC;				if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {				        snprintf(ebuf, PCAP_ERRBUF_SIZE,						 "SIOCSIFFLAGS: %s",						 pcap_strerror(errno));					break;				}				handle->md.clear_promisc = 1;				/*				 * Add this to the list of pcaps				 * to close when we exit.				 */				handle->md.next = pcaps_to_close;				pcaps_to_close = handle;			}		}		/*		 * Default value for offset to align link-layer payload		 * on a 4-byte boundary.		 */		handle->offset	 = 0;		return 1;	} while (0);	pcap_close_linux(handle);	return 0;}/* *  Bind the socket associated with FD to the given device using the *  interface of the old kernels. */static intiface_bind_old(int fd, const char *device, char *ebuf){	struct sockaddr	saddr;	int		err;	socklen_t	errlen = sizeof(err);	memset(&saddr, 0, sizeof(saddr));	strncpy(saddr.sa_data, device, sizeof(saddr.sa_data));	if (bind(fd, &saddr, sizeof(saddr)) == -1) {		snprintf(ebuf, PCAP_ERRBUF_SIZE,			 "bind: %s", pcap_strerror(errno));		return -1;	}	/* Any pending errors, e.g., network is down? */	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {		snprintf(ebuf, PCAP_ERRBUF_SIZE,			"getsockopt: %s", pcap_strerror(errno));		return -1;	}	if (err > 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE,			"bind: %s", pcap_strerror(err));		return -1;	}	return 0;}/* ===== System calls available on all supported kernels ============== *//* *  Query the kernel for the MTU of the given interface. */static intiface_get_mtu(int fd, const char *device, char *ebuf){	struct ifreq	ifr;	if (!device)		return BIGGER_THAN_ALL_MTUS;	memset(&ifr, 0, sizeof(ifr));	strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));	if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) {		snprintf(ebuf, PCAP_ERRBUF_SIZE,			 "SIOCGIFMTU: %s", pcap_strerror(errno));		return -1;	}	return ifr.ifr_mtu;}/* *  Get the hardware type of the given interface as ARPHRD_xxx constant. */static intiface_get_arptype(int fd, const char *device, char *ebuf){	struct ifreq	ifr;	memset(&ifr, 0, sizeof(ifr));	strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));	if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {		snprintf(ebuf, PCAP_ERRBUF_SIZE,			 "SIOCGIFHWADDR: %s", pcap_strerror(errno));		return -1;	}	return ifr.ifr_hwaddr.sa_family;}#ifdef SO_ATTACH_FILTERstatic intfix_program(pcap_t *handle, struct sock_fprog *fcode){	size_t prog_size;	register int i;	register struct bpf_insn *p;	struct bpf_insn *f;	int len;	/*	 * Make a copy of the filter, and modify that copy if	 * necessary.	 */	prog_size = sizeof(*handle->fcode.bf_insns) * handle->fcode.bf_len;	len = handle->fcode.bf_len;	f = (struct bpf_insn *)malloc(prog_size);	if (f == NULL) {		snprintf(handle->errbuf, sizeof(handle->errbuf),			 "malloc: %s", pcap_strerror(errno));		return -1;	}	memcpy(f, handle->fcode.bf_insns, prog_size);	fcode->len = len;	fcode->filter = (struct sock_filter *) f;	for (i = 0; i < len; ++i) {		p = &f[i];		/*		 * What type of instruction is this?		 */		switch (BPF_CLASS(p->code)) {		case BPF_RET:			/*			 * It's a return instruction; is the snapshot			 * length a constant, rather than the contents			 * of the accumulator?			 */			if (BPF_MODE(p->code) == BPF_K) {				/*				 * Yes - if the value to be returned,				 * i.e. the snapshot length, is anything				 * other than 0, make it 65535, so that				 * the packet is truncated by "recvfrom()",				 * not by the filter.				 *				 * XXX - there's nothing we can easily do				 * if it's getting the value from the				 * accumulator; we'd have to insert				 * code to force non-zero values to be				 * 65535.				 */				if (p->k != 0)					p->k = 65535;			}			break;		case BPF_LD:		case BPF_LDX:			/*			 * It's a load instruction; is it loading			 * from the packet?			 */			switch (BPF_MODE(p->code)) {			case BPF_ABS:			case BPF_IND:			case BPF_MSH:				/*				 * Yes; are we in cooked mode?				 */				if (handle->md.cooked) {					/*					 * Yes, so we need to fix this					 * instruction.					 */					if (fix_offset(p) < 0) {						/*						 * We failed to do so.						 * Return 0, so our caller						 * knows to punt to userland.						 */						return 0;					}				}				break;			}			break;		}	}	return 1;	/* we succeeded */}static intfix_offset(struct bpf_insn *p){	/*	 * What's the offset?	 */	if (p->k >= SLL_HDR_LEN) {		/*		 * It's within the link-layer payload; that starts at an		 * offset of 0, as far as the kernel packet filter is		 * concerned, so subtract the length of the link-layer		 * header.		 */		p->k -= SLL_HDR_LEN;	} else if (p->k == 14) {		/*		 * It's the protocol field; map it to the special magic		 * kernel offset for that field.		 */		p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;	} else {		/*		 * It's within the header, but it's not one of those		 * fields; we can't do that in the kernel, so punt		 * to userland.		 */		return -1;	}	return 0;}static intset_kernel_filter(pcap_t *handle, struct sock_fprog *fcode){	int total_filter_on = 0;	int save_mode;	int ret;	int save_errno;	/*	 * The socket filter code doesn't discard all packets queued	 * up on the socket when the filter is changed; this means	 * that packets that don't match the new filter may show up	 * after the new filter is put onto the socket, if those	 * packets haven't yet been read.	 *	 * This means, for example, that if you do a tcpdump capture	 * with a filter, the first few packets in the capture might	 * be packets that wouldn't have passed the filter.	 *	 * We therefore discard all packets queued up on the socket	 * when setting a kernel filter.  (This isn't an issue for	 * userland filters, as the userland filtering is done after	 * packets are queued up.)	 *	 * To flush those packets, we put the socket in read-only mode,	 * and read packets from the socket until there are no more to	 * read.	 *	 * In order to keep that from being an infinite loop - i.e.,	 * to keep more packets from arriving while we're draining	 * the queue - we put the "total filter", which is a filter	 * that rejects all packets, onto the socket before draining	 * the queue.	 *	 * This code deliberately ignores any errors, so that you may	 * get bogus packets if an error occurs, rather than having	 * the filtering done in userland even if it could have been	 * done in the kernel.	 */	if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,		       &total_fcode, sizeof(total_fcode)) == 0) {		char drain[1];		/*		 * Note that we've put the total filter onto the socket.		 */		total_filter_on = 1;		/*		 * Save the socket's current mode, and put it in		 * non-blocking mode; we drain it by reading packets		 * until we get an error (which is normally a		 * "nothing more to be read" error).		 */		save_mode = fcntl(handle->fd, F_GETFL, 0);		if (save_mode != -1 &&		    fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) >= 0) {			while (recv(handle->fd, &drain, sizeof drain,			       MSG_TRUNC) >= 0)				;			save_errno = errno;			fcntl(handle->fd, F_SETFL, save_mode);			if (save_errno != EAGAIN) {				/* Fatal error */				reset_kernel_filter(handle);				snprintf(handle->errbuf, sizeof(handle->errbuf),				 "recv: %s", pcap_strerror(save_errno));				return -2;			}		}	}	/*	 * Now attach the new filter.	 */	ret = setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,			 fcode, sizeof(*fcode));	if (ret == -1 && total_filter_on) {		/*		 * Well, we couldn't set that filter on the socket,		 * but we could set the total filter on the socket.		 *		 * This could, for example, mean that the filter was		 * too big to put into the kernel, so we'll have to		 * filter in userland; in any case, we'll be doing		 * filtering in userland, so we need to remove the		 * total filter so we see packets.		 */		save_errno = errno;		/*		 * XXX - if this fails, we're really screwed;		 * we have the total filter on the socket,		 * and it won't come off.  What do we do then?		 */		reset_kernel_filter(handle);		errno = save_errno;	}	return ret;}static intreset_kernel_filter(pcap_t *handle){	/*	 * setsockopt() barfs unless it get a dummy parameter.	 * valgrind whines unless the value is initialized,	 * as it has no idea that setsockopt() ignores its	 * parameter.	 */	int dummy = 0;	return setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER,				   &dummy, sizeof(dummy));}#endif

⌨️ 快捷键说明

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