dect
/
libpcap
Archived
13
0
Fork 0

Have "map_arphrd_to_dlt()" take a flag indicating whether it's OK to

return DLT_LINUX_SLL or not, and, if that flag is false, for those
interface types where we'd used DLT_LINUX_SLL, pick a DLT_ type that
works as well as possible in raw mode, or fail.

Pass 1 as that flag if we're using a PF_PACKET socket; pass 0 as that
flag if we're using a PF_INET/SOCK_PACKET socket.

For PF_INET/SOCK_PACKET sockets, try to get the link-layer type and map
it to a DLT_ value *before* turning promiscuous mode on, so that we
don't try to put the interface into promiscuous mode unless we know we
can handle its link-layer type (and thus that we can use the interface).
This commit is contained in:
guy 2002-02-10 00:05:14 +00:00
parent e1f3b3be1a
commit bb0918aeef
1 changed files with 61 additions and 34 deletions

View File

@ -26,7 +26,7 @@
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.76 2002-02-05 05:47:14 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.77 2002-02-10 00:05:14 guy Exp $ (LBL)";
#endif
/*
@ -168,7 +168,7 @@ typedef int socklen_t;
/*
* Prototypes for internal functions
*/
static void map_arphrd_to_dlt(pcap_t *, int);
static void map_arphrd_to_dlt(pcap_t *, int, int);
static int live_open_old(pcap_t *, char *, int, int, char *);
static int live_open_new(pcap_t *, char *, int, int, char *);
static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
@ -861,10 +861,14 @@ pcap_setfilter(pcap_t *handle, struct bpf_program *filter)
* will be aligned on a 4-byte boundary when capturing packets).
* (If the offset isn't set here, it'll be 0; add code as appropriate
* for cases where it shouldn't be 0.)
*
* If "cooked_ok" is non-zero, we can use DLT_LINUX_SLL and capture
* in cooked mode; otherwise, we can't use cooked mode, so we have
* to pick some type that works in raw mode, or fail.
*
* Sets the link type to -1 if unable to map the type.
*/
static void map_arphrd_to_dlt(pcap_t *handle, int arptype)
static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok)
{
switch (arptype) {
@ -949,9 +953,13 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype)
* Both of those are a nuisance - and, at least on systems
* that support PF_PACKET sockets, we don't have to put
* up with those nuisances; instead, we can just capture
* in cooked mode. That's what we'll do.
* in cooked mode. That's what we'll do, if we can.
* Otherwise, we'll just fail.
*/
handle->linktype = DLT_LINUX_SLL;
if (cooked_ok)
handle->linktype = DLT_LINUX_SLL;
else
handle->linktype = -1;
break;
#ifndef ARPHRD_IEEE80211 /* From Linux 2.4.6 */
@ -981,9 +989,34 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype)
* oddball link-layer headers particular packets have).
*
* As such, we just punt, and run all PPP interfaces
* in cooked mode.
* in cooked mode, if we can; otherwise, we just treat
* it as DLT_RAW, for now - if somebody needs to capture,
* on a 2.0[.x] kernel, on PPP devices that supply a
* link-layer header, they'll have to add code here to
* map to the appropriate DLT_ type (possibly adding a
* new DLT_ type, if necessary).
*/
handle->linktype = DLT_LINUX_SLL;
if (cooked_ok)
handle->linktype = DLT_LINUX_SLL;
else {
/*
* XXX - handle ISDN types here? We can't fall
* back on cooked sockets, so we'd have to
* figure out from the device name what type of
* link-layer encapsulation it's using, and map
* that to an appropriate DLT_ value, meaning
* we'd map "isdnN" devices to DLT_RAW (they
* supply raw IP packets with no link-layer
* header) and "isdY" devices to a new DLT_I4L_IP
* type that has only an Ethernet packet type as
* a link-layer header.
*
* But sometimes we seem to get random crap
* in the link-layer header when capturing on
* ISDN devices....
*/
handle->linktype = DLT_RAW;
}
break;
#ifndef ARPHRD_HDLC
@ -1089,7 +1122,7 @@ live_open_new(pcap_t *handle, char *device, int promisc,
arptype = iface_get_arptype(sock_fd, device, ebuf);
if (arptype == -1)
break;
map_arphrd_to_dlt(handle, arptype);
map_arphrd_to_dlt(handle, arptype, 1);
if (handle->linktype == -1 ||
handle->linktype == DLT_LINUX_SLL ||
(handle->linktype == DLT_EN10MB &&
@ -1389,7 +1422,26 @@ live_open_old(pcap_t *handle, char *device, int promisc,
if (iface_bind_old(sock_fd, device, ebuf) == -1)
break;
/* Go to promisc mode */
/*
* Try to get the link-layer type.
*/
arptype = iface_get_arptype(sock_fd, device, ebuf);
if (arptype == -1)
break;
/*
* Try to find the DLT_ type corresponding to that
* link-layer type.
*/
map_arphrd_to_dlt(handle, arptype, 0);
if (handle->linktype == -1) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"unknown arptype %d", arptype);
break;
}
/* Go to promisc mode if requested */
if (promisc) {
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
@ -1443,12 +1495,6 @@ live_open_old(pcap_t *handle, char *device, int promisc,
}
}
/* All done - fill in the pcap handle */
arptype = iface_get_arptype(sock_fd, device, ebuf);
if (arptype == -1)
break;
/* Save the socket FD in the pcap structure */
handle->fd = sock_fd;
@ -1459,25 +1505,6 @@ live_open_old(pcap_t *handle, char *device, int promisc,
*/
handle->offset = 0;
/*
* XXX - handle ISDN types here? We can't fall back on
* cooked sockets, so we'd have to figure out from the
* device name what type of link-layer encapsulation
* it's using, and map that to an appropriate DLT_
* value, meaning we'd map "isdnN" devices to DLT_RAW
* (they supply raw IP packets with no link-layer
* header) and "isdY" devices to a new DLT_I4L_IP
* type that has only an Ethernet packet type as
* a link-layer header.
*/
map_arphrd_to_dlt(handle, arptype);
if (handle->linktype == -1 ||
handle->linktype == DLT_LINUX_SLL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"interface type of %s not supported", device);
break;
}
return 1;
} while (0);