dect
/
libpcap
Archived
13
0
Fork 0

From Pawel Pokrywka: add support for requesting that only received

packets, only sent packets, or all packets be accepted, with an
implementation for Linux.

Add an implementation for BPF platforms that support BIOCSSEESENT.
This commit is contained in:
guy 2005-05-03 18:53:58 +00:00
parent a27ec87482
commit e987a615e2
15 changed files with 171 additions and 28 deletions

View File

@ -71,6 +71,7 @@ Additional people who have contributed patches:
Patrick Marie <mycroft@virgaria.org>
Paul Mundt <lethal@linux-sh.org>
Pavel Kankovsky <kan@dcit.cz>
Pawel Pokrywka <publicpp@gmail.com>
Peter Fales <peter@fales-lorenz.net>
Peter Jeremy <peter.jeremy@alcatel.com.au>
Phil Wood <cpw@lanl.gov>

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.88 2005-04-21 02:41:12 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.89 2005-05-03 18:53:58 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -105,6 +105,7 @@ static int odmlockid = 0;
#include "gencode.h" /* for "no_optimize" */
static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp);
static int pcap_setdirection_bpf(pcap_t *, direction_t);
static int pcap_set_datalink_bpf(pcap_t *p, int dlt);
static int
@ -1019,6 +1020,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->read_op = pcap_read_bpf;
p->inject_op = pcap_inject_bpf;
p->setfilter_op = pcap_setfilter_bpf;
p->setdirection_op = pcap_setdirection_bpf;
p->set_datalink_op = pcap_set_datalink_bpf;
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
@ -1088,6 +1090,42 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
return (0);
}
/*
* Set direction flag: Which packets do we accept on a forwarding
* single device? IN, OUT or both?
*/
static int
pcap_setdirection_bpf(pcap_t *p, direction_t d)
{
#ifdef BIOCSSEESENT
u_int seesent;
#endif
/*
* We don't support D_OUT.
*/
if (d == D_OUT) {
snprintf(p->errbuf, sizeof(p->errbuf),
"Setting direction to D_OUT is not supported on BPF");
return -1;
}
#ifdef BIOCSSEESENT
seesent = (d == D_INOUT);
if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) {
(void) snprintf(p->errbuf, sizeof(p->errbuf),
"Cannot set direction to %s: %s",
(d == D_INOUT) ? "D_INOUT" : "D_IN",
strerror(errno));
return (-1);
}
return (0);
#else
(void) snprintf(p->errbuf, sizeof(p->errbuf),
"This system doesn't support BIOCSSEESENT, so the direction can't be set");
return (-1);
#endif
}
static int
pcap_set_datalink_bpf(pcap_t *p, int dlt)
{

View File

@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21 2005-04-03 23:56:47 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.22 2005-05-03 18:53:58 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -507,6 +507,7 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
handle->read_op = dag_read;
handle->inject_op = dag_inject;
handle->setfilter_op = dag_setfilter;
handle->setdirection_op = NULL; /* Not implemented.*/
handle->set_datalink_op = dag_set_datalink;
handle->getnonblock_op = pcap_getnonblock_fd;
handle->setnonblock_op = dag_setnonblock;

View File

@ -70,7 +70,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.113 2005-04-17 17:25:51 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.114 2005-05-03 18:53:58 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -933,6 +933,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->read_op = pcap_read_dlpi;
p->inject_op = pcap_inject_dlpi;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->setdirection_op = NULL; /* Not implemented.*/
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;

View File

@ -5,7 +5,7 @@
* pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
* network drivers.
*
* @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1 2004-12-18 08:52:10 guy Exp $ (LBL)
* @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.2 2005-05-03 18:53:59 guy Exp $ (LBL)
*/
#include <stdio.h>
@ -172,6 +172,7 @@ pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc,
pcap->stats_op = pcap_stats_dos;
pcap->inject_op = pcap_sendpacket_dos;
pcap->setfilter_op = pcap_setfilter_dos;
pcap->setdirection_op = NULL; /* Not implemented.*/
pcap->fd = ++ref_count;
if (pcap->fd == 1) /* first time we're called */

View File

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.70 2005-04-07 02:47:34 guy Exp $ (LBL)
* @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.71 2005-05-03 18:53:59 guy Exp $ (LBL)
*/
#ifndef pcap_int_h
@ -150,12 +150,16 @@ struct pcap {
*/
u_char *pkt;
/* We're accepting only packets in this direction/these directions. */
direction_t direction;
/*
* Methods.
*/
int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *);
int (*inject_op)(pcap_t *, const void *, size_t);
int (*setfilter_op)(pcap_t *, struct bpf_program *);
int (*setdirection_op)(pcap_t *, direction_t);
int (*set_datalink_op)(pcap_t *, int);
int (*getnonblock_op)(pcap_t *, char *);
int (*setnonblock_op)(pcap_t *, int, char *);

View File

@ -27,7 +27,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.110 2004-10-19 07:06:12 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.111 2005-05-03 18:53:59 guy Exp $ (LBL)";
#endif
/*
@ -191,6 +191,7 @@ static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
static int pcap_inject_linux(pcap_t *, const void *, size_t);
static int pcap_stats_linux(pcap_t *, struct pcap_stat *);
static int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
static int pcap_setdirection_linux(pcap_t *, direction_t);
static void pcap_close_linux(pcap_t *);
/*
@ -407,6 +408,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
handle->read_op = pcap_read_linux;
handle->inject_op = pcap_inject_linux;
handle->setfilter_op = pcap_setfilter_linux;
handle->setdirection_op = pcap_setdirection_linux;
handle->set_datalink_op = NULL; /* can't change data link type */
handle->getnonblock_op = pcap_getnonblock_fd;
handle->setnonblock_op = pcap_setnonblock_fd;
@ -504,19 +506,37 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
}
#ifdef HAVE_PF_PACKET_SOCKETS
/*
* If this is from the loopback device, reject outgoing packets;
* we'll see the packet as an incoming packet as well, and
* we don't want to see it twice.
*
* We can only do this if we're using PF_PACKET; the address
* returned for SOCK_PACKET is a "sockaddr_pkt" which lacks
* the relevant packet type information.
*/
if (!handle->md.sock_packet &&
from.sll_ifindex == handle->md.lo_ifindex &&
from.sll_pkttype == PACKET_OUTGOING)
return 0;
if (!handle->md.sock_packet) {
/*
* Do checks based on packet direction.
* We can only do this if we're using PF_PACKET; the
* address returned for SOCK_PACKET is a "sockaddr_pkt"
* which lacks the relevant packet type information.
*/
if (from.sll_pkttype == PACKET_OUTGOING) {
/*
* Outgoing packet.
* If this is from the loopback device, reject it;
* we'll see the packet as an incoming packet as well,
* and we don't want to see it twice.
*/
if (from.sll_ifindex == handle->md.lo_ifindex)
return 0;
/*
* If the user only wants incoming packets, reject it.
*/
if (handle->direction == D_IN)
return 0;
} else {
/*
* Incoming packet.
* If the user only wants outgoing packets, reject it.
*/
if (handle->direction == D_OUT)
return 0;
}
}
#endif
#ifdef HAVE_PF_PACKET_SOCKETS
@ -974,6 +994,28 @@ pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter)
return 0;
}
/*
* Set direction flag: Which packets do we accept on a forwarding
* single device? IN, OUT or both?
*/
static int
pcap_setdirection_linux(pcap_t *handle, 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

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.57 2004-10-19 07:06:13 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.58 2005-05-03 18:54:00 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -334,6 +334,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->read_op = pcap_read_nit;
p->inject_op = pcap_inject_nit;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->setdirection_op = NULL; /* Not implemented. */
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;

View File

@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.92 2005-04-19 00:55:48 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.93 2005-05-03 18:54:00 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -497,6 +497,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
p->read_op = pcap_read_pf;
p->inject_op = pcap_inject_pf;
p->setfilter_op = pcap_setfilter_pf;
p->setdirection_op = NULL; /* Not implemented. */
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;

View File

@ -25,7 +25,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.72 2004-10-19 07:06:13 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.73 2005-05-03 18:54:00 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -397,6 +397,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->read_op = pcap_read_snit;
p->inject_op = pcap_inject_snit;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->setdirection_op = NULL; /* Not implemented. */
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.54 2004-10-19 07:06:14 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.55 2005-05-03 18:54:00 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -379,6 +379,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->read_op = pcap_read_snoop;
p->inject_op = pcap_inject_snoop;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->setdirection_op = NULL; /* Not implemented. */
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;

View File

@ -32,7 +32,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.25 2005-02-26 21:58:06 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.26 2005-05-03 18:54:01 guy Exp $ (LBL)";
#endif
#include <pcap-int.h>
@ -602,6 +602,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#ifdef HAVE_DAG_API
}
#endif /* HAVE_DAG_API */
p->setdirection_op = NULL; /* Not implemented. */
/* XXX - can this be implemented on some versions of Windows? */
p->inject_op = pcap_inject_win32;
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_win32;

