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

📄 pcap-dlpi.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 1993, 1994, 1995, 1996, 1997 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), * University College London, and subsequently modified by * Guy Harris (guy@alum.mit.edu), Mark Pizzolato * <List-tcpdump-workers@subscriptions.pizzolato.net>, * and Mark C. Brown (mbrown@hp.com). *//* * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX. * * Notes: * *    - The DLIOCRAW ioctl() is specific to SunOS. * *    - There is a bug in bufmod(7) such that setting the snapshot *      length results in data being left of the front of the packet. * *    - It might be desirable to use pfmod(7) to filter packets in the *      kernel when possible. * *    - An older version of the HP-UX DLPI Programmer's Guide, which *      I think was advertised as the 10.20 version, used to be available *      at * *            http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html * *      but is no longer available; it can still be found at * *            http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90093.pdf * *      in PDF form. * *    - The HP-UX 10.x, 11.0, and 11i v1.6 version of the HP-UX DLPI *      Programmer's Guide, which I think was once advertised as the *      11.00 version is available at * *            http://docs.hp.com/en/B2355-90139/index.html * *    - The HP-UX 11i v2 version of the HP-UX DLPI Programmer's Guide *      is available at * *            http://docs.hp.com/en/B2355-90871/index.html * *    - All of the HP documents describe raw-mode services, which are *      what we use if DL_HP_RAWDLS is defined.  XXX - we use __hpux *      in some places to test for HP-UX, but use DL_HP_RAWDLS in *      other places; do we support any versions of HP-UX without *      DL_HP_RAWDLS? */#ifndef lintstatic const char rcsid[] _U_ =    "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.108.2.7 2006/04/04 05:33:02 guy Exp $ (LBL)";#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <sys/types.h>#include <sys/time.h>#ifdef HAVE_SYS_BUFMOD_H#include <sys/bufmod.h>#endif#include <sys/dlpi.h>#ifdef HAVE_SYS_DLPI_EXT_H#include <sys/dlpi_ext.h>#endif#ifdef HAVE_HPUX9#include <sys/socket.h>#endif#ifdef DL_HP_PPA_REQ#include <sys/stat.h>#endif#include <sys/stream.h>#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)#include <sys/systeminfo.h>#endif#ifdef HAVE_HPUX9#include <net/if.h>#endif#include <ctype.h>#ifdef HAVE_HPUX9#include <nlist.h>#endif#include <errno.h>#include <fcntl.h>#include <memory.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stropts.h>#include <unistd.h>#ifdef HAVE_LIMITS_H#include <limits.h>#else#define INT_MAX		2147483647#endif#include "pcap-int.h"#ifdef HAVE_OS_PROTO_H#include "os-proto.h"#endif#ifndef PCAP_DEV_PREFIX#ifdef _AIX#define PCAP_DEV_PREFIX "/dev/dlpi"#else#define PCAP_DEV_PREFIX "/dev"#endif#endif#define	MAXDLBUF	8192#ifdef HAVE_SYS_BUFMOD_H/* * Size of a bufmod chunk to pass upstream; that appears to be the biggest * value to which you can set it, and setting it to that value (which * is bigger than what appears to be the Solaris default of 8192) * reduces the number of packet drops. */#define CHUNKSIZE	65536/* * Size of the buffer to allocate for packet data we read; it must be * large enough to hold a chunk. */#define PKTBUFSIZE	CHUNKSIZE#else /* HAVE_SYS_BUFMOD_H *//* * Size of the buffer to allocate for packet data we read; this is * what the value used to be - there's no particular reason why it * should be tied to MAXDLBUF, but we'll leave it as this for now. */#define PKTBUFSIZE	(MAXDLBUF * sizeof(bpf_u_int32))#endif/* Forwards */static char *split_dname(char *, int *, char *);static int dl_doattach(int, int, char *);#ifdef DL_HP_RAWDLSstatic int dl_dohpuxbind(int, char *);#endifstatic int dlattachreq(int, bpf_u_int32, char *);static int dlbindreq(int, bpf_u_int32, char *);static int dlbindack(int, char *, char *, int *);static int dlpromisconreq(int, bpf_u_int32, char *);static int dlokack(int, const char *, char *, char *);static int dlinforeq(int, char *);static int dlinfoack(int, char *, char *);#ifdef DL_HP_RAWDLSstatic int dlrawdatareq(int, const u_char *, int);#endifstatic int recv_ack(int, int, const char *, char *, char *, int *);static char *dlstrerror(bpf_u_int32);static char *dlprim(bpf_u_int32);#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *);#endifstatic int send_request(int, char *, int, char *, char *);#ifdef HAVE_SYS_BUFMOD_Hstatic int strioctl(int, int, int, char *);#endif#ifdef HAVE_HPUX9static int dlpi_kread(int, off_t, void *, u_int, char *);#endif#ifdef HAVE_DEV_DLPIstatic int get_dlpi_ppa(int, const char *, int, char *);#endifstatic intpcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps){	/*	 * "ps_recv" counts packets handed to the filter, not packets	 * that passed the filter.  As filtering is done in userland,	 * this would not include packets dropped because we ran out	 * of buffer space; in order to make this more like other	 * platforms (Linux 2.4 and later, BSDs with BPF), where the	 * "packets received" count includes packets received but dropped	 * due to running out of buffer space, and to keep from confusing	 * applications that, for example, compute packet drop percentages,	 * we also make it count packets dropped by "bufmod" (otherwise we	 * might run the risk of the packet drop count being bigger than	 * the received-packet count).	 *	 * "ps_drop" counts packets dropped by "bufmod" because of	 * flow control requirements or resource exhaustion; it doesn't	 * count packets dropped by the interface driver, or packets	 * dropped upstream.  As filtering is done in userland, it counts	 * packets regardless of whether they would've passed the filter.	 *	 * These statistics don't include packets not yet read from	 * the kernel by libpcap, but they may include packets not	 * yet read from libpcap by the application.	 */	*ps = p->md.stat;	/*	 * Add in the drop count, as per the above comment.	 */	ps->ps_recv += ps->ps_drop;	return (0);}/* XXX Needed by HP-UX (at least) */static bpf_u_int32 ctlbuf[MAXDLBUF];static struct strbuf ctl = {	MAXDLBUF,	0,	(char *)ctlbuf};static intpcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user){	register int cc, n, caplen, origlen;	register u_char *bp, *ep, *pk;	register struct bpf_insn *fcode;#ifdef HAVE_SYS_BUFMOD_H	register struct sb_hdr *sbp;#ifdef LBL_ALIGN	struct sb_hdr sbhdr;#endif#endif	int flags;	struct strbuf data;	struct pcap_pkthdr pkthdr;	flags = 0;	cc = p->cc;	if (cc == 0) {		data.buf = (char *)p->buffer + p->offset;		data.maxlen = p->bufsize;		data.len = 0;		do {			/*			 * Has "pcap_breakloop()" been called?			 */			if (p->break_loop) {				/*				 * Yes - clear the flag that indicates				 * that it has, and return -2 to				 * indicate that we were told to				 * break out of the loop.				 */				p->break_loop = 0;				return (-2);			}			/*			 * XXX - check for the DLPI primitive, which			 * would be DL_HP_RAWDATA_IND on HP-UX			 * if we're in raw mode?			 */			if (getmsg(p->fd, &ctl, &data, &flags) < 0) {				/* Don't choke when we get ptraced */				switch (errno) {				case EINTR:					cc = 0;					continue;				case EAGAIN:					return (0);				}				strlcpy(p->errbuf, pcap_strerror(errno),				    sizeof(p->errbuf));				return (-1);			}			cc = data.len;		} while (cc == 0);		bp = p->buffer + p->offset;	} else		bp = p->bp;	/* Loop through packets */	fcode = p->fcode.bf_insns;	ep = bp + cc;	n = 0;#ifdef HAVE_SYS_BUFMOD_H	while (bp < ep) {		/*		 * Has "pcap_breakloop()" been called?		 * If so, return immediately - if we haven't read any		 * packets, clear the flag and return -2 to indicate		 * that we were told to break out of the loop, otherwise		 * leave the flag set, so that the *next* call will break		 * out of the loop without having read any packets, and		 * return the number of packets we've processed so far.		 */		if (p->break_loop) {			if (n == 0) {				p->break_loop = 0;				return (-2);			} else {				p->bp = bp;				p->cc = ep - bp;				return (n);			}		}#ifdef LBL_ALIGN		if ((long)bp & 3) {			sbp = &sbhdr;			memcpy(sbp, bp, sizeof(*sbp));		} else#endif			sbp = (struct sb_hdr *)bp;		p->md.stat.ps_drop = sbp->sbh_drops;		pk = bp + sizeof(*sbp);		bp += sbp->sbh_totlen;		origlen = sbp->sbh_origlen;		caplen = sbp->sbh_msglen;#else		origlen = cc;		caplen = min(p->snapshot, cc);		pk = bp;		bp += caplen;#endif		++p->md.stat.ps_recv;		if (bpf_filter(fcode, pk, origlen, caplen)) {#ifdef HAVE_SYS_BUFMOD_H			pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;			pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;#else			(void)gettimeofday(&pkthdr.ts, NULL);#endif			pkthdr.len = origlen;			pkthdr.caplen = caplen;			/* Insure caplen does not exceed snapshot */			if (pkthdr.caplen > p->snapshot)				pkthdr.caplen = p->snapshot;			(*callback)(user, &pkthdr, pk);			if (++n >= cnt && cnt >= 0) {				p->cc = ep - bp;				p->bp = bp;				return (n);			}		}#ifdef HAVE_SYS_BUFMOD_H	}#endif	p->cc = 0;	return (n);}static intpcap_inject_dlpi(pcap_t *p, const void *buf, size_t size){	int ret;#if defined(DLIOCRAW)	ret = write(p->fd, buf, size);	if (ret == -1) {		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",		    pcap_strerror(errno));		return (-1);	}#elif defined(DL_HP_RAWDLS)	if (p->send_fd < 0) {		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,		    "send: Output FD couldn't be opened");		return (-1);	}	ret = dlrawdatareq(p->send_fd, buf, size);	if (ret == -1) {		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",		    pcap_strerror(errno));		return (-1);	}	/*	 * putmsg() returns either 0 or -1; it doesn't indicate how	 * many bytes were written (presumably they were all written	 * or none of them were written).  OpenBSD's pcap_inject()	 * returns the number of bytes written, so, for API compatibility,	 * we return the number of bytes we were told to write.	 */	ret = size;#else /* no raw mode */	/*	 * XXX - this is a pain, because you might have to extract	 * the address from the packet and use it in a DL_UNITDATA_REQ	 * request.  That would be dependent on the link-layer type.	 *	 * I also don't know what SAP you'd have to bind the descriptor	 * to, or whether you'd need separate "receive" and "send" FDs,	 * nor do I know whether you'd need different bindings for	 * D/I/X Ethernet and 802.3, or for {FDDI,Token Ring} plus	 * 802.2 and {FDDI,Token Ring} plus 802.2 plus SNAP.	 *	 * So, for now, we just return a "you can't send" indication,	 * and leave it up to somebody with a DLPI-based system lacking	 * both DLIOCRAW and DL_HP_RAWDLS to supply code to implement	 * packet transmission on that system.  If they do, they should	 * send it to us - but should not send us code that assumes	 * Ethernet; if the code doesn't work on non-Ethernet interfaces,	 * it should check "p->linktype" and reject the send request if	 * it's anything other than DLT_EN10MB.	 */	strlcpy(p->errbuf, "send: Not supported on this version of this OS",	    PCAP_ERRBUF_SIZE);	ret = -1;#endif /* raw mode */	return (ret);}   #ifndef DL_IPATM#define DL_IPATM	0x12	/* ATM Classical IP interface */#endif#ifdef HAVE_SOLARIS/* * For SunATM. */#ifndef A_GET_UNITS#define A_GET_UNITS	(('A'<<8)|118)#endif /* A_GET_UNITS */#ifndef A_PROMISCON_REQ#define A_PROMISCON_REQ	(('A'<<8)|121)#endif /* A_PROMISCON_REQ */#endif /* HAVE_SOLARIS */static voidpcap_close_dlpi(pcap_t *p){	pcap_close_common(p);	if (p->send_fd >= 0)		close(p->send_fd);}pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,    char *ebuf){	register char *cp;	register pcap_t *p;	int ppa;#ifdef HAVE_SOLARIS	int isatm = 0;#endif	register dl_info_ack_t *infop;

⌨️ 快捷键说明

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