From 482fa426bca50908c3739ba8b0539398dc01c9ae Mon Sep 17 00:00:00 2001 From: guy Date: Thu, 19 Dec 2002 09:05:45 +0000 Subject: NetBSD support for multiple data link types on an interface, from David Young , with some minor changes by Jason R. Thorpe , 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. --- CREDITS | 3 +- pcap-bpf.c | 57 +++++++++++++++++- pcap-dlpi.c | 8 ++- pcap-int.h | 13 +++- pcap-linux.c | 8 ++- pcap-nit.c | 8 ++- pcap-null.c | 8 ++- pcap-pf.c | 8 ++- pcap-snit.c | 8 ++- pcap-snoop.c | 8 ++- pcap-win32.c | 8 ++- pcap.3 | 43 ++++++++++++- pcap.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- pcap.h | 6 +- 14 files changed, 364 insertions(+), 16 deletions(-) diff --git a/CREDITS b/CREDITS index 632974f..8b202b8 100644 --- a/CREDITS +++ b/CREDITS @@ -21,6 +21,7 @@ Additional people who have contributed patches: Chris Pepper Darren Reed David Kaelbling + David Young Don Ebright Franz Schaefer Gianluca Varenni @@ -31,7 +32,7 @@ Additional people who have contributed patches: Hyung Sik Yoon Igor Khristophorov Jan-Philip Velders - Jason R. Thorpe + Jason R. Thorpe Javier Achirica Jefferson Ogata John Bankier diff --git a/pcap-bpf.c b/pcap-bpf.c index 60caac6..32a21c7 100644 --- a/pcap-bpf.c +++ b/pcap-bpf.c @@ -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); +} diff --git a/pcap-dlpi.c b/pcap-dlpi.c index 854aa2b..3f29a27 100644 --- a/pcap-dlpi.c +++ b/pcap-dlpi.c @@ -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); +} diff --git a/pcap-int.h b/pcap-int.h index e66a94b..a5205a1 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -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()". * diff --git a/pcap-linux.c b/pcap-linux.c index 00bd29f..2e155f3 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -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); +} diff --git a/pcap-nit.c b/pcap-nit.c index 8407cb3..5029bd7 100644 --- a/pcap-nit.c +++ b/pcap-nit.c @@ -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); +} diff --git a/pcap-null.c b/pcap-null.c index 0c2183d..a8e2630 100644 --- a/pcap-null.c +++ b/pcap-null.c @@ -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); +} diff --git a/pcap-pf.c b/pcap-pf.c index d5085ff..22b22c2 100644 --- a/pcap-pf.c +++ b/pcap-pf.c @@ -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); +} diff --git a/pcap-snit.c b/pcap-snit.c index 359c4ad..2131ea0 100644 --- a/pcap-snit.c +++ b/pcap-snit.c @@ -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); +} diff --git a/pcap-snoop.c b/pcap-snoop.c index 2d81190..f7aaff1 100644 --- a/pcap-snoop.c +++ b/pcap-snoop.c @@ -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); +} diff --git a/pcap-win32.c b/pcap-win32.c index e076877..18001d5 100644 --- a/pcap-win32.c +++ b/pcap-win32.c @@ -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 @@ -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); +} diff --git a/pcap.3 b/pcap.3 index 517621d..8036e69 100644 --- a/pcap.3 +++ b/pcap.3 @@ -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() diff --git a/pcap.c b/pcap.c index 042687a..41e2c1b 100644 --- a/pcap.c +++ b/pcap.c @@ -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) { /* diff --git a/pcap.h b/pcap.h index 8e8e623..fea5dde 100644 --- a/pcap.h +++ b/pcap.h @@ -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 *); -- cgit v1.2.3