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.

Reply via email to