Hi,
here is a patch I made to libpcap, permitting zero copy by allowing the
calling application to specify it's own allocation/freeing function for
the packet buffer, and the pcap header.
This patch was done in a way that it won't break the existing libpcap
API (except for the pcap_next function, but I could simply remove the
modification here and move them to pcap_next_ex, which is more
appropriate and would avoid API breakage for this function).
This patch allow application that need to keep track of packet to avoid
making a copy of the pcap buffer.
The change might be a little complicated to understand because we have
to deal with a number of issues: for example some of the pcap OS
dependant packet reading layer might put several packet in the same
buffer, and that's why pcap_header was modifier to hold a refcount.
I'm maintaining my own version of libpcap, kept in sync with this patch.
Seeing the new pcap_next_ex function within libpcap 0.8, that seemed
related to what I am doing with this patch (but which in fact is not
related at all), I just thought I would send this patch to the list to
know if :
- are people interested by the inclusion of this patch ?
- does people feel it should be done another way ?
It's really a lost of time to have to maintain a separate version of the
patch and keep it in sync with every released pcap version, so I'm
looking forward at this being included in the pcap main repository.
I'm looking forward to hearing from you,
--
Yoann Vandoorselaere <[EMAIL PROTECTED]>
diff -uprN libpcap-0.7.2/gencode.c libpcap/gencode.c
--- libpcap-0.7.2/gencode.c 2003-02-26 07:45:31.000000000 +0100
+++ libpcap/gencode.c 2003-10-05 23:30:22.000000000 +0200
@@ -283,7 +283,7 @@ int no_optimize;
int
pcap_compile(pcap_t *p, struct bpf_program *program,
- char *buf, int optimize, bpf_u_int32 mask)
+ const char *buf, int optimize, bpf_u_int32 mask)
{
extern int n_errors;
int len;
diff -uprN libpcap-0.7.2/gencode.h libpcap/gencode.h
--- libpcap-0.7.2/gencode.h 2001-05-10 16:48:02.000000000 +0200
+++ libpcap/gencode.h 2003-10-05 23:30:22.000000000 +0200
@@ -203,7 +203,7 @@ char *sdup(const char *);
struct bpf_insn *icode_to_fcode(struct block *, int *);
int pcap_parse(void);
-void lex_init(char *);
+void lex_init(const char *);
void lex_cleanup(void);
void sappend(struct slist *, struct slist *);
diff -uprN libpcap-0.7.2/inet.c libpcap/inet.c
--- libpcap-0.7.2/inet.c 2003-02-26 07:45:31.000000000 +0100
+++ libpcap/inet.c 2003-10-05 23:30:22.000000000 +0200
@@ -995,7 +995,7 @@ pcap_lookupdev(errbuf)
int
pcap_lookupnet(device, netp, maskp, errbuf)
- register char *device;
+ register const char *device;
register bpf_u_int32 *netp, *maskp;
register char *errbuf;
{
diff -uprN libpcap-0.7.2/pcap-bpf.c libpcap/pcap-bpf.c
--- libpcap-0.7.2/pcap-bpf.c 2003-02-26 07:45:31.000000000 +0100
+++ libpcap/pcap-bpf.c 2003-10-05 23:30:22.000000000 +0200
@@ -95,12 +95,17 @@ int
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
int cc;
- int n = 0;
+ int n = 0, ret;
register u_char *bp, *ep;
+ struct pcap_pkthdr *pcap_header;
- again:
cc = p->cc;
if (p->cc == 0) {
+ ret = pcap_buffer_lock(p);
+ if ( ret < 0 )
+ return -1;
+
+ again:
cc = read(p->fd, (char *)p->buffer, p->bufsize);
if (cc < 0) {
/* Don't choke when we get ptraced */
@@ -110,6 +115,7 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
goto again;
case EWOULDBLOCK:
+ pcap_buffer_release(p);
return (0);
#if defined(sun) && !defined(BSD)
/*
@@ -128,6 +134,7 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
}
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
pcap_strerror(errno));
+ pcap_buffer_release(p);
return (-1);
}
bp = p->buffer;
@@ -160,16 +167,34 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
*/
bhp->bh_tstamp.tv_usec = bhp->bh_tstamp.tv_usec/1000;
#endif
- (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
+
+ pcap_header = pcap_header_new(p);
+ if ( ! pcap_header ) {
+ pcap_buffer_release(p);
+ return -1;
+ }
+
+ pcap_header->ts.tv_sec = bhp->bh_tstamp.tv_sec;
+ pcap_header->ts.tv_usec = bhp->bh_tstamp.tv_usec;
+ pcap_header->caplen = caplen;
+ pcap_header->len = bhp->bh_datalen;
+
+ (*callback)(user, pcap_header, bp + hdrlen);
+
bp += BPF_WORDALIGN(caplen + hdrlen);
if (++n >= cnt && cnt > 0) {
p->bp = bp;
p->cc = ep - bp;
- return (n);
+
+ if ( p->cc == 0 )
+ pcap_buffer_release(p);
+
+ return (n);
}
}
#undef bhp
p->cc = 0;
+ pcap_buffer_release(p);
return (n);
}
@@ -199,7 +224,7 @@ bpf_open(pcap_t *p, char *errbuf)
}
pcap_t *
-pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
int fd;
struct ifreq ifr;
diff -uprN libpcap-0.7.2/pcap-dlpi.c libpcap/pcap-dlpi.c
--- libpcap-0.7.2/pcap-dlpi.c 2003-02-26 07:45:31.000000000 +0100
+++ libpcap/pcap-dlpi.c 2003-10-05 23:56:28.000000000 +0200
@@ -171,11 +171,15 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
#endif
int flags;
struct strbuf data;
- struct pcap_pkthdr pkthdr;
+ struct pcap_pkthdr *pkthdr;
flags = 0;
cc = p->cc;
if (cc == 0) {
+ ret = pcap_buffer_lock(p);
+ if ( ret < 0 )
+ return -1;
+
data.buf = (char *)p->buffer + p->offset;
data.maxlen = p->bufsize;
data.len = 0;
@@ -188,7 +192,10 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
}
strlcpy(p->errbuf, pcap_strerror(errno),
sizeof(p->errbuf));
- return (-1);
+
+ pcap_buffer_release(p);
+
+ return (-1);
}
cc = data.len;
} while (cc == 0);
@@ -222,21 +229,34 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
#endif
++p->md.stat.ps_recv;
if (bpf_filter(fcode, pk, origlen, caplen)) {
+
+ pkthdr = pcap_header_new(p);
+ if ( ! pkthdr ) {
+ pcap_buffer_release(p);
+ return -1;
+ }
+
#ifdef HAVE_SYS_BUFMOD_H
- pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
- pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
+ pkthdr->ts.tv_sec = sbp->sbh_timestamp.tv_sec;
+ pkthdr->ts.tv_usec = sbp->sbh_timestamp.tv_usec;
#else
- (void)gettimeofday(&pkthdr.ts, NULL);
+ (void)gettimeofday(&pkthdr->ts, NULL);
#endif
- pkthdr.len = origlen;
- pkthdr.caplen = caplen;
+ pkthdr->len = origlen;
+ pkthdr->caplen = caplen;
/* Insure caplen does not exceed snapshot */
- if (pkthdr.caplen > p->snapshot)
- pkthdr.caplen = p->snapshot;
- (*callback)(user, &pkthdr, pk);
- if (++n >= cnt && cnt >= 0) {
+ if (pkthdr->caplen > p->snapshot)
+ pkthdr->caplen = p->snapshot;
+
+ (*callback)(user, pkthdr, pk);
+
+ if (++n >= cnt && cnt >= 0) {
p->cc = ep - bp;
p->bp = bp;
+
+ if ( p->cc == 0 )
+ pcap_buffer_release(p);
+
return (n);
}
}
@@ -244,11 +264,13 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
}
#endif
p->cc = 0;
+ pcap_buffer_release(p);
+
return (n);
}
pcap_t *
-pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
register char *cp;
register pcap_t *p;
diff -uprN libpcap-0.7.2/pcap-int.h libpcap/pcap-int.h
--- libpcap-0.7.2/pcap-int.h 2001-08-24 09:46:52.000000000 +0200
+++ libpcap/pcap-int.h 2003-10-05 23:30:22.000000000 +0200
@@ -117,6 +117,23 @@ struct pcap_timeval {
bpf_int32 tv_usec; /* microseconds */
};
+
+ struct buffer_head {
+ int refcount;
+ unsigned char buf[0];
+ };
+
+
+ struct pcap_ref_pkthdr
+ {
+ struct timeval ts; /* time stamp */
+ bpf_u_int32 caplen; /* length of portion present */
+ bpf_u_int32 len; /* length this packet (off wire) */
+ struct buffer_head *bhead;
+ };
+
+
+
/*
* How a `pcap_pkthdr' is actually stored in the dumpfile.
*
@@ -175,6 +192,11 @@ int yylex(void);
#endif
/* XXX should these be in pcap.h? */
+
+ int pcap_buffer_lock(pcap_t *p);
+ void pcap_buffer_release(pcap_t *p);
+ struct pcap_pkthdr *pcap_header_new(pcap_t *p);
+
int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *);
diff -uprN libpcap-0.7.2/pcap-linux.c libpcap/pcap-linux.c
--- libpcap-0.7.2/pcap-linux.c 2003-02-26 07:45:32.000000000 +0100
+++ libpcap/pcap-linux.c 2003-10-05 23:31:06.000000000 +0200
@@ -179,8 +179,8 @@ typedef int socklen_t;
* Prototypes for internal functions
*/
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 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_packet(pcap_t *, pcap_handler, u_char *);
/*
@@ -219,7 +219,7 @@ static struct sock_fprog total_fcode
* See also pcap(3).
*/
pcap_t *
-pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
pcap_t *handle;
int mtu;
@@ -426,8 +426,12 @@ pcap_read_packet(pcap_t *handle, pcap_ha
struct sockaddr from;
#endif
socklen_t fromlen;
- int packet_len, caplen;
- struct pcap_pkthdr pcap_header;
+ int packet_len, caplen, ret;
+ struct pcap_pkthdr *pcap_header;
+
+ ret = pcap_buffer_lock(handle);
+ if ( ret < 0 )
+ return -1;
#ifdef HAVE_PF_PACKET_SOCKETS
/*
@@ -460,12 +464,14 @@ pcap_read_packet(pcap_t *handle, pcap_ha
/* Check if an error occured */
if (packet_len == -1) {
- if (errno == EAGAIN)
+ if (errno == EAGAIN) {
+ pcap_buffer_release(handle);
return 0; /* no packet there */
- else {
+ } else {
snprintf(handle->errbuf, sizeof(handle->errbuf),
"recvfrom: %s", pcap_strerror(errno));
- return -1;
+ pcap_buffer_release(handle);
+ return -1;
}
}
@@ -481,8 +487,10 @@ pcap_read_packet(pcap_t *handle, pcap_ha
*/
if (!handle->md.sock_packet &&
from.sll_ifindex == handle->md.lo_ifindex &&
- from.sll_pkttype == PACKET_OUTGOING)
+ from.sll_pkttype == PACKET_OUTGOING) {
+ pcap_buffer_release(handle);
return 0;
+ }
#endif
#ifdef HAVE_PF_PACKET_SOCKETS
@@ -585,19 +593,28 @@ pcap_read_packet(pcap_t *handle, pcap_ha
packet_len, caplen) == 0)
{
/* rejected by filter */
+ pcap_buffer_release(handle);
return 0;
}
}
+ pcap_header = pcap_header_new(handle);
+ if ( ! pcap_header ) {
+ pcap_buffer_release(handle);
+ return -1;
+ }
+
/* Fill in our own header data */
- if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
+ if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header->ts) == -1) {
snprintf(handle->errbuf, sizeof(handle->errbuf),
"ioctl: %s", pcap_strerror(errno));
+ pcap_header_free(pcap_header);
+ pcap_buffer_release(handle);
return -1;
}
- pcap_header.caplen = caplen;
- pcap_header.len = packet_len;
+ pcap_header->caplen = caplen;
+ pcap_header->len = packet_len;
/*
* Count the packet.
@@ -635,7 +652,9 @@ pcap_read_packet(pcap_t *handle, pcap_ha
handle->md.stat.ps_recv++;
/* Call the user supplied callback function */
- callback(userdata, &pcap_header, bp);
+ callback(userdata, pcap_header, bp);
+
+ pcap_buffer_release(handle);
return 1;
}
@@ -1096,7 +1115,7 @@ static void map_arphrd_to_dlt(pcap_t *ha
* FIXME: 0 uses to mean success (Sebastian)
*/
static int
-live_open_new(pcap_t *handle, char *device, int promisc,
+live_open_new(pcap_t *handle, const char *device, int promisc,
int to_ms, char *ebuf)
{
#ifdef HAVE_PF_PACKET_SOCKETS
@@ -1450,7 +1469,7 @@ void pcap_close_linux( pcap_t *handle )
* FIXME: 0 uses to mean success (Sebastian)
*/
static int
-live_open_old(pcap_t *handle, char *device, int promisc,
+live_open_old(pcap_t *handle, const char *device, int promisc,
int to_ms, char *ebuf)
{
int sock_fd = -1, arptype;
diff -uprN libpcap-0.7.2/pcap-nit.c libpcap/pcap-nit.c
--- libpcap-0.7.2/pcap-nit.c 2001-12-10 08:14:18.000000000 +0100
+++ libpcap/pcap-nit.c 2003-10-05 23:30:22.000000000 +0200
@@ -202,7 +202,7 @@ nit_setflags(int fd, int promisc, int to
}
pcap_t *
-pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
int fd;
struct sockaddr_nit snit;
diff -uprN libpcap-0.7.2/pcap-pf.c libpcap/pcap-pf.c
--- libpcap-0.7.2/pcap-pf.c 2001-12-10 08:14:19.000000000 +0100
+++ libpcap/pcap-pf.c 2003-10-05 23:30:22.000000000 +0200
@@ -238,7 +238,7 @@ pcap_stats(pcap_t *p, struct pcap_stat *
}
pcap_t *
-pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
pcap_t *p;
short enmode;
diff -uprN libpcap-0.7.2/pcap-snit.c libpcap/pcap-snit.c
--- libpcap-0.7.2/pcap-snit.c 2001-12-10 08:14:20.000000000 +0100
+++ libpcap/pcap-snit.c 2003-10-05 23:30:22.000000000 +0200
@@ -219,7 +219,7 @@ nit_setflags(int fd, int promisc, int to
}
pcap_t *
-pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
struct strioctl si; /* struct for ioctl() */
struct ifreq ifr; /* interface request struct */
diff -uprN libpcap-0.7.2/pcap.c libpcap/pcap.c
--- libpcap-0.7.2/pcap.c 2001-12-29 22:55:32.000000000 +0100
+++ libpcap/pcap.c 2003-10-05 23:30:22.000000000 +0200
@@ -55,6 +55,122 @@ static const char rcsid[] =
#include "pcap-int.h"
+
+
+#define get_buffer_head(ptr, type, member) \
+ ((type *) ((void *) (ptr) - (void *) (& ((type *) 0)->member)))
+
+
+static void *(*alloc_buffer_cb)(size_t size) = NULL;
+static void (*free_buffer_cb)(void *ptr) = NULL;
+
+
+
+int pcap_buffer_lock(pcap_t *p)
+{
+ struct buffer_head *bhead;
+
+ if ( ! alloc_buffer_cb )
+ return 0;
+
+ bhead = alloc_buffer_cb(sizeof(struct buffer_head) + p->bufsize + p->offset);
+ if ( ! bhead ) {
+ snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+
+ bhead->refcount = 1;
+ p->buffer = bhead->buf;
+
+ return 0;
+}
+
+
+
+
+void pcap_buffer_release(pcap_t *p)
+{
+ struct buffer_head *bhead;
+
+ if ( ! alloc_buffer_cb )
+ return;
+
+ bhead = get_buffer_head(p->buffer, struct buffer_head, buf);
+ if ( --bhead->refcount == 0 )
+ free_buffer_cb(bhead);
+
+ p->buffer = NULL;
+}
+
+
+
+
+
+struct pcap_pkthdr *pcap_header_new(pcap_t *p)
+{
+ struct pcap_ref_pkthdr *ref;
+
+ if ( ! alloc_buffer_cb ) {
+ static struct pcap_pkthdr hdr;
+ return &hdr;
+ }
+
+ ref = malloc(sizeof(struct pcap_ref_pkthdr));
+ if ( ! ref ) {
+ snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
+ return NULL;
+ }
+
+ ref->bhead = get_buffer_head(p->buffer, struct buffer_head, buf);
+ ref->bhead->refcount++;
+
+ return (struct pcap_pkthdr *) ref;
+}
+
+
+
+
+void pcap_header_free(const struct pcap_pkthdr *phdr)
+{
+ struct pcap_ref_pkthdr *ref;
+
+ if ( ! alloc_buffer_cb )
+ return;
+
+ ref = (struct pcap_ref_pkthdr *) phdr;
+
+ if ( --ref->bhead->refcount == 0 )
+ free_buffer_cb(ref->bhead);
+
+ free(ref);
+}
+
+
+
+
+void pcap_header_reference(const struct pcap_pkthdr *phdr)
+{
+ struct pcap_ref_pkthdr *ref;
+
+ if ( ! alloc_buffer_cb )
+ return;
+
+ ref = (struct pcap_ref_pkthdr *) phdr;
+ ref->bhead->refcount++;
+}
+
+
+
+
+void pcap_set_alloc_func(pcap_t *p, void *(*alloc)(size_t size), void (*free)(void *ptr))
+{
+ alloc_buffer_cb = alloc;
+ free_buffer_cb = free;
+}
+
+
+
+
int
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
@@ -279,7 +395,7 @@ pcap_close(pcap_t *p)
(void)fclose(p->sf.rfile);
if (p->sf.base != NULL)
free(p->sf.base);
- } else if (p->buffer != NULL)
+ } else if (p->buffer != NULL && ! alloc_buffer_cb )
free(p->buffer);
pcap_freecode(&p->fcode);
diff -uprN libpcap-0.7.2/pcap.h libpcap/pcap.h
--- libpcap-0.7.2/pcap.h 2001-12-09 06:10:03.000000000 +0100
+++ libpcap/pcap.h 2003-10-05 23:30:22.000000000 +0200
@@ -158,9 +158,13 @@ struct pcap_addr {
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
const u_char *);
+ void pcap_header_free(const struct pcap_pkthdr *phdr);
+ void pcap_set_alloc_func(pcap_t *p, void *(*alloc)(size_t size), void (*free)(void *ptr));
+ void pcap_header_reference(const struct pcap_pkthdr *phdr);
+
char *pcap_lookupdev(char *);
-int pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *);
-pcap_t *pcap_open_live(char *, int, int, int, char *);
+int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+pcap_t *pcap_open_live(const char *, int, int, int, char *);
pcap_t *pcap_open_dead(int, int);
pcap_t *pcap_open_offline(const char *, char *);
void pcap_close(pcap_t *);
@@ -175,7 +179,7 @@ int pcap_setnonblock(pcap_t *, int, char
void pcap_perror(pcap_t *, char *);
char *pcap_strerror(int);
char *pcap_geterr(pcap_t *);
-int pcap_compile(pcap_t *, struct bpf_program *, char *, int,
+int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
bpf_u_int32);
int pcap_compile_nopcap(int, int, struct bpf_program *,
char *, int, bpf_u_int32);
diff -uprN libpcap-0.7.2/savefile.c libpcap/savefile.c
--- libpcap-0.7.2/savefile.c 2003-02-26 07:45:32.000000000 +0100
+++ libpcap/savefile.c 2003-10-05 23:30:22.000000000 +0200
@@ -443,6 +443,9 @@ pcap_open_offline(const char *fname, cha
if (p->bufsize < 0)
p->bufsize = BPF_MAXBUFSIZE;
+
+ p->offset = BPF_ALIGNMENT;
+
p->sf.base = (u_char *)malloc(p->bufsize + BPF_ALIGNMENT);
if (p->sf.base == NULL) {
strlcpy(errbuf, "out of swap", PCAP_ERRBUF_SIZE);
@@ -573,26 +576,45 @@ int
pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
struct bpf_insn *fcode = p->fcode.bf_insns;
- int status = 0;
- int n = 0;
+ struct pcap_pkthdr *hdr;
+ int status = 0;
+ int n = 0, ret;
while (status == 0) {
- struct pcap_pkthdr h;
-
- status = sf_next_packet(p, &h, p->buffer, p->bufsize);
+
+ ret = pcap_buffer_lock(p);
+ if ( ret < 0 )
+ return -1;
+
+ hdr = pcap_header_new(p);
+ if ( ! hdr ) {
+ pcap_buffer_release(p);
+ return -1;
+ }
+
+ status = sf_next_packet(p, hdr, p->buffer, p->bufsize);
if (status) {
- if (status == 1)
+ pcap_header_free(hdr);
+ pcap_buffer_release(p);
+
+ if (status == 1)
return (0);
return (status);
}
if (fcode == NULL ||
- bpf_filter(fcode, p->buffer, h.len, h.caplen)) {
- (*callback)(user, &h, p->buffer);
- if (++n >= cnt && cnt > 0)
- break;
- }
+ bpf_filter(fcode, p->buffer, hdr->len, hdr->caplen)) {
+ (*callback)(user, hdr, p->buffer);
+ if (++n >= cnt && cnt > 0) {
+ pcap_buffer_release(p);
+ break;
+ }
+ } else
+ pcap_header_free(hdr);
+
+ pcap_buffer_release(p);
}
+
/*XXX this breaks semantics tcpslice expects */
return (n);
}
diff -uprN libpcap-0.7.2/scanner.l libpcap/scanner.l
--- libpcap-0.7.2/scanner.l 2003-02-26 07:45:32.000000000 +0100
+++ libpcap/scanner.l 2003-10-05 23:30:22.000000000 +0200
@@ -308,7 +308,7 @@ tcp-urg { yylval.i = 0x20; return NUM;
%%
void
lex_init(buf)
- char *buf;
+ const char *buf;
{
#ifdef FLEX_SCANNER
in_buffer = yy_scan_string(buf);