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

📄 pcap-dlpi.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef HAVE_SYS_BUFMOD_H	bpf_u_int32 ss, chunksize;#ifdef HAVE_SOLARIS	register char *release;	bpf_u_int32 osmajor, osminor, osmicro;#endif#endif	bpf_u_int32 buf[MAXDLBUF];	char dname[100];#ifndef HAVE_DEV_DLPI	char dname2[100];#endif	p = (pcap_t *)malloc(sizeof(*p));	if (p == NULL) {		strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);		return (NULL);	}	memset(p, 0, sizeof(*p));	p->fd = -1;	/* indicate that it hasn't been opened yet */	p->send_fd = -1;#ifdef HAVE_DEV_DLPI	/*	** Remove any "/dev/" on the front of the device.	*/	cp = strrchr(device, '/');	if (cp == NULL)		strlcpy(dname, device, sizeof(dname));	else		strlcpy(dname, cp + 1, sizeof(dname));	/*	 * Split the device name into a device type name and a unit number;	 * chop off the unit number, so "dname" is just a device type name.	 */	cp = split_dname(dname, &ppa, ebuf);	if (cp == NULL)		goto bad;	*cp = '\0';	/*	 * Use "/dev/dlpi" as the device.	 *	 * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that	 * the "dl_mjr_num" field is for the "major number of interface	 * driver"; that's the major of "/dev/dlpi" on the system on	 * which I tried this, but there may be DLPI devices that	 * use a different driver, in which case we may need to	 * search "/dev" for the appropriate device with that major	 * device number, rather than hardwiring "/dev/dlpi".	 */	cp = "/dev/dlpi";	if ((p->fd = open(cp, O_RDWR)) < 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE,		    "%s: %s", cp, pcap_strerror(errno));		goto bad;	}#ifdef DL_HP_RAWDLS	/*	 * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and	 * receiving packets on the same descriptor - you need separate	 * descriptors for sending and receiving, bound to different SAPs.	 *	 * If the open fails, we just leave -1 in "p->send_fd" and reject	 * attempts to send packets, just as if, in pcap-bpf.c, we fail	 * to open the BPF device for reading and writing, we just try	 * to open it for reading only and, if that succeeds, just let	 * the send attempts fail.	 */	p->send_fd = open(cp, O_RDWR);#endif	/*	 * Get a table of all PPAs for that device, and search that	 * table for the specified device type name and unit number.	 */	ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf);	if (ppa < 0)		goto bad;#else	/*	 * If the device name begins with "/", assume it begins with	 * the pathname of the directory containing the device to open;	 * otherwise, concatenate the device directory name and the	 * device name.	 */	if (*device == '/')		strlcpy(dname, device, sizeof(dname));	else		snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,		    device);	/*	 * Get the unit number, and a pointer to the end of the device	 * type name.	 */	cp = split_dname(dname, &ppa, ebuf);	if (cp == NULL)		goto bad;	/*	 * Make a copy of the device pathname, and then remove the unit	 * number from the device pathname.	 */	strlcpy(dname2, dname, sizeof(dname));	*cp = '\0';	/* Try device without unit number */	if ((p->fd = open(dname, O_RDWR)) < 0) {		if (errno != ENOENT) {			snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,			    pcap_strerror(errno));			goto bad;		}		/* Try again with unit number */		if ((p->fd = open(dname2, O_RDWR)) < 0) {			if (errno == ENOENT) {				/*				 * We just report "No DLPI device found"				 * with the device name, so people don't				 * get confused and think, for example,				 * that if they can't capture on "lo0"				 * on Solaris the fix is to change libpcap				 * (or the application that uses it) to				 * look for something other than "/dev/lo0",				 * as the fix is to look for an operating				 * system other than Solaris - you just				 * *can't* capture on a loopback interface				 * on Solaris, the lack of a DLPI device				 * for the loopback interface is just a				 * symptom of that inability.				 */				snprintf(ebuf, PCAP_ERRBUF_SIZE,				    "%s: No DLPI device found", device);			} else {				snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s",				    dname2, pcap_strerror(errno));			}			goto bad;		}		/* XXX Assume unit zero */		ppa = 0;	}#endif	p->snapshot = snaplen;	/*	** Attach if "style 2" provider	*/	if (dlinforeq(p->fd, ebuf) < 0 ||	    dlinfoack(p->fd, (char *)buf, ebuf) < 0)		goto bad;	infop = &((union DL_primitives *)buf)->info_ack;#ifdef HAVE_SOLARIS	if (infop->dl_mac_type == DL_IPATM)		isatm = 1;#endif	if (infop->dl_provider_style == DL_STYLE2) {		if (dl_doattach(p->fd, ppa, ebuf) < 0)			goto bad;#ifdef DL_HP_RAWDLS		if (p->send_fd >= 0) {			if (dl_doattach(p->send_fd, ppa, ebuf) < 0)				goto bad;		}#endif	}	/*	** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally	** skip if using SINIX)	*/#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20_OR_LATER) && !defined(sinix)#ifdef _AIX	/*	** AIX.	** According to IBM's AIX Support Line, the dl_sap value	** should not be less than 0x600 (1536) for standard Ethernet.	** However, we seem to get DL_BADADDR - "DLSAP addr in improper	** format or invalid" - errors if we use 1537 on the "tr0"	** device, which, given that its name starts with "tr" and that	** it's IBM, probably means a Token Ring device.  (Perhaps we	** need to use 1537 on "/dev/dlpi/en" because that device is for	** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and	** it rejects invalid Ethernet types.)	**	** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea	** says that works on Token Ring (he says that 0 does *not*	** work; perhaps that's considered an invalid LLC SAP value - I	** assume the SAP value in a DLPI bind is an LLC SAP for network	** types that use 802.2 LLC).	*/	if ((dlbindreq(p->fd, 1537, ebuf) < 0 &&	     dlbindreq(p->fd, 2, ebuf) < 0) ||	     dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0)		goto bad;#elif defined(DL_HP_RAWDLS)	/*	** HP-UX 10.0x and 10.1x.	*/	if (dl_dohpuxbind(p->fd, ebuf) < 0)		goto bad;	if (p->send_fd >= 0) {		/*		** XXX - if this fails, just close send_fd and		** set it to -1, so that you can't send but can		** still receive?		*/		if (dl_dohpuxbind(p->send_fd, ebuf) < 0)			goto bad;	}#else /* neither AIX nor HP-UX */	/*	** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other	** OS using DLPI.	**/	if (dlbindreq(p->fd, 0, ebuf) < 0 ||	    dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0)		goto bad;#endif /* AIX vs. HP-UX vs. other */#endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */#ifdef HAVE_SOLARIS	if (isatm) {		/*		** Have to turn on some special ATM promiscuous mode		** for SunATM.		** Do *NOT* turn regular promiscuous mode on; it doesn't		** help, and may break things.		*/		if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) {			snprintf(ebuf, PCAP_ERRBUF_SIZE, "A_PROMISCON_REQ: %s",			    pcap_strerror(errno));			goto bad;		}	} else#endif	if (promisc) {		/*		** Enable promiscuous (not necessary on send FD)		*/		if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 ||		    dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0)			goto bad;		/*		** Try to enable multicast (you would have thought		** promiscuous would be sufficient). (Skip if using		** HP-UX or SINIX) (Not necessary on send FD)		*/#if !defined(__hpux) && !defined(sinix)		if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 ||		    dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0)			fprintf(stderr,			    "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf);#endif	}	/*	** Try to enable SAP promiscuity (when not in promiscuous mode	** when using HP-UX, when not doing SunATM on Solaris, and never	** under SINIX) (Not necessary on send FD)	*/#ifndef sinix	if (#ifdef __hpux	    !promisc &&#endif#ifdef HAVE_SOLARIS	    !isatm &&#endif	    (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 ||	    dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0)) {		/* Not fatal if promisc since the DL_PROMISC_PHYS worked */		if (promisc)			fprintf(stderr,			    "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf);		else			goto bad;	}#endif /* sinix */	/*	** HP-UX 9, and HP-UX 10.20 or later, must bind after setting	** promiscuous options.	*/#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER)	if (dl_dohpuxbind(p->fd, ebuf) < 0)		goto bad;	/*	** We don't set promiscuous mode on the send FD, but we'll defer	** binding it anyway, just to keep the HP-UX 9/10.20 or later	** code together.	*/	if (p->send_fd >= 0) {		/*		** XXX - if this fails, just close send_fd and		** set it to -1, so that you can't send but can		** still receive?		*/		if (dl_dohpuxbind(p->send_fd, ebuf) < 0)			goto bad;	}#endif	/*	** Determine link type	** XXX - get SAP length and address length as well, for use	** when sending packets.	*/	if (dlinforeq(p->fd, ebuf) < 0 ||	    dlinfoack(p->fd, (char *)buf, ebuf) < 0)		goto bad;	infop = &((union DL_primitives *)buf)->info_ack;	switch (infop->dl_mac_type) {	case DL_CSMACD:	case DL_ETHER:		p->linktype = DLT_EN10MB;		p->offset = 2;		/*		 * 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).		 */		p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);		/*		 * If that fails, just leave the list empty.		 */		if (p->dlt_list != NULL) {			p->dlt_list[0] = DLT_EN10MB;			p->dlt_list[1] = DLT_DOCSIS;			p->dlt_count = 2;		}		break;	case DL_FDDI:		p->linktype = DLT_FDDI;		p->offset = 3;		break;	case DL_TPR:		/*		 * XXX - what about DL_TPB?  Is that Token Bus?		 */			p->linktype = DLT_IEEE802;		p->offset = 2;		break;#ifdef HAVE_SOLARIS	case DL_IPATM:		p->linktype = DLT_SUNATM;		p->offset = 0;	/* works for LANE and LLC encapsulation */		break;#endif	default:		snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu",		    (unsigned long)infop->dl_mac_type);		goto bad;	}#ifdef	DLIOCRAW	/*	** This is a non standard SunOS hack to get the full raw link-layer	** header.	*/	if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s",		    pcap_strerror(errno));		goto bad;	}#endif#ifdef HAVE_SYS_BUFMOD_H	/*	** Another non standard call to get the data nicely buffered	*/	if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_PUSH bufmod: %s",		    pcap_strerror(errno));		goto bad;	}	/*	** Now that the bufmod is pushed lets configure it.	**	** There is a bug in bufmod(7). When dealing with messages of	** less than snaplen size it strips data from the beginning not	** the end.	**	** This bug is supposed to be fixed in 5.3.2. Also, there is a	** patch available. Ask for bugid 1149065.	*/	ss = snaplen;#ifdef HAVE_SOLARIS	release = get_release(&osmajor, &osminor, &osmicro);	if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&	    getenv("BUFMOD_FIXED") == NULL) {		fprintf(stderr,		"WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n",		    release);		ss = 0;	}#endif	if (ss > 0 &&	    strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSSNAP: %s",		    pcap_strerror(errno));		goto bad;	}	/*	** Set up the bufmod timeout	*/	if (to_ms != 0) {		struct timeval to;		to.tv_sec = to_ms / 1000;		to.tv_usec = (to_ms * 1000) % 1000000;		if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {			snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSTIME: %s",			    pcap_strerror(errno));			goto bad;		}	}	/*	** Set the chunk length.	*/	chunksize = CHUNKSIZE;	if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)	    != 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSCHUNKP: %s",		    pcap_strerror(errno));		goto bad;	}#endif	/*	** As the last operation flush the read side.	*/	if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {		snprintf(ebuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",		    pcap_strerror(errno));		goto bad;	}	/* Allocate data buffer */	p->bufsize = PKTBUFSIZE;	p->buffer = (u_char *)malloc(p->bufsize + p->offset);	if (p->buffer == NULL) {		strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);		goto bad;	}	/*	 * "p->fd" is an FD for a STREAMS device, so "select()" and	 * "poll()" should work on it.	 */

⌨️ 快捷键说明

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