dect
/
libpcap
Archived
13
0
Fork 0

NetBSD support for multiple data link types on an interface, from David

Young <dyoung@ojctech.com>, with some minor changes by Jason R.  Thorpe
<thorpej@netbsd.org>, and further changes by me to support it on BPF
systems lacking BIOCGDLTLIST and other platforms lacking an equivalent
feature.

Update Jason Thorpe's e-mail address (Zembu is going away, if it hasn't
done so already).

Add APIs to map DLT names to DLT values and vice versa.
This commit is contained in:
guy 2002-12-19 09:05:45 +00:00
parent 1e574aa6fd
commit 482fa426bc
14 changed files with 364 additions and 16 deletions

View File

@ -21,6 +21,7 @@ Additional people who have contributed patches:
Chris Pepper <pepper@mail.reppep.com>
Darren Reed <darrenr@reed.wattle.id.au>
David Kaelbling <drk@sgi.com>
David Young <dyoung@ojctech.com>
Don Ebright <Don.Ebright@compuware.com>
Franz Schaefer <schaefer@mond.at>
Gianluca Varenni <varenni@netgroup-serv.polito.it>
@ -31,7 +32,7 @@ Additional people who have contributed patches:
Hyung Sik Yoon <hsyn@kr.ibm.com>
Igor Khristophorov <igor@atdot.org>
Jan-Philip Velders <jpv@veldersjes.net>
Jason R. Thorpe <thorpej@zembu.com>
Jason R. Thorpe <thorpej@netbsd.org>
Javier Achirica <achirica@ttd.net>
Jefferson Ogata <jogata@nodc.noaa.gov>
John Bankier <jbankier@rainfinity.com>

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.53 2002-10-08 07:18:08 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.54 2002-12-19 09:05:45 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -229,9 +229,16 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
int fd;
struct ifreq ifr;
struct bpf_version bv;
#ifdef BIOCGDLTLIST
struct bpf_dltlist bdl;
#endif
u_int v;
pcap_t *p;
#ifdef BIOCGDLTLIST
bzero(&bdl, sizeof(bdl));
#endif
p = (pcap_t *)malloc(sizeof(*p));
if (p == NULL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
@ -348,6 +355,37 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
#endif
p->linktype = v;
#ifdef BIOCGDLTLIST
/*
* We know the default link type -- now determine all the DLTs
* this interface supports. If this fails with EINVAL, it's
* not fatal; we just don't get to use the feature later.
*/
if (ioctl(fd, BIOCGDLTLIST, (caddr_t) &bdl) == 0) {
bdl.bfl_list = (u_int *) malloc(sizeof(u_int) * bdl.bfl_len);
if (bdl.bfl_list == NULL) {
(void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
goto bad;
}
if (ioctl(fd, BIOCGDLTLIST, (caddr_t) &bdl) < 0) {
(void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
"BIOCGDLTLIST: %s", pcap_strerror(errno));
goto bad;
}
p->dlt_count = bdl.bfl_len;
p->dlt_list = bdl.bfl_list;
} else {
if (errno != EINVAL) {
(void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
"BIOCGDLTLIST: %s", pcap_strerror(errno));
goto bad;
}
}
#endif
/* set timeout */
if (to_ms != 0) {
/*
@ -446,6 +484,10 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
return (p);
bad:
(void)close(fd);
#ifdef BIOCGDLTLIST
if (bdl.bfl_list != NULL)
free(bdl.bfl_list);
#endif
free(p);
return (NULL);
}
@ -477,3 +519,16 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp)
}
return (0);
}
int
pcap_set_datalink_platform(pcap_t *p, int dlt)
{
#ifdef BIOCSDLT
if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
(void) snprintf(p->errbuf, sizeof(p->errbuf),
"Cannot set DLT %d: %s", dlt, strerror(errno));
return (-1);
}
#endif
return (0);
}

View File

@ -38,7 +38,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.79 2002-07-11 09:06:37 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.80 2002-12-19 09:05:46 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -1444,3 +1444,9 @@ dlpi_kread(register int fd, register off_t addr,
return (cc);
}
#endif
int
pcap_set_datalink_platform(pcap_t *p, int dlt)
{
return (0);
}

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.40 2002-08-20 15:33:31 risso Exp $ (LBL)
* @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.41 2002-12-19 09:05:46 guy Exp $ (LBL)
*/
#ifndef pcap_int_h
@ -115,6 +115,8 @@ struct pcap {
struct bpf_program fcode;
char errbuf[PCAP_ERRBUF_SIZE + 1];
int dlt_count;
int *dlt_list;
};
/*
@ -209,6 +211,15 @@ int sf_next_packet(pcap_t *, struct pcap_pkthdr *, u_char *, int);
strlen((y)))
#endif
/*
* Internal interface for "pcap_set_datalink()". Attempts to set the
* link-layer type to the specified type; if that fails, returns -1.
* (On platforms that don't support setting it at all, this can just
* return 0 - on those platforms, "pcap_set_datalink()" has already
* checked whether the DLT_ value is the one the device supports.
*/
int pcap_set_datalink_platform(pcap_t *, int);
/*
* Internal interfaces for "pcap_findalldevs()".
*

View File

@ -26,7 +26,7 @@
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.85 2002-10-18 08:46:14 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.86 2002-12-19 09:05:46 guy Exp $ (LBL)";
#endif
/*
@ -1934,3 +1934,9 @@ reset_kernel_filter(pcap_t *handle)
&dummy, sizeof(dummy));
}
#endif
int
pcap_set_datalink_platform(pcap_t *p, int dlt)
{
return (0);
}

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.42 2002-07-11 09:06:39 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.43 2002-12-19 09:05:47 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -271,3 +271,9 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp)
return (-1);
return (0);
}
int
pcap_set_datalink_platform(pcap_t *p, int dlt)
{
return (0);
}

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.14 2002-07-11 09:06:41 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.15 2002-12-19 09:05:47 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -78,3 +78,9 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp)
return (-1);
return (0);
}
int
pcap_set_datalink_platform(pcap_t *p, int dlt)
{
return (0);
}

View File

@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.69 2002-08-03 20:22:27 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.70 2002-12-19 09:05:47 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -435,3 +435,9 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp)
fprintf(stderr, "tcpdump: Filtering in user process\n");
return (0);
}
int
pcap_set_datalink_platform(pcap_t *p, int dlt)
{
return (0);
}

View File

@ -25,7 +25,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.58 2002-08-25 21:13:52 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.59 2002-12-19 09:05:47 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -329,3 +329,9 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp)
return (-1);
return (0);
}
int
pcap_set_datalink_platform(pcap_t *p, int dlt)
{
return (0);
}

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.37 2002-07-30 07:48:20 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.38 2002-12-19 09:05:48 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -305,3 +305,9 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp)
return (-1);
return (0);
}
int
pcap_set_datalink_platform(pcap_t *p, int dlt)
{
return (0);
}

View File

@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.3 2002-11-11 10:34:06 risso Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.4 2002-12-19 09:05:48 guy Exp $ (LBL)";
#endif
#include <pcap-int.h>
@ -322,4 +322,8 @@ pcap_setmintocopy(pcap_t *p, int size)
return 0;
}
int
pcap_set_datalink_platform(pcap_t *p, int dlt)
{
return (0);
}

43
pcap.3
View File

@ -1,4 +1,4 @@
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.40 2002-12-17 07:32:55 guy Exp $
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.41 2002-12-19 09:05:48 guy Exp $
.\"
.\" Copyright (c) 1994, 1996, 1997
.\" The Regents of the University of California. All rights reserved.
@ -82,6 +82,10 @@ u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
.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);
int pcap_datalink_name_to_val(const char *name);
const char *pcap_datalink_val_to_name(int dlt);
int pcap_snapshot(pcap_t *p)
int pcap_is_swapped(pcap_t *p)
int pcap_major_version(pcap_t *p)
@ -765,10 +769,45 @@ a 2-byte VCI field, in network byte order.
.B DLT_IP_OVER_FC
RFC 2625 IP-over-Fibre Channel, with the link-layer header being the
Network_Header as described in that RFC.
.RE
.PP
.B pcap_list_datalinks()
is used to get a list of the supported data link types of the interface
associated with the pcap descriptor.
.B pcap_list_datalinks()
allocates an array to hold the list and sets
.IR *dlt_buf .
The caller is responsible for freeing the array.
.B \-1
is returned on failure;
otherwise, the number of data link types in the array is returned.
.PP
.B pcap_set_datalink()
is used to set the current data link type of the pcap descriptor
to the type specified by
.IR dlt .
.B \-1
is returned on failure.
.PP
.B pcap_datalink_name_to_val()
translates a data link type name, which is a
.B DLT_
name with the
.B DLT_
removed, to the corresponding data link type value. The translation
is case-insensitive.
is used to set the current data link type of the pcap descriptor
NULL is returned on failure.
.PP
.B pcap_datalink_val_to_name()
translates a data link type value to the corresponding data link type
name.
.B \-1
is returned on failure.
.PP
.B pcap_snapshot()
returns the snapshot length specified when
.B pcap_open_live
.B pcap_open_live()
was called.
.PP
.B pcap_is_swapped()

194
pcap.c
View File

@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.41 2002-08-02 03:44:21 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.42 2002-12-19 09:05:48 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -128,6 +128,196 @@ pcap_datalink(pcap_t *p)
return (p->linktype);
}
int
pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
{
if (p->dlt_count == 0) {
/*
* We couldn't fetch the list of DLTs, which means
* this platform doesn't support changing the
* DLT for an interface. Return a list of DLTs
* containing only the DLT this device supports.
*/
*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
if (*dlt_buffer == NULL) {
(void)snprintf(p->errbuf, sizeof(p->errbuf),
"malloc: %s", pcap_strerror(errno));
return (-1);
}
**dlt_buffer = p->linktype;
return (1);
} else {
*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer) * p->dlt_count);
if (*dlt_buffer == NULL) {
(void)snprintf(p->errbuf, sizeof(p->errbuf),
"malloc: %s", pcap_strerror(errno));
return (-1);
}
(void)memcpy(*dlt_buffer, p->dlt_list,
sizeof(**dlt_buffer) * p->dlt_count);
return (p->dlt_count);
}
}
int
pcap_set_datalink(pcap_t *p, int dlt)
{
int i;
const char *dlt_name;
if (p->dlt_count == 0) {
/*
* We couldn't fetch the list of DLTs, which means
* this platform doesn't support changing the
* DLT for an interface. Check whether the new
* DLT is the one this interface supports.
*/
if (p->linktype != dlt)
goto unsupported;
/*
* It is, so there's nothing we need to do here.
*/
return (0);
}
for (i = 0; i < p->dlt_count; i++)
if (p->dlt_list[i] == dlt)
break;
if (i >= p->dlt_count)
goto unsupported;
if (pcap_set_datalink_platform(p, dlt) == -1)
return (-1);
p->linktype = dlt;
return (0);
unsupported:
dlt_name = pcap_datalink_val_to_name(dlt);
if (dlt_name != NULL) {
(void) snprintf(p->errbuf, sizeof(p->errbuf),
"%s is not one of the DLTs supported by this device",
dlt_name);
} else {
(void) snprintf(p->errbuf, sizeof(p->errbuf),
"DLT %d is not one of the DLTs supported by this device",
dlt);
}
return (-1);
}
struct dlt_choice {
const char *name;
int dlt;
};
#define DLT_CHOICE(code) { #code, code }
#define DLT_CHOICE_SENTINEL { NULL, 0 }
static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(DLT_ARCNET),
DLT_CHOICE(DLT_EN10MB),
DLT_CHOICE(DLT_SLIP),
DLT_CHOICE(DLT_SLIP_BSDOS),
DLT_CHOICE(DLT_NULL),
DLT_CHOICE(DLT_LOOP),
DLT_CHOICE(DLT_PPP),
DLT_CHOICE(DLT_C_HDLC),
DLT_CHOICE(DLT_PPP_SERIAL),
DLT_CHOICE(DLT_PPP_ETHER),
DLT_CHOICE(DLT_PPP_BSDOS),
DLT_CHOICE(DLT_FDDI),
DLT_CHOICE(DLT_IEEE802),
DLT_CHOICE(DLT_IEEE802_11),
DLT_CHOICE(DLT_PRISM_HEADER),
DLT_CHOICE(DLT_IEEE802_11_RADIO),
DLT_CHOICE(DLT_ATM_RFC1483),
DLT_CHOICE(DLT_ATM_CLIP),
DLT_CHOICE(DLT_SUNATM),
DLT_CHOICE(DLT_RAW),
DLT_CHOICE(DLT_LINUX_SLL),
DLT_CHOICE(DLT_LTALK),
DLT_CHOICE(DLT_IP_OVER_FC),
DLT_CHOICE(DLT_FRELAY),
DLT_CHOICE_SENTINEL
};
/*
* This array is designed for mapping upper and lower case letter
* together for a case independent comparison. The mappings are
* based upon ascii character sequences.
*/
static const u_char charmap[] = {
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
'\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
'\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
};
static int
pcap_strcasecmp(const char *s1, const char *s2)
{
register const u_char *cm = charmap,
*us1 = (u_char *)s1,
*us2 = (u_char *)s2;
while (cm[*us1] == cm[*us2++])
if (*us1++ == '\0')
return(0);
return (cm[*us1] - cm[*--us2]);
}
int
pcap_datalink_name_to_val(const char *name)
{
int i;
for (i = 0; dlt_choices[i].name != NULL; i++) {
if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1,
name) == 0)
return (dlt_choices[i].dlt);
}
return (-1);
}
const char *
pcap_datalink_val_to_name(int dlt)
{
int i;
for (i = 0; dlt_choices[i].name != NULL; i++) {
if (dlt_choices[i].dlt == dlt)
return (dlt_choices[i].name + sizeof("DLT_") - 1);
}
return (NULL);
}
int
pcap_snapshot(pcap_t *p)
{
@ -226,6 +416,8 @@ pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
#else
int newtimeout;
#endif
if (p->dlt_list != NULL)
free(p->dlt_list);
if (p->sf.rfile != NULL) {
/*

6
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.37 2002-08-02 03:44:21 guy Exp $ (LBL)
* @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.38 2002-12-19 09:05:49 guy Exp $ (LBL)
*/
#ifndef lib_pcap_h
@ -188,6 +188,10 @@ int pcap_compile_nopcap(int, int, struct bpf_program *,
char *, int, bpf_u_int32);
void pcap_freecode(struct bpf_program *);
int pcap_datalink(pcap_t *);
int pcap_list_datalinks(pcap_t *, int **);
int pcap_set_datalink(pcap_t *, int);
int pcap_datalink_name_to_val(const char *);
const char *pcap_datalink_val_to_name(int);
int pcap_snapshot(pcap_t *);
int pcap_is_swapped(pcap_t *);
int pcap_major_version(pcap_t *);