dect
/
libpcap
Archived
13
0
Fork 0

Add support for sending packets; includes contributions from Mark

Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net>.
This commit is contained in:
guy 2004-03-23 19:18:04 +00:00
parent 3380fa10db
commit 2d2890dd37
15 changed files with 453 additions and 54 deletions

View File

@ -55,6 +55,7 @@ Additional people who have contributed patches:
Love Hörnquist-Ĺstrand <lha@stacken.kth.se>
Maciej W. Rozycki <macro@ds2.pg.gda.pl>
Marcus Felipe Pereira <marcus@task.com.br>
Mark Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net>
Martin Husemann <martin@netbsd.org>
Mike Wiacek <mike@iroot.net>
Monroe Williams <monroe@pobox.com>

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.73 2003-12-24 08:26:24 itojun Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.74 2004-03-23 19:18:04 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -292,6 +292,29 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (n);
}
static int
pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
{
int ret;
/*
* Do a BIOCSHDRCMPLT, if defined, to turn that flag on, so
* the link-layer source address isn't forcibly overwritten?
* (Ignore errors? Return errors if not "sorry, that ioctl
* isn't supported?)
*
* XXX - I seem to remember some packet-sending bug in some
* BSDs - check CVS log for "bpf.c"?
*/
ret = write(p->fd, buf, size);
if (ret == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
}
#ifdef _AIX
static int
bpf_odminit(char *errbuf)
@ -467,7 +490,23 @@ bpf_open(pcap_t *p, char *errbuf)
*/
do {
(void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
fd = open(device, O_RDONLY);
/*
* Initially try a read/write open (to allow the inject
* method to work). If that fails due to permission
* issues, fall back to read-only. This allows a
* non-root user to be granted specific access to pcap
* capabilities via file permissions.
*
* XXX - we should have an API that has a flag that
* controls whether to open read-only or read-write,
* so that denial of permission to send (or inability
* to send, if sending packets isn't supported on
* the device in question) can be indicated at open
* time.
*/
fd = open(device, O_RDWR);
if (fd == -1 && errno == EACCES)
fd = open(device, O_RDONLY);
} while (fd < 0 && errno == EBUSY);
/*
@ -898,6 +937,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->set_datalink_op = pcap_set_datalink_bpf;
p->getnonblock_op = pcap_getnonblock_fd;

View File

@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.17 2004-01-30 02:23:53 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.18 2004-03-23 19:18:04 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -377,6 +377,14 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return processed;
}
static int
dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
{
strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
PCAP_ERRBUF_SIZE);
return (-1);
}
/*
* Get a handle for a live capture from the given DAG device. Passing a NULL
* device will result in a failure. The promisc flag is ignored because DAG
@ -503,6 +511,7 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
#endif
handle->read_op = dag_read;
handle->inject_op = dag_inject;
handle->setfilter_op = dag_setfilter;
handle->set_datalink_op = dag_set_datalink;
handle->getnonblock_op = pcap_getnonblock_fd;

View File

@ -38,7 +38,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.95 2003-12-18 23:32:32 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.96 2004-03-23 19:18:05 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -220,6 +220,11 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
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 */
if (errno == EINTR) {
@ -306,6 +311,23 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (n);
}
static int
pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
{
int ret;
/*
* XXX - use "dlunitdatareq()" on HP-UX.
*/
ret = write(p->fd, buf, size);
if (ret == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
}
#ifndef DL_IPATM
#define DL_IPATM 0x12 /* ATM Classical IP interface */
#endif
@ -573,6 +595,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/*
** 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)
@ -612,6 +636,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
break;
case DL_TPR:
/*
* XXX - what about DL_TPB? Is that Token Bus?
*/
p->linktype = DLT_IEEE802;
p->offset = 2;
break;
@ -730,6 +757,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->selectable_fd = p->fd;
p->read_op = pcap_read_dlpi;
p->inject_op = pcap_inject_dlpi;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
@ -1194,6 +1222,77 @@ dlinfoack(int fd, char *bufp, char *ebuf)
return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf));
}
#if 0
/*
* No ack?
*
* On HP-UX, use DL_HP_RAWDATA_REQ instead, *if* we're in RAW mode.
* There is an ack *IF* there's an error.
*
* XXX - this is not needed on Solaris; we're running in raw mode so
* we can just do a "write()".
* What about, say, AIX?
*/
static int
dlunitdatareq(int fd, u_char *addrp, int addrlen, u_char *datap, int datalen)
{
struct strbuf ctl, data;
long buf[MAXDLBUF]; /* XXX - char? */
union DL_primitives *dlp;
dlp = (union DL_primitives*) buf;
dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ;
dlp->unitdata_req.dl_dest_addr_length = addrlen;
dlp->unitdata_req.dl_dest_addr_offset = DL_UNITDATA_REQ_SIZE;
dlp->unitdata_req.dl_priority.dl_min = 0;
dlp->unitdata_req.dl_priority.dl_max = 0
/*
* XXX - the "address", on Ethernet, is the destination address,
* followed by the link-layer type. What is it for other
* link layers?
*
* The address length "dl_addr_length" from the "info_ack"
* structure is the total length of the link-layer address.
*
* The SAP length "dl_sap_length" is the length of the SAP part
* of the address.
* If positive, the SAP comes before the destination address;
* if negative, the SAP comes after the destination address.
*
* XXX - what about Ethernet vs. 802.3? Is the SAP the Ethertype
* or the DSAP? How can we send both? *Can* we send both on
* the same device?
*
* Note that in raw mode, we send a raw link-layer packet.
* In that mode, can we avoid worrying about this crap?
*
* For ATM (ha ha), we might not be able to send packets,
* even in raw mode, without binding to a VC. (Presumably
* going into SAP promiscuous mode lets us *see* all packets.)
*
* XXX - extract it from the packet to be sent.
*/
memcpy((char *)dlp + DL_UNITDATA_REQ_SIZE, addrp, addrlen);
ctl.maxlen = 0;
ctl.len = DL_UNITDATA_REQ_SIZE + addrlen;
ctl.buf = buf;
data.maxlen = 0;
data.len = datalen;
data.buf = datap;
if (putmsg(fd, &ctl, &data, 0) < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"dlunitdatareq: putmsg: %s", pcap_strerror(errno));
return (-1);
}
return (0);
}
#endif
#ifdef HAVE_SYS_BUFMOD_H
static int
strioctl(int fd, int cmd, int len, char *dp)

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.61 2003-12-21 22:00:10 guy Exp $ (LBL)
* @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.62 2004-03-23 19:18:05 guy Exp $ (LBL)
*/
#ifndef pcap_int_h
@ -74,13 +74,14 @@ struct pcap_md {
u_long TotDrops; /* count of dropped packets */
long TotMissed; /* missed by i/f during this run */
long OrigMissed; /* missed by i/f before this run */
char *device; /* device name */
#ifdef linux
int sock_packet; /* using Linux 2.0 compatible interface */
int timeout; /* timeout specified to pcap_open_live */
int clear_promisc; /* must clear promiscuous mode when we close */
int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */
int ifindex; /* interface index of device we're bound to */
int lo_ifindex; /* interface index of the loopback device */
char *device; /* device name */
struct pcap *next; /* list of open promiscuous sock_packet pcaps */
#endif
@ -130,6 +131,7 @@ struct pcap {
* 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 (*set_datalink_op)(pcap_t *, int);
int (*getnonblock_op)(pcap_t *, char *);

View File

@ -27,7 +27,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.105 2004-01-14 01:56:10 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.106 2004-03-23 19:18:05 guy Exp $ (LBL)";
#endif
/*
@ -188,6 +188,7 @@ static int live_open_old(pcap_t *, const char *, int, int, char *);
static int live_open_new(pcap_t *, const char *, int, int, char *);
static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
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 void pcap_close_linux(pcap_t *);
@ -404,6 +405,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
handle->selectable_fd = handle->fd;
handle->read_op = pcap_read_linux;
handle->inject_op = pcap_inject_linux;
handle->setfilter_op = pcap_setfilter_linux;
handle->set_datalink_op = NULL; /* can't change data link type */
handle->getnonblock_op = pcap_getnonblock_fd;
@ -672,6 +674,63 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
return 1;
}
static int
pcap_inject_linux(pcap_t *handle, const void *buf, size_t size)
{
#ifdef HAVE_PF_PACKET_SOCKETS
struct sockaddr_ll sa_ll;
#endif
struct sockaddr_pkt sa_pkt;
int ret;
#ifdef HAVE_PF_PACKET_SOCKETS
if (!handle->md.sock_packet)) {
/* PF_PACKET socket */
if (handle->md.ifindex == -1) {
/*
* Cooked mode - can't send.
* XXX - how do you send on a bound cooked-mode
* socket?
*/
strlcpy(handle->errbuf,
"Sending packets isn't supported in cooked mode",
PCAP_ERRBUF_SIZE);
return (-1);
}
memset(&sa_ll, 0, sizeof(sa_ll));
sa_ll.sll_family = AF_PACKET;
sa_ll.sll_ifindex = handle->md.ifindex;
/*
* Do we have to set the hardware address?
*/
sa_ll.sll_protocol = htons(ETH_P_ALL);
ret = sendto(handle->fd, buf, size, 0, &sa_ll, sizeof(sa_ll));
if (ret == -1) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
}
#endif
memset(&sa_pkt, 0, sizeof(sa_pkt));
sa_pkt.spkt_family = PF_INET;
strcpy(sa_pkt.spkt_device, handle->md.device);
/*
* Do we have to set "spkt_protocol" to the Ethernet protocol?
*/
ret = sendto(handle->fd, buf, size, 0, &sa, sizeof(sa)));
if (ret == -1) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
}
/*
* Get the statistics for the given packet capture handle.
* Reports the number of dropped packets iff the kernel supports
@ -1221,7 +1280,7 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
int to_ms, char *ebuf)
{
#ifdef HAVE_PF_PACKET_SOCKETS
int sock_fd = -1, device_id, arptype;
int sock_fd = -1, arptype;
int err;
int fatal_err = 0;
struct packet_mreq mr;
@ -1341,11 +1400,12 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
handle->linktype = DLT_LINUX_SLL;
}
device_id = iface_get_id(sock_fd, device, ebuf);
if (device_id == -1)
handle->md.ifindex = iface_get_id(sock_fd, device, ebuf);
if (handle->md.ifindex == -1)
break;
if ((err = iface_bind(sock_fd, device_id, ebuf)) < 0) {
if ((err = iface_bind(sock_fd, handle->md.ifindex,
ebuf)) < 0) {
if (err == -2)
fatal_err = 1;
break;
@ -1358,14 +1418,15 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
handle->linktype = DLT_LINUX_SLL;
/*
* XXX - squelch GCC complaints about
* uninitialized variables; if we can't
* select promiscuous mode on all interfaces,
* we should move the code below into the
* "if (device)" branch of the "if" and
* get rid of the next statement.
* We're not bound to a device.
* XXX - true? Or true only if we're using
* the "any" device?
* For now, we're using this as an indication
* that we can't transmit; stop doing that only
* if we figure out how to transmit in cooked
* mode.
*/
device_id = -1;
handle->md.ifindex = -1;
}
/*
@ -1389,7 +1450,7 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
if (device && promisc) {
memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = device_id;
mr.mr_ifindex = handle->md.ifindex;
mr.mr_type = PACKET_MR_PROMISC;
if (setsockopt(sock_fd, SOL_PACKET,
PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1)

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.55 2004-03-21 08:32:05 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.56 2004-03-23 19:18:06 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -192,6 +192,23 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (n);
}
static int
pcap_inject_nit(pcap_t *p, const void *buf, size_t size)
{
struct sockaddr sa;
int ret;
memset(&sa, 0, sizeof(sa));
strncpy(sa.sa_data, device, sizeof(sa.sa_data));
ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa));
if (ret == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
}
static int
nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
{
@ -226,6 +243,8 @@ pcap_close_nit(pcap_t *p)
{
if (p->buffer != NULL)
free(p->buffer);
if (p->device != NULL)
free(p->device);
if (p->fd >= 0)
close(p->fd);
}
@ -280,6 +299,16 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
goto bad;
}
/*
* We need the device name in order to send packets.
*/
p->device = strdup(device);
if (p->device == NULL) {
strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
free(p->buffer);
goto bad;
}
/*
* "p->fd" is a socket, so "select()" should work on it.
*/
@ -306,6 +335,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->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;

