Guy Harris <[EMAIL PROTECTED]> writes:
> On Tue, Jul 24, 2001 at 08:26:57AM +0200, Yoann Vandoorselaere wrote:
> > Sure, it will behave differently, but should work without problem on
> > all architectures...
>
> With your patch, attempts to call "pcap_set_alloc_func()" on OSes other
> than Linux will fail, because that function doesn't exist. I consider
> that a problem for applications that want the packet data supplied to
> the callback to persist after the callback routine returns.
>
> So "pcap_set_alloc_func()" has to be written for the other OSes as well.
You didn't looked at the new version of this patch.
(which I attach here). This one should work for all OS. (it modify
pcap.c, not pcap-linux.c).
> The question then is "if the application has called
> 'pcap_set_alloc_func()', what should libpcap do on platforms where more
> than one packet is read into the buffer in a system call?"
>
> Should it just allocate a buffer for each packet, and copy from the
> buffer into the packet? That's the easiest solution, but it does mean
> you have to copy the packet.
>
> Or should it allocate a buffer for each read? That'd avoid the copy,
> but it'd mean that libpcap would have to keep track of the buffers, and
> provide a routine to free them, as the pointers handed to the callback
> routine will be pointers into the middle of that buffer, not pointers to
> independently allocated buffers.
>
> A further question is raised by the memory-mapped capture mechanism in
> Linux - if we add support for that, then, if the application has called
> 'pcap_set_alloc_func()', should libpcap allocate a buffer and copy from
> the memory-mapped buffer into the allocated buffer?
>
> I suspect "allocate a buffer for the packet and copy into it" is the
> right answer, but I'd like to see whether anybody else has any
> suggestions first.
Is there any way to capture the packet one by read on any OS ?
That would solve the problem...
New, generic, version of the patch :
Common subdirectories: libpcap.orig/CVS and libpcap/CVS
Common subdirectories: libpcap.orig/SUNOS4 and libpcap/SUNOS4
Common subdirectories: libpcap.orig/bpf and libpcap/bpf
Common subdirectories: libpcap.orig/lbl and libpcap/lbl
diff -up libpcap.orig/pcap-int.h libpcap/pcap-int.h
--- libpcap.orig/pcap-int.h Thu Dec 21 11:29:23 2000
+++ libpcap/pcap-int.h Mon May 28 10:32:24 2001
@@ -105,6 +105,8 @@ struct pcap {
struct bpf_program fcode;
char errbuf[PCAP_ERRBUF_SIZE];
+
+ void *(*alloc)(size_t size);
};
/*
diff -up libpcap.orig/pcap.c libpcap/pcap.c
--- libpcap.orig/pcap.c Sat Dec 16 11:43:31 2000
+++ libpcap/pcap.c Mon May 28 10:36:07 2001
@@ -46,6 +46,7 @@ static const char rcsid[] =
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
@@ -56,10 +57,22 @@ static const char rcsid[] =
int
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
-
+ int ret;
+
+ if ( p->alloc && ! p->buffer && ! (p->buffer = p->alloc(p->bufsize)) ) {
+ snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+
if (p->sf.rfile != NULL)
- return (pcap_offline_read(p, cnt, callback, user));
- return (pcap_read(p, cnt, callback, user));
+ ret = (pcap_offline_read(p, cnt, callback, user));
+ else
+ ret = (pcap_read(p, cnt, callback, user));
+
+ if ( ret > 0 )
+ p->buffer = NULL;
+
+ return ret;
}
int
@@ -67,6 +80,11 @@ pcap_loop(pcap_t *p, int cnt, pcap_handl
{
register int n;
+ if ( p->alloc && ! (p->buffer = p->alloc(p->bufsize)) ) {
+ snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+
for (;;) {
if (p->sf.rfile != NULL)
n = pcap_offline_read(p, cnt, callback, user);
@@ -203,6 +221,14 @@ pcap_open_dead(int linktype, int snaplen
return p;
}
+
+void pcap_set_alloc_func(pcap_t *p, void *(*alloc)(size_t size))
+{
+ free(p->buffer);
+ p->buffer = NULL;
+ p->alloc = alloc;
+}
+
void
pcap_close(pcap_t *p)
{
@@ -218,9 +244,14 @@ 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 && ! p->alloc )
free(p->buffer);
pcap_freecode(&p->fcode);
free(p);
}
+
+
+
+
+
diff -up libpcap.orig/pcap.h libpcap/pcap.h
--- libpcap.orig/pcap.h Sat Oct 28 02:01:31 2000
+++ libpcap/pcap.h Mon May 28 10:32:24 2001
@@ -157,6 +157,12 @@ int pcap_is_swapped(pcap_t *);
int pcap_major_version(pcap_t *);
int pcap_minor_version(pcap_t *);
+/*
+ * Set allocation function,
+ * this allow application to have their own buffer managment.
+ */
+ void pcap_set_alloc_func(pcap_t *p, void *(*alloc)(size_t size));
+
/* XXX */
FILE *pcap_file(pcap_t *);
int pcap_fileno(pcap_t *);
--
Yoann Vandoorselaere | Murphy's law : If anything can go wrong, it will.
MandrakeSoft | O'Tool's commentary : Murphy was an optimist.