pcap-pf.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 256 行

C
256
字号
/* * Copyright (c) 1990 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. * * SCCSID: @(#)pcap-pf.c	4.1	ULTRIX	1/25/91 * Based on: * rcsid[] = "@(#)$Header: pcap-pf.c,v 1.16 90/12/04 17:12:42 mccanne Exp $ (LBL)" *//* * packet filter subroutines for tcpdump *	Extraction/creation by Jeffrey Mogul, DECWRL * * Extracted from tcpdump.c. */#include <stdio.h>#include <netdb.h>#include <ctype.h>#include <signal.h>#include <errno.h>#include <sys/types.h>#include <sys/time.h>#include <sys/timeb.h>#include <sys/socket.h>#include <sys/file.h>#include <sys/ioctl.h>#include <net/pfilt.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#include <netinet/ip_var.h>#include <netinet/udp.h>#include <netinet/udp_var.h>#include <netinet/tcp.h>#include <netinet/tcpip.h>#include <net/bpf.h>#include "interface.h"static	u_long	TotPkts = 0;		/* can't oflow for 79 hrs on ether */static	u_long	TotDrops = 0;		/* count of dropped packets */static	long	TotMissed = 0;		/* missed by i/f during this run */static	long	OrigMissed = -1;	/* missed by i/f before this run */void pfReadError();static void PrintPFStats();extern int errno;/* * BUFSPACE is the size in bytes of the packet read buffer.  Most tcpdump * applications aren't going to need more than 200 bytes of packet header * and the read shouldn't return more packets than packetfilter's internal * queue limit (bounded at 256). */#define BUFSPACE (200*256)voidreadloop(cnt, if_fd, fp, printit)	int cnt;	int if_fd;	struct bpf_program *fp;	void (*printit)();{	u_char *p;	struct bpf_insn *fcode;	int cc;	/* This funny declaration forces buf to be properly aligned.	   We really just want a u_char buffer that is BUFSPACE	   bytes large. */	struct enstamp buf[BUFSPACE / sizeof(struct enstamp)];	fcode = fp->bf_insns;	while (1) {		register u_char *bp;		int buflen, inc;		struct enstamp stamp;		if ((cc = read(if_fd, (char *)buf, sizeof(buf))) < 0) {			pfReadError(if_fd, "reader");		}		/*		 * Loop through each packet.		 */		bp = (u_char *)buf;		while (cc > 0) {			/* avoid alignment issues here */			bcopy((char *)bp, (char *)&stamp, sizeof(stamp));			if (stamp.ens_stamplen != sizeof(stamp)) {				/* buffer is garbage, treat it as poison */				break;			}			TotPkts++;			TotDrops += stamp.ens_dropped;			TotMissed = stamp.ens_ifoverflows;			if (OrigMissed < 0)				OrigMissed = TotMissed;			p = bp + stamp.ens_stamplen;			buflen = stamp.ens_count;			if (buflen > snaplen)				buflen = snaplen;			if (bpf_filter(fcode, p, stamp.ens_count, buflen)) { 				(*printit)(p, &stamp.ens_tstamp,					   stamp.ens_count, buflen);				if (cflag && --cnt == 0)					goto out;			}			inc = ENALIGN(buflen + stamp.ens_stamplen);			cc -= inc;			bp += inc;		}	} out:	wrapup(if_fd);}/* Call ONLY if read() has returned an error on packet filter */voidpfReadError(fid, msg)	int fid;	char *msg;{	if (errno == EINVAL) {	/* read MAXINT bytes already! */		if (lseek(fid, 0L, 0) < 0) {			perror("pfReadError/lseek");			exit(-1);		}		else			return;	}	else {		perror(msg);		exit(-1);	}}wrapup(fd)	int fd;{	PrintPFStats();	(void)close(fd);}static voidPrintPFStats(){	int missed = TotMissed - OrigMissed;		(void)printf("%d packets", TotPkts);	if (TotDrops)		(void)printf(" + %d discarded by kernel", TotDrops);	if (missed)		(void)printf(" + %d discarded by interface", missed);	(void)printf("\n");}intinitdevice(device, pflag, linktype)	char *device;	int pflag;	int *linktype;{	struct timeval timeout;	short enmode;	int backlog = -1;	/* request the most */	struct enfilter Filter;	int if_fd;		if_fd = pfopen(device, 0);	if (if_fd < 0) {		perror(device);		error("your system may not be properly configured; see \"man packetfilter(4)\"");	}	/* set timeout */	timeout.tv_sec = 1;	timeout.tv_usec = 0;	if (ioctl(if_fd, EIOCSRTIMEOUT, &timeout) < 0) {		perror(device);		exit(-1);	}	enmode = ENTSTAMP|ENBATCH|ENNONEXCL;	/* set promiscuous mode if requested */	if (pflag == 0) {		enmode |= ENPROMISC;	}	if (ioctl(if_fd, EIOCMBIS, &enmode) < 0) {		perror(device);		exit(-1);	}#ifdef	ENCOPYALL	/* Try to set COPYALL mode so that we see packets to ourself */	enmode = ENCOPYALL;	ioctl(if_fd, EIOCMBIS, &enmode);	/* OK if this fails */#endif	/* set the backlog */	if (ioctl(if_fd, EIOCSETW, &backlog) < 0) {		perror(device);		exit(-1);	}	/* set truncation */	if (ioctl(if_fd, EIOCTRUNCATE, &snaplen) < 0) {		perror(device);		exit(-1);	}	/* accept all packets */	Filter.enf_Priority = 37;	/* anything > 2 */	Filter.enf_FilterLen = 0;	/* means "always true" */	if (ioctl(if_fd, EIOCSETF, &Filter) < 0) {		perror(device);		exit(-1);	}	/*	 * XXX	 * Currently, the Ultrix packet filter supports only Ethernets.	 * Eventually, support for FDDI and PPP (and possibly others) will	 * be added.  At some point, we will have to recode this to do 	 * the EIOCDEVP ioctl to get the ENDT_* type, and then convert 	 * that to a DLT_* type.	 */	*linktype = DLT_EN10MB;	return(if_fd);}

⌨️ 快捷键说明

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