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

📄 pcap-linux.c

📁 Ubuntu packages of security software。 相当不错的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	case ARPHRD_FCAL:#ifndef ARPHRD_FCPL#define ARPHRD_FCPL	786#endif	case ARPHRD_FCPL:#ifndef ARPHRD_FCFABRIC#define ARPHRD_FCFABRIC	787#endif	case ARPHRD_FCFABRIC:		/*		 * We assume that those all mean RFC 2625 IP-over-		 * Fibre Channel, with the RFC 2625 header at		 * the beginning of the packet.		 */		handle->linktype = DLT_IP_OVER_FC;		break;#ifndef ARPHRD_IRDA#define ARPHRD_IRDA	783#endif	case ARPHRD_IRDA:		/* Don't expect IP packet out of this interfaces... */		handle->linktype = DLT_LINUX_IRDA;		/* We need to save packet direction for IrDA decoding,		 * so let's use "Linux-cooked" mode. Jean II */		//handle->md.cooked = 1;		break;	/* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation	 * is needed, please report it to <daniele@orlandi.com> */#ifndef ARPHRD_LAPD#define ARPHRD_LAPD	8445#endif	case ARPHRD_LAPD:		/* Don't expect IP packet out of this interfaces... */		handle->linktype = DLT_LINUX_LAPD;		break;	default:		handle->linktype = -1;		break;	}}/* ===== Functions to interface to the newer kernels ================== *//* *  Try to open a packet socket using the new kernel interface. *  Returns 0 on failure. *  FIXME: 0 uses to mean success (Sebastian) */static intlive_open_new(pcap_t *handle, const char *device, int promisc,	      int to_ms, char *ebuf){#ifdef HAVE_PF_PACKET_SOCKETS	int			sock_fd = -1, arptype;	int			err;	int			fatal_err = 0;	struct packet_mreq	mr;	/* One shot loop used for error handling - bail out with break */	do {		/*		 * Open a socket with protocol family packet. If a device is		 * given we try to open it in raw mode otherwise we use		 * the cooked interface.		 */		sock_fd = device ?			socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))		      : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));		if (sock_fd == -1) {			snprintf(ebuf, PCAP_ERRBUF_SIZE, "socket: %s",				 pcap_strerror(errno) );			break;		}		/* It seems the kernel supports the new interface. */		handle->md.sock_packet = 0;		/*		 * Get the interface index of the loopback device.		 * If the attempt fails, don't fail, just set the		 * "md.lo_ifindex" to -1.		 *		 * XXX - can there be more than one device that loops		 * packets back, i.e. devices other than "lo"?  If so,		 * we'd need to find them all, and have an array of		 * indices for them, and check all of them in		 * "pcap_read_packet()".		 */		handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", ebuf);		/*		 * Default value for offset to align link-layer payload		 * on a 4-byte boundary.		 */		handle->offset	 = 0;		/*		 * What kind of frames do we have to deal with? Fall back		 * to cooked mode if we have an unknown interface type.		 */		if (device) {			/* Assume for now we don't need cooked mode. */			handle->md.cooked = 0;			arptype	= iface_get_arptype(sock_fd, device, ebuf);			if (arptype == -1) {				fatal_err = 1;				break;			}			map_arphrd_to_dlt(handle, arptype, 1);			if (handle->linktype == -1 ||			    handle->linktype == DLT_LINUX_SLL ||			    handle->linktype == DLT_LINUX_IRDA ||			    handle->linktype == DLT_LINUX_LAPD ||			    (handle->linktype == DLT_EN10MB &&			     (strncmp("isdn", device, 4) == 0 ||			      strncmp("isdY", device, 4) == 0))) {				/*				 * Unknown interface type (-1), or a				 * device we explicitly chose to run				 * in cooked mode (e.g., PPP devices),				 * or an ISDN device (whose link-layer				 * type we can only determine by using				 * APIs that may be different on different				 * kernels) - reopen in cooked mode.				 */				if (close(sock_fd) == -1) {					snprintf(ebuf, PCAP_ERRBUF_SIZE,						 "close: %s", pcap_strerror(errno));					break;				}				sock_fd = socket(PF_PACKET, SOCK_DGRAM,						 htons(ETH_P_ALL));				if (sock_fd == -1) {					snprintf(ebuf, PCAP_ERRBUF_SIZE,						 "socket: %s", pcap_strerror(errno));					break;				}				handle->md.cooked = 1;				/*				 * Get rid of any link-layer type list				 * we allocated - this only supports cooked				 * capture.				 */				if (handle->dlt_list != NULL) {					free(handle->dlt_list);					handle->dlt_list = NULL;					handle->dlt_count = 0;				}				if (handle->linktype == -1) {					/*					 * Warn that we're falling back on					 * cooked mode; we may want to					 * update "map_arphrd_to_dlt()"					 * to handle the new type.					 */					snprintf(ebuf, PCAP_ERRBUF_SIZE,						"arptype %d not "						"supported by libpcap - "						"falling back to cooked "						"socket",						arptype);				}				/* IrDA capture is not a real "cooked" capture,				 * it's IrLAP frames, not IP packets. */				if (handle->linktype != DLT_LINUX_IRDA &&			    		handle->linktype != DLT_LINUX_LAPD)					handle->linktype = DLT_LINUX_SLL;			}			handle->md.ifindex = iface_get_id(sock_fd, device, ebuf);			if (handle->md.ifindex == -1)				break;			if ((err = iface_bind(sock_fd, handle->md.ifindex,			    ebuf)) < 0) {				if (err == -2)					fatal_err = 1;				break;			}		} else {			/*			 * This is cooked mode.			 */			handle->md.cooked = 1;			handle->linktype = DLT_LINUX_SLL;			/*			 * We're not bound to a device.			 * XXX - true?  Or true only if we're using			 * the "any" device?			 * For now, we're using this as an indication			 * that we can't transmit; stop doing that only			 * if we figure out how to transmit in cooked			 * mode.			 */			handle->md.ifindex = -1;		}		/*		 * Select promiscuous mode on if "promisc" is set.		 *		 * Do not turn allmulti mode on if we don't select		 * promiscuous mode - on some devices (e.g., Orinoco		 * wireless interfaces), allmulti mode isn't supported		 * and the driver implements it by turning promiscuous		 * mode on, and that screws up the operation of the		 * card as a normal networking interface, and on no		 * other platform I know of does starting a non-		 * promiscuous capture affect which multicast packets		 * are received by the interface.		 */		/*		 * Hmm, how can we set promiscuous mode on all interfaces?		 * I am not sure if that is possible at all.		 */		if (device && promisc) {			memset(&mr, 0, sizeof(mr));			mr.mr_ifindex = handle->md.ifindex;			mr.mr_type    = PACKET_MR_PROMISC;			if (setsockopt(sock_fd, SOL_PACKET,				PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1)			{				snprintf(ebuf, PCAP_ERRBUF_SIZE,					"setsockopt: %s", pcap_strerror(errno));				break;			}		}		/* Save the socket FD in the pcap structure */		handle->fd 	 = sock_fd;		return 1;	} while(0);	if (sock_fd != -1)		close(sock_fd);	if (fatal_err) {		/*		 * Get rid of any link-layer type list we allocated.		 */		if (handle->dlt_list != NULL)			free(handle->dlt_list);		return -2;	} else		return 0;#else	strncpy(ebuf,		"New packet capturing interface not supported by build "		"environment", PCAP_ERRBUF_SIZE);	return 0;#endif}#ifdef HAVE_PF_PACKET_SOCKETS/* *  Return the index of the given device name. Fill ebuf and return *  -1 on failure. */static intiface_get_id(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, SIOCGIFINDEX, &ifr) == -1) {		snprintf(ebuf, PCAP_ERRBUF_SIZE,			 "SIOCGIFINDEX: %s", pcap_strerror(errno));		return -1;	}	return ifr.ifr_ifindex;}/* *  Bind the socket associated with FD to the given device. */static intiface_bind(int fd, int ifindex, char *ebuf){	struct sockaddr_ll	sll;	int			err;	socklen_t		errlen = sizeof(err);	memset(&sll, 0, sizeof(sll));	sll.sll_family		= AF_PACKET;	sll.sll_ifindex		= ifindex;	sll.sll_protocol	= htons(ETH_P_ALL);	if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -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 -2;	}	if (err > 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE,			"bind: %s", pcap_strerror(err));		return -2;	}	return 0;}#endif/* ===== Functions to interface to the older kernels ================== *//* * With older kernels promiscuous mode is kind of interesting because we * have to reset the interface before exiting. The problem can't really * be solved without some daemon taking care of managing usage counts. * If we put the interface into promiscuous mode, we set a flag indicating * that we must take it out of that mode when the interface is closed, * and, when closing the interface, if that flag is set we take it out * of promiscuous mode. *//* * List of pcaps for which we turned promiscuous mode on by hand. * If there are any such pcaps, we arrange to call "pcap_close_all()" * when we exit, and have it close all of them to turn promiscuous mode * off. */static struct pcap *pcaps_to_close;/* * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to * be called on exit. */static int did_atexit;static void	pcap_close_all(void){	struct pcap *handle;	while ((handle = pcaps_to_close) != NULL)		pcap_close(handle);}static void	pcap_close_linux( pcap_t *handle ){	struct pcap	*p, *prevp;	struct ifreq	ifr;	if (handle->md.clear_promisc) {		/*		 * We put the interface into promiscuous mode; take		 * it out of promiscuous mode.		 *		 * XXX - if somebody else wants it in promiscuous mode,		 * this code cannot know that, so it'll take it out		 * of promiscuous mode.  That's not fixable in 2.0[.x]		 * kernels.		 */		memset(&ifr, 0, sizeof(ifr));		strncpy(ifr.ifr_name, handle->md.device, sizeof(ifr.ifr_name));		if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {			fprintf(stderr,			    "Can't restore interface flags (SIOCGIFFLAGS failed: %s).\n"			    "Please adjust manually.\n"			    "Hint: This can't happen with Linux >= 2.2.0.\n",			    strerror(errno));		} else {			if (ifr.ifr_flags & IFF_PROMISC) {				/*				 * Promiscuous mode is currently on; turn it				 * off.				 */				ifr.ifr_flags &= ~IFF_PROMISC;				if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {					fprintf(stderr,					    "Can't restore interface flags (SIOCSIFFLAGS failed: %s).\n"					    "Please adjust manually.\n"					    "Hint: This can't happen with Linux >= 2.2.0.\n",					    strerror(errno));				}			}		}		/*		 * Take this pcap out of the list of pcaps for which we		 * have to take the interface out of promiscuous mode.		 */		for (p = pcaps_to_close, prevp = NULL; p != NULL;		    prevp = p, p = p->md.next) {			if (p == handle) {				/*				 * Found it.  Remove it from the list.				 */				if (prevp == NULL) {					/*					 * It was at the head of the list.					 */					pcaps_to_close = p->md.next;				} else {					/*					 * It was in the middle of the list.					 */					prevp->md.next = p->md.next;				}				break;			}		}	}	if (handle->md.device != NULL)		free(handle->md.device);	handle->md.device = NULL;	pcap_close_common(handle);}/* *  Try to open a packet socket using the old kernel interface. *  Returns 0 on failure. *  FIXME: 0 uses to mean success (Sebastian) */static intlive_open_old(pcap_t *handle, const char *device, int promisc,	      int to_ms, char *ebuf){

⌨️ 快捷键说明

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