29
pcap.3
View File

@ -1,4 +1,4 @@
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.65 2005-04-13 18:59:41 mcr Exp $
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.66 2005-05-03 18:54:01 guy Exp $
.\"
.\" Copyright (c) 1994, 1996, 1997
.\" The Regents of the University of California. All rights reserved.
@ -79,7 +79,8 @@ int pcap_compile(pcap_t *p, struct bpf_program *fp,
.ti +8
char *str, int optimize, bpf_u_int32 netmask)
int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
void pcap_freecode(struct bpf_program *);
void pcap_freecode(struct bpf_program *)
int pcap_setdirection(pcap_t *p, direction_t d)
.ft
.LP
.ft B
@ -777,6 +778,30 @@ when that BPF program is no longer needed, for example after it
has been made the filter program for a pcap structure by a call to
.BR pcap_setfilter() .
.PP
.B pcap_setdirection()
is used to specify a direction that packets will be captured.
.I direction_t
is one of the constants
.BR D_IN ,
.B D_OUT
or
.BR D_INOUT .
.B D_IN
will only capture packets received by the device,
.B D_OUT
will only capture packets sent by the device and
.B D_INOUT
will capture packets received by or sent by the device.
.B D_INOUT
is the default setting if this function is not called. This isn't
necessarily supported on all platforms; some platforms might return an
error, and some other platforms might not support
.BR D_OUT .
.B \-1
is returned on failure,
.B 0
is returned on success.
.PP
.B pcap_datalink()
returns the link layer type; link layer types it can return include:
.PP