View File

@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.86 2004-02-09 06:24:42 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.87 2004-03-23 19:18:06 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -219,6 +219,20 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
return (n);
}
static int
pcap_inject_pf(pcap_t *p, const void *buf, size_t size)
{
int ret;
ret = write(p->fd, buf, size);
if (ret == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
}
static int
pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
{
@ -299,14 +313,28 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
return (0);
}
memset(p, 0, sizeof(*p));
/*
* Initially try a read/write open (to allow the inject
* method to work). If that fails due to permission
* issues, fall back to read-only. This allows a
* non-root user to be granted specific access to pcap
* capabilities via file permissions.
*
* XXX - we should have an API that has a flag that
* controls whether to open read-only or read-write,
* so that denial of permission to send (or inability
* to send, if sending packets isn't supported on
* the device in question) can be indicated at open
* time.
*
* XXX - we assume here that "pfopen()" does not, in fact, modify
* its argument, even though it takes a "char *" rather than a
* "const char *" as its first argument. That appears to be
* the case, at least on Digital UNIX 4.0.
*/
p->fd = pfopen(device, O_RDONLY);
p->fd = pfopen(device, O_RDWR);
if (p->fd == -1 && errno == EACCES)
p->fd = pfopen(device, O_RDONLY);
if (p->fd < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\
your system may not be properly configured; see the packetfilter(4) man page\n",
@ -467,6 +495,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
p->selectable_fd = p->fd;
p->read_op = pcap_read_pf;
p->inject_op = pcap_inject_pf;
p->setfilter_op = pcap_setfilter_pf;
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;

View File

@ -25,7 +25,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.70 2003-12-18 23:32:33 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.71 2004-03-23 19:18:06 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -204,6 +204,29 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (n);
}
static int
pcap_inject_snit(pcap_t *p, const void *buf, size_t size)
{
struct strbuf ctl, data;
/*
* XXX - can we just do
*
ret = write(pd->f, buf, size);
*/
ctl.len = sizeof(*sa); /* XXX - what was this? */
ctl.buf = (char *)sa;
data.buf = buf;
data.len = size;
ret = putmsg(p->fd, &ctl, &data);
if (ret == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
}
static int
nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
{
@ -271,7 +294,23 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
snaplen = 96;
memset(p, 0, sizeof(*p));
p->fd = fd = open(dev, O_RDONLY);
/*
* Initially try a read/write open (to allow the inject
* method to work). If that fails due to permission
* issues, fall back to read-only. This allows a
* non-root user to be granted specific access to pcap
* capabilities via file permissions.
*
* XXX - we should have an API that has a flag that
* controls whether to open read-only or read-write,
* so that denial of permission to send (or inability
* to send, if sending packets isn't supported on
* the device in question) can be indicated at open
* time.
*/
p->fd = fd = open(dev, O_RDWR);
if (fd < 0 && errno == EACCES)
p->fd = fd = open(dev, O_RDONLY);
if (fd < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dev,
pcap_strerror(errno));
@ -365,6 +404,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->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.51 2004-03-21 08:32:06 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.52 2004-03-23 19:18:06 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -125,6 +125,22 @@ again:
return (0);
}
static int
pcap_inject_snoop(pcap_t *p, const void *buf, size_t size)
{
/*
* XXX - libnet overwrites the source address with what I
* presume is the interface's address; is that required?
*/
ret = write(p->fd, buf, size);
if (ret == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
}
static int
pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
{
@ -358,6 +374,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->selectable_fd = p->fd;
p->read_op = pcap_read_snoop;
p->inject_op = pcap_inject_snoop;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;

View File

@ -32,7 +32,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.20 2004-01-28 14:06:20 risso Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.21 2004-03-23 19:18:07 guy Exp $ (LBL)";
#endif
#include <pcap-int.h>
@ -344,6 +344,29 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
#endif /* HAVE_DAG_API */
/* Send a packet to the network */
static int
pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
LPPACKET PacketToSend;
PacketToSend=PacketAllocatePacket();
PacketInitPacket(PacketToSend,buf,size);
if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
PacketFreePacket(PacketToSend);
return -1;
}
PacketFreePacket(PacketToSend);
/*
* We assume it all got sent if "PacketSendPacket()" succeeded.
* "pcap_inject()" is expected to return the number of bytes
* sent.
*/
return size;
}
static void
pcap_close_win32(pcap_t *p)
{
@ -569,6 +592,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#ifdef HAVE_DAG_API
}
#endif /* HAVE_DAG_API */
p->inject_op = pcap_inject_win32;
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_win32;
p->setnonblock_op = pcap_setnonblock_win32;
@ -686,28 +710,6 @@ pcap_setmode(pcap_t *p, int mode){
return 0;
}
/* Send a packet to the network */
int
pcap_sendpacket(pcap_t *p, u_char *buf, int size){
LPPACKET PacketToSend;
if (p->adapter==NULL)
{
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter");
return -1;
}
PacketToSend=PacketAllocatePacket();
PacketInitPacket(PacketToSend,buf,size);
if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
PacketFreePacket(PacketToSend);
return -1;
}
PacketFreePacket(PacketToSend);
return 0;
}
/* Set the dimension of the kernel-level capture buffer */
int
pcap_setbuff(pcap_t *p, int dim)

37
pcap.3
View File

@ -1,4 +1,4 @@
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.58 2004-02-28 02:51:26 guy Exp $
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.59 2004-03-23 19:18:07 guy Exp $
.\"
.\" Copyright (c) 1994, 1996, 1997
.\" The Regents of the University of California. All rights reserved.
@ -88,6 +88,11 @@ void pcap_breakloop(pcap_t *)
.ft
.LP
.ft B
int pcap_inject(pcap_t *p, const void *buf, size_t size)
int pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
.ft
.LP
.ft B
int pcap_datalink(pcap_t *p)
int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
int pcap_set_datalink(pcap_t *p, int dlt);
@ -628,6 +633,36 @@ the flag is cleared, so a subsequent call will resume reading packets.
If a positive number is returned, the flag is not cleared, so a
subsequent call will return \-2 and clear the flag.
.PP
.B pcap_inject()
sends a raw packet through the network interface;
.I buf
points to the data of the packet, including the link-layer header, and
.I size
is the number of bytes in the packet.
It returns the number of bytes written on success. A return of \-1
indicates an error in which case
.B pcap_perror()
or
.B pcap_geterr()
may be used to display the error text.
Note that, even if you successfully open the network interface, you
might not have permission to send packets on it, or it might not support
sending packets; as
.I pcap_open_live()
doesn't have a flag to indicate whether to open for capturing, sending,
or capturing and sending, you cannot request an open that supports
sending and be notified at open time whether sending will be possible.
Note also that some devices might not support sending packets.
.PP
.B pcap_sendpacket()
is like
.BR pcap_inject() ,
but it returns 0 on success and \-1 on failure.
.RB ( pcap_inject()
comes from OpenBSD;
.B pcap_sendpacket()
comes from WinPcap. Both are provided for compatibility.)
.PP
.B pcap_dump()
outputs a packet to the ``savefile'' opened with
.BR pcap_dump_open() .

26
pcap.c
View File

@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.72 2004-03-17 19:03:29 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.73 2004-03-23 19:18:07 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -700,6 +700,30 @@ pcap_open_dead(int linktype, int snaplen)
return p;
}
/*
* API compatible with WinPcap's "send a packet" routine - returns -1
* on error, 0 otherwise.
*
* XXX - what if we get a short write?
*/
int
pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
{
if (p->inject_op(p, buf, size) == -1)
return (-1);
return (0);
}
/*
* API compatible with OpenBSD's "send a packet" routine - returns -1 on
* error, number of bytes written otherwise.
*/
int
pcap_inject(pcap_t *p, const void *buf, size_t size)
{
return (p->inject_op(p, buf, size));
}
void
pcap_close(pcap_t *p)
{

5
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.49 2004-01-27 09:44:14 risso Exp $ (LBL)
* @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.50 2004-03-23 19:18:07 guy Exp $ (LBL)
*/
#ifndef lib_pcap_h
@ -184,6 +184,8 @@ int pcap_setfilter(pcap_t *, struct bpf_program *);
int pcap_getnonblock(pcap_t *, char *);
int pcap_setnonblock(pcap_t *, int, char *);
void pcap_perror(pcap_t *, char *);
int pcap_inject(pcap_t *, const void *, size_t);
int pcap_sendpacket(pcap_t *, const u_char *, int);
char *pcap_strerror(int);
char *pcap_geterr(pcap_t *);
int pcap_compile(pcap_t *, struct bpf_program *, char *, int,
@ -230,7 +232,6 @@ void bpf_dump(struct bpf_program *, int);
int pcap_setbuff(pcap_t *p, int dim);
int pcap_setmode(pcap_t *p, int mode);
int pcap_sendpacket(pcap_t *p, u_char *buf, int size);
int pcap_setmintocopy(pcap_t *p, int size);
#ifdef WPCAP

View File

@ -30,7 +30,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.105 2004-03-16 19:27:55 risso Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.106 2004-03-23 19:18:08 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -574,6 +574,14 @@ sf_stats(pcap_t *p, struct pcap_stat *ps)
return (-1);
}
static int
sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
{
strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
PCAP_ERRBUF_SIZE);
return (-1);
}
static void
sf_close(pcap_t *p)
{
@ -730,6 +738,7 @@ pcap_open_offline(const char *fname, char *errbuf)
#endif
p->read_op = pcap_offline_read;
p->inject_op = sf_inject;
p->setfilter_op = install_bpf_program;
p->set_datalink_op = NULL; /* we don't support munging link-layer headers */
p->getnonblock_op = sf_getnonblock;