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

📄 pcap-linux.c

📁 Ubuntu packages of security software。 相当不错的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 */	stats->ps_recv = handle->md.packets_read;	stats->ps_drop = 0;	return 0;}/* * Description string for the "any" device. */static const char any_descr[] = "Pseudo-device that captures on all interfaces";intpcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf){	if (pcap_add_if(alldevsp, "any", 0, any_descr, errbuf) < 0)		return (-1);#ifdef HAVE_DAG_API	if (dag_platform_finddevs(alldevsp, errbuf) < 0)		return (-1);#endif /* HAVE_DAG_API */#ifdef HAVE_SEPTEL_API	if (septel_platform_finddevs(alldevsp, errbuf) < 0)		return (-1);#endif /* HAVE_SEPTEL_API */	return (0);}/* *  Attach the given BPF code to the packet capture device. */static intpcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter){#ifdef SO_ATTACH_FILTER	struct sock_fprog	fcode;	int			can_filter_in_kernel;	int			err = 0;#endif	if (!handle)		return -1;	if (!filter) {	        strncpy(handle->errbuf, "setfilter: No filter specified",			sizeof(handle->errbuf));		return -1;	}	/* Make our private copy of the filter */	if (install_bpf_program(handle, filter) < 0)		/* install_bpf_program() filled in errbuf */		return -1;	/*	 * Run user level packet filter by default. Will be overriden if	 * installing a kernel filter succeeds.	 */	handle->md.use_bpf = 0;	/* Install kernel level filter if possible */#ifdef SO_ATTACH_FILTER#ifdef USHRT_MAX	if (handle->fcode.bf_len > USHRT_MAX) {		/*		 * fcode.len is an unsigned short for current kernel.		 * I have yet to see BPF-Code with that much		 * instructions but still it is possible. So for the		 * sake of correctness I added this check.		 */		fprintf(stderr, "Warning: Filter too complex for kernel\n");		fcode.len = 0;		fcode.filter = NULL;		can_filter_in_kernel = 0;	} else#endif /* USHRT_MAX */	{		/*		 * Oh joy, the Linux kernel uses struct sock_fprog instead		 * of struct bpf_program and of course the length field is		 * of different size. Pointed out by Sebastian		 *		 * Oh, and we also need to fix it up so that all "ret"		 * instructions with non-zero operands have 65535 as the		 * operand, and so that, if we're in cooked mode, all		 * memory-reference instructions use special magic offsets		 * in references to the link-layer header and assume that		 * the link-layer payload begins at 0; "fix_program()"		 * will do that.		 */		switch (fix_program(handle, &fcode)) {		case -1:		default:			/*			 * Fatal error; just quit.			 * (The "default" case shouldn't happen; we			 * return -1 for that reason.)			 */			return -1;		case 0:			/*			 * The program performed checks that we can't make			 * work in the kernel.			 */			can_filter_in_kernel = 0;			break;		case 1:			/*			 * We have a filter that'll work in the kernel.			 */			can_filter_in_kernel = 1;			break;		}	}	if (can_filter_in_kernel) {		if ((err = set_kernel_filter(handle, &fcode)) == 0)		{			/* Installation succeded - using kernel filter. */			handle->md.use_bpf = 1;		}		else if (err == -1)	/* Non-fatal error */		{			/*			 * Print a warning if we weren't able to install			 * the filter for a reason other than "this kernel			 * isn't configured to support socket filters.			 */			if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) {				fprintf(stderr,				    "Warning: Kernel filter failed: %s\n",					pcap_strerror(errno));			}		}	}	/*	 * If we're not using the kernel filter, get rid of any kernel	 * filter that might've been there before, e.g. because the	 * previous filter could work in the kernel, or because some other	 * code attached a filter to the socket by some means other than	 * calling "pcap_setfilter()".  Otherwise, the kernel filter may	 * filter out packets that would pass the new userland filter.	 */	if (!handle->md.use_bpf)		reset_kernel_filter(handle);	/*	 * Free up the copy of the filter that was made by "fix_program()".	 */	if (fcode.filter != NULL)		free(fcode.filter);	if (err == -2)		/* Fatal error */		return -1;#endif /* SO_ATTACH_FILTER */	return 0;}/* * Set direction flag: Which packets do we accept on a forwarding * single device? IN, OUT or both? */static intpcap_setdirection_linux(pcap_t *handle, pcap_direction_t d){#ifdef HAVE_PF_PACKET_SOCKETS	if (!handle->md.sock_packet) {		handle->direction = d;		return 0;	}#endif	/*	 * We're not using PF_PACKET sockets, so we can't determine	 * the direction of the packet.	 */	snprintf(handle->errbuf, sizeof(handle->errbuf),	    "Setting direction is not supported on SOCK_PACKET sockets");	return -1;}/* *  Linux uses the ARP hardware type to identify the type of an *  interface. pcap uses the DLT_xxx constants for this. This *  function takes a pointer to a "pcap_t", and an ARPHRD_xxx *  constant, as arguments, and sets "handle->linktype" to the *  appropriate DLT_XXX constant and sets "handle->offset" to *  the appropriate value (to make "handle->offset" plus link-layer *  header length be a multiple of 4, so that the link-layer payload *  will be aligned on a 4-byte boundary when capturing packets). *  (If the offset isn't set here, it'll be 0; add code as appropriate *  for cases where it shouldn't be 0.) * *  If "cooked_ok" is non-zero, we can use DLT_LINUX_SLL and capture *  in cooked mode; otherwise, we can't use cooked mode, so we have *  to pick some type that works in raw mode, or fail. * *  Sets the link type to -1 if unable to map the type. */static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok){	switch (arptype) {	case ARPHRD_ETHER:		/*		 * This is (presumably) a real Ethernet capture; give it a		 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so		 * that an application can let you choose it, in case you're		 * capturing DOCSIS traffic that a Cisco Cable Modem		 * Termination System is putting out onto an Ethernet (it		 * doesn't put an Ethernet header onto the wire, it puts raw		 * DOCSIS frames out on the wire inside the low-level		 * Ethernet framing).		 *		 * XXX - are there any sorts of "fake Ethernet" that have		 * ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as		 * a Cisco CMTS won't put traffic onto it or get traffic		 * bridged onto it?  ISDN is handled in "live_open_new()",		 * as we fall back on cooked mode there; are there any		 * others?		 */		handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);		/*		 * If that fails, just leave the list empty.		 */		if (handle->dlt_list != NULL) {			handle->dlt_list[0] = DLT_EN10MB;			handle->dlt_list[1] = DLT_DOCSIS;			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

⌨️ 快捷键说明

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