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

📄 pcap-linux.c

📁 Ubuntu packages of security software。 相当不错的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
			handle->dlt_count = 2;		}		/* FALLTHROUGH */	case ARPHRD_METRICOM:	case ARPHRD_LOOPBACK:		handle->linktype = DLT_EN10MB;		handle->offset = 2;		break;	case ARPHRD_EETHER:		handle->linktype = DLT_EN3MB;		break;	case ARPHRD_AX25:		handle->linktype = DLT_AX25;		break;	case ARPHRD_PRONET:		handle->linktype = DLT_PRONET;		break;	case ARPHRD_CHAOS:		handle->linktype = DLT_CHAOS;		break;#ifndef ARPHRD_IEEE802_TR#define ARPHRD_IEEE802_TR 800	/* From Linux 2.4 */#endif	case ARPHRD_IEEE802_TR:	case ARPHRD_IEEE802:		handle->linktype = DLT_IEEE802;		handle->offset = 2;		break;	case ARPHRD_ARCNET:		handle->linktype = DLT_ARCNET_LINUX;		break;#ifndef ARPHRD_FDDI	/* From Linux 2.2.13 */#define ARPHRD_FDDI	774#endif	case ARPHRD_FDDI:		handle->linktype = DLT_FDDI;		handle->offset = 3;		break;#ifndef ARPHRD_ATM  /* FIXME: How to #include this? */#define ARPHRD_ATM 19#endif	case ARPHRD_ATM:		/*		 * The Classical IP implementation in ATM for Linux		 * supports both what RFC 1483 calls "LLC Encapsulation",		 * in which each packet has an LLC header, possibly		 * with a SNAP header as well, prepended to it, and		 * what RFC 1483 calls "VC Based Multiplexing", in which		 * different virtual circuits carry different network		 * layer protocols, and no header is prepended to packets.		 *		 * They both have an ARPHRD_ type of ARPHRD_ATM, so		 * you can't use the ARPHRD_ type to find out whether		 * captured packets will have an LLC header, and,		 * while there's a socket ioctl to *set* the encapsulation		 * type, there's no ioctl to *get* the encapsulation type.		 *		 * This means that		 *		 *	programs that dissect Linux Classical IP frames		 *	would have to check for an LLC header and,		 *	depending on whether they see one or not, dissect		 *	the frame as LLC-encapsulated or as raw IP (I		 *	don't know whether there's any traffic other than		 *	IP that would show up on the socket, or whether		 *	there's any support for IPv6 in the Linux		 *	Classical IP code);		 *		 *	filter expressions would have to compile into		 *	code that checks for an LLC header and does		 *	the right thing.		 *		 * Both of those are a nuisance - and, at least on systems		 * that support PF_PACKET sockets, we don't have to put		 * up with those nuisances; instead, we can just capture		 * in cooked mode.  That's what we'll do, if we can.		 * Otherwise, we'll just fail.		 */		if (cooked_ok)			handle->linktype = DLT_LINUX_SLL;		else			handle->linktype = -1;		break;#ifndef ARPHRD_IEEE80211  /* From Linux 2.4.6 */#define ARPHRD_IEEE80211 801#endif	case ARPHRD_IEEE80211:		handle->linktype = DLT_IEEE802_11;		break;#ifndef ARPHRD_IEEE80211_PRISM  /* From Linux 2.4.18 */#define ARPHRD_IEEE80211_PRISM 802#endif	case ARPHRD_IEEE80211_PRISM:		handle->linktype = DLT_PRISM_HEADER;		break;#ifndef ARPHRD_IEEE80211_RADIOTAP /* new */#define ARPHRD_IEEE80211_RADIOTAP 803#endif	case ARPHRD_IEEE80211_RADIOTAP:		handle->linktype = DLT_IEEE802_11_RADIO;		break;	case ARPHRD_PPP:		/*		 * Some PPP code in the kernel supplies no link-layer		 * header whatsoever to PF_PACKET sockets; other PPP		 * code supplies PPP link-layer headers ("syncppp.c");		 * some PPP code might supply random link-layer		 * headers (PPP over ISDN - there's code in Ethereal,		 * for example, to cope with PPP-over-ISDN captures		 * with which the Ethereal developers have had to cope,		 * heuristically trying to determine which of the		 * oddball link-layer headers particular packets have).		 *		 * As such, we just punt, and run all PPP interfaces		 * in cooked mode, if we can; otherwise, we just treat		 * it as DLT_RAW, for now - if somebody needs to capture,		 * on a 2.0[.x] kernel, on PPP devices that supply a		 * link-layer header, they'll have to add code here to		 * map to the appropriate DLT_ type (possibly adding a		 * new DLT_ type, if necessary).		 */		if (cooked_ok)			handle->linktype = DLT_LINUX_SLL;		else {			/*			 * XXX - handle ISDN types here?  We can't fall			 * back on cooked sockets, so we'd have to			 * figure out from the device name what type of			 * link-layer encapsulation it's using, and map			 * that to an appropriate DLT_ value, meaning			 * we'd map "isdnN" devices to DLT_RAW (they			 * supply raw IP packets with no link-layer			 * header) and "isdY" devices to a new DLT_I4L_IP			 * type that has only an Ethernet packet type as			 * a link-layer header.			 *			 * But sometimes we seem to get random crap			 * in the link-layer header when capturing on			 * ISDN devices....			 */			handle->linktype = DLT_RAW;		}		break;#ifndef ARPHRD_CISCO#define ARPHRD_CISCO 513 /* previously ARPHRD_HDLC */#endif	case ARPHRD_CISCO:		handle->linktype = DLT_C_HDLC;		break;	/* Not sure if this is correct for all tunnels, but it	 * works for CIPE */	case ARPHRD_TUNNEL:#ifndef ARPHRD_SIT#define ARPHRD_SIT 776	/* From Linux 2.2.13 */#endif	case ARPHRD_SIT:	case ARPHRD_CSLIP:	case ARPHRD_SLIP6:	case ARPHRD_CSLIP6:	case ARPHRD_ADAPT:	case ARPHRD_SLIP:#ifndef ARPHRD_RAWHDLC#define ARPHRD_RAWHDLC 518#endif	case ARPHRD_RAWHDLC:#ifndef ARPHRD_DLCI#define ARPHRD_DLCI 15#endif	case ARPHRD_DLCI:		/*		 * XXX - should some of those be mapped to DLT_LINUX_SLL		 * instead?  Should we just map all of them to DLT_LINUX_SLL?		 */		handle->linktype = DLT_RAW;		break;#ifndef ARPHRD_FRAD#define ARPHRD_FRAD 770#endif	case ARPHRD_FRAD:		handle->linktype = DLT_FRELAY;		break;	case ARPHRD_LOCALTLK:		handle->linktype = DLT_LTALK;		break;#ifndef ARPHRD_FCPP#define ARPHRD_FCPP	784#endif	case ARPHRD_FCPP:#ifndef ARPHRD_FCAL#define ARPHRD_FCAL	785#endif	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;	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_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_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,			 "ioctl: %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. *//*

⌨️ 快捷键说明

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