map_packet_type_to_sll_type() isn't used - and won't compile - if you
don't have PF_PACKET support; #ifdef it out. Move the code to compute the buffer size into live_open_new() and live_open_old(), as it's dependent on the mechanism being used; there's little code shared between the two variants.
This commit is contained in:
parent
9f8edc61fa
commit
c0b1d4703d
179
pcap-linux.c
179
pcap-linux.c
|
@ -34,7 +34,7 @@
|
|||
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.133 2008-01-06 20:23:17 guy Exp $ (LBL)";
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.134 2008-01-24 20:20:08 guy Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -213,7 +213,9 @@ typedef int socklen_t;
|
|||
* Prototypes for internal functions
|
||||
*/
|
||||
static void map_arphrd_to_dlt(pcap_t *, int, int);
|
||||
#ifdef HAVE_PF_PACKET_SOCKETS
|
||||
static short int map_packet_type_to_sll_type(short int);
|
||||
#endif
|
||||
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 live_open_mmap(pcap_t *, char *);
|
||||
|
@ -277,10 +279,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
|||
char *ebuf)
|
||||
{
|
||||
pcap_t *handle;
|
||||
int mtu;
|
||||
int err;
|
||||
int live_open_ok = 0;
|
||||
struct utsname utsname;
|
||||
|
||||
#ifdef HAVE_DAG_API
|
||||
if (strstr(device, "dag")) {
|
||||
|
@ -388,89 +388,6 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the buffer size.
|
||||
*
|
||||
* If we're using SOCK_PACKET, this might be a 2.0[.x] kernel,
|
||||
* and might require special handling - check.
|
||||
*/
|
||||
if (handle->md.sock_packet && (uname(&utsname) < 0 ||
|
||||
strncmp(utsname.release, "2.0", 3) == 0)) {
|
||||
/*
|
||||
* We're using a SOCK_PACKET structure, and either
|
||||
* we couldn't find out what kernel release this is,
|
||||
* or it's a 2.0[.x] kernel.
|
||||
*
|
||||
* In the 2.0[.x] kernel, a "recvfrom()" on
|
||||
* a SOCK_PACKET socket, with MSG_TRUNC set, will
|
||||
* return the number of bytes read, so if we pass
|
||||
* a length based on the snapshot length, it'll
|
||||
* return the number of bytes from the packet
|
||||
* copied to userland, not the actual length
|
||||
* of the packet.
|
||||
*
|
||||
* This means that, for example, the IP dissector
|
||||
* in tcpdump will get handed a packet length less
|
||||
* than the length in the IP header, and will
|
||||
* complain about "truncated-ip".
|
||||
*
|
||||
* So we don't bother trying to copy from the
|
||||
* kernel only the bytes in which we're interested,
|
||||
* but instead copy them all, just as the older
|
||||
* versions of libpcap for Linux did.
|
||||
*
|
||||
* The buffer therefore needs to be big enough to
|
||||
* hold the largest packet we can get from this
|
||||
* device. Unfortunately, we can't get the MRU
|
||||
* of the network; we can only get the MTU. The
|
||||
* MTU may be too small, in which case a packet larger
|
||||
* than the buffer size will be truncated *and* we
|
||||
* won't get the actual packet size.
|
||||
*
|
||||
* However, if the snapshot length is larger than
|
||||
* the buffer size based on the MTU, we use the
|
||||
* snapshot length as the buffer size, instead;
|
||||
* this means that with a sufficiently large snapshot
|
||||
* length we won't artificially truncate packets
|
||||
* to the MTU-based size.
|
||||
*
|
||||
* This mess just one of many problems with packet
|
||||
* capture on 2.0[.x] kernels; you really want a
|
||||
* 2.2[.x] or later kernel if you want packet capture
|
||||
* to work well.
|
||||
*/
|
||||
mtu = iface_get_mtu(handle->fd, device, ebuf);
|
||||
if (mtu == -1) {
|
||||
pcap_close_linux(handle);
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
handle->bufsize = MAX_LINKHEADER_SIZE + mtu;
|
||||
if (handle->bufsize < handle->snapshot)
|
||||
handle->bufsize = handle->snapshot;
|
||||
} else {
|
||||
/*
|
||||
* This is a 2.2[.x] or later kernel (we know that
|
||||
* either because we're not using a SOCK_PACKET
|
||||
* socket - PF_PACKET is supported only in 2.2
|
||||
* and later kernels - or because we checked the
|
||||
* kernel version).
|
||||
*
|
||||
* We can safely pass "recvfrom()" a byte count
|
||||
* based on the snapshot length.
|
||||
*
|
||||
* If we're in cooked mode, make the snapshot length
|
||||
* large enough to hold a "cooked mode" header plus
|
||||
* 1 byte of packet data (so we don't pass a byte
|
||||
* count of 0 to "recvfrom()").
|
||||
*/
|
||||
if (handle->md.cooked) {
|
||||
if (handle->snapshot < SLL_HDR_LEN + 1)
|
||||
handle->snapshot = SLL_HDR_LEN + 1;
|
||||
}
|
||||
handle->bufsize = handle->snapshot;
|
||||
}
|
||||
|
||||
/* Allocate the buffer */
|
||||
|
||||
handle->buffer = malloc(handle->bufsize + handle->offset);
|
||||
|
@ -1107,6 +1024,7 @@ pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d)
|
|||
}
|
||||
|
||||
|
||||
#ifdef HAVE_PF_PACKET_SOCKETS
|
||||
/*
|
||||
* Map the PACKET_ value to a LINUX_SLL_ value; we
|
||||
* want the same numerical value to be used in
|
||||
|
@ -1139,6 +1057,7 @@ map_packet_type_to_sll_type(short int sll_pkttype)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Linux uses the ARP hardware type to identify the type of an
|
||||
|
@ -1635,6 +1554,26 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a 2.2[.x] or later kernel (we know that
|
||||
* because we're not using a SOCK_PACKET socket -
|
||||
* PF_PACKET is supported only in 2.2 and later
|
||||
* kernels).
|
||||
*
|
||||
* We can safely pass "recvfrom()" a byte count
|
||||
* based on the snapshot length.
|
||||
*
|
||||
* If we're in cooked mode, make the snapshot length
|
||||
* large enough to hold a "cooked mode" header plus
|
||||
* 1 byte of packet data (so we don't pass a byte
|
||||
* count of 0 to "recvfrom()").
|
||||
*/
|
||||
if (handle->md.cooked) {
|
||||
if (handle->snapshot < SLL_HDR_LEN + 1)
|
||||
handle->snapshot = SLL_HDR_LEN + 1;
|
||||
}
|
||||
handle->bufsize = handle->snapshot;
|
||||
|
||||
/* Save the socket FD in the pcap structure */
|
||||
|
||||
handle->fd = sock_fd;
|
||||
|
@ -2165,6 +2104,8 @@ live_open_old(pcap_t *handle, const char *device, int promisc,
|
|||
{
|
||||
int arptype;
|
||||
struct ifreq ifr;
|
||||
struct utsname utsname;
|
||||
int mtu;
|
||||
|
||||
do {
|
||||
/* Open the socket */
|
||||
|
@ -2266,6 +2207,72 @@ live_open_old(pcap_t *handle, const char *device, int promisc,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the buffer size.
|
||||
*
|
||||
* We're using SOCK_PACKET, so this might be a 2.0[.x]
|
||||
* kernel, and might require special handling - check.
|
||||
*/
|
||||
if (uname(&utsname) < 0 ||
|
||||
strncmp(utsname.release, "2.0", 3) == 0) {
|
||||
/*
|
||||
* Either we couldn't find out what kernel release
|
||||
* this is, or it's a 2.0[.x] kernel.
|
||||
*
|
||||
* In the 2.0[.x] kernel, a "recvfrom()" on
|
||||
* a SOCK_PACKET socket, with MSG_TRUNC set, will
|
||||
* return the number of bytes read, so if we pass
|
||||
* a length based on the snapshot length, it'll
|
||||
* return the number of bytes from the packet
|
||||
* copied to userland, not the actual length
|
||||
* of the packet.
|
||||
*
|
||||
* This means that, for example, the IP dissector
|
||||
* in tcpdump will get handed a packet length less
|
||||
* than the length in the IP header, and will
|
||||
* complain about "truncated-ip".
|
||||
*
|
||||
* So we don't bother trying to copy from the
|
||||
* kernel only the bytes in which we're interested,
|
||||
* but instead copy them all, just as the older
|
||||
* versions of libpcap for Linux did.
|
||||
*
|
||||
* The buffer therefore needs to be big enough to
|
||||
* hold the largest packet we can get from this
|
||||
* device. Unfortunately, we can't get the MRU
|
||||
* of the network; we can only get the MTU. The
|
||||
* MTU may be too small, in which case a packet larger
|
||||
* than the buffer size will be truncated *and* we
|
||||
* won't get the actual packet size.
|
||||
*
|
||||
* However, if the snapshot length is larger than
|
||||
* the buffer size based on the MTU, we use the
|
||||
* snapshot length as the buffer size, instead;
|
||||
* this means that with a sufficiently large snapshot
|
||||
* length we won't artificially truncate packets
|
||||
* to the MTU-based size.
|
||||
*
|
||||
* This mess just one of many problems with packet
|
||||
* capture on 2.0[.x] kernels; you really want a
|
||||
* 2.2[.x] or later kernel if you want packet capture
|
||||
* to work well.
|
||||
*/
|
||||
mtu = iface_get_mtu(handle->fd, device, ebuf);
|
||||
if (mtu == -1)
|
||||
break;
|
||||
handle->bufsize = MAX_LINKHEADER_SIZE + mtu;
|
||||
if (handle->bufsize < handle->snapshot)
|
||||
handle->bufsize = handle->snapshot;
|
||||
} else {
|
||||
/*
|
||||
* This is a 2.2[.x] or later kernel.
|
||||
*
|
||||
* We can safely pass "recvfrom()" a byte count
|
||||
* based on the snapshot length.
|
||||
*/
|
||||
handle->bufsize = handle->snapshot;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default value for offset to align link-layer payload
|
||||
* on a 4-byte boundary.
|
||||
|
|
Reference in New Issue