19
pcap.c
View File

@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.88 2005-02-08 20:03:15 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.89 2005-05-03 18:54:01 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -685,6 +685,23 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp)
return p->setfilter_op(p, fp);
}
/*
* Set direction flag, which controls whether we accept only incoming
* packets, only outgoing packets, or both.
* Note that, depending on the platform, some or all direction arguments
* might not be supported.
*/
int
pcap_setdirection(pcap_t *p, direction_t d)
{
if (p->setdirection_op == NULL) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Setting direction is not implemented on this platform");
return -1;
} else
return p->setdirection_op(p, d);
}
int
pcap_stats(pcap_t *p, struct pcap_stat *ps)
{

9
pcap.h
View File

@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.52 2004-12-18 08:52:11 guy Exp $ (LBL)
* @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.53 2005-05-03 18:54:02 guy Exp $ (LBL)
*/
#ifndef lib_pcap_h
@ -120,6 +120,12 @@ struct pcap_file_header {
bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
};
typedef enum {
D_INOUT = 0,
D_IN,
D_OUT
} direction_t;
/*
* Each packet in the dump file is prepended with this generic header.
* This gets around the problem of different headers for different
@ -218,6 +224,7 @@ int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
void pcap_breakloop(pcap_t *);
int pcap_stats(pcap_t *, struct pcap_stat *);
int pcap_setfilter(pcap_t *, struct bpf_program *);
int pcap_setdirection(pcap_t *, direction_t);
int pcap_getnonblock(pcap_t *, char *);
int pcap_setnonblock(pcap_t *, int, char *);
void pcap_perror(pcap_t *, char *);