Hi,

Here is an updated patch following the discussion that occured on
tcpdump-workers.

I figured out a way for backend to be ported much more easily, and now
porting the backend to the new API is really straight forward. 

I ported most, if not all the backend (excepted pcap-enet.c which look
like unsupported), thought I'm a little tired and it is possible that I
forgot some :)

Also, I only could test my change on OpenBSD 3.2 and Linux 2.6.0, so any
report about compilation failure, or any application going down in flame
will be welcome...

The patch fix the following issue:

- remove constness fix from the patch
- remove use of zero sized array (some architecture doesn't support it).
- port to libpcap-0.8.1.
- port to yet unsuported backend.
- make it way more easy for a backend to support the new scheme.
- move pcap_next() modification to pcap_next_ex()


Regards,


-- 
Yoann Vandoorselaere <[EMAIL PROTECTED]>
diff -urp libpcap-0.8.1.orig/pcap-bpf.c libpcap-0.8.1/pcap-bpf.c
--- libpcap-0.8.1.orig/pcap-bpf.c	2003-11-22 00:06:28.000000000 +0000
+++ libpcap-0.8.1/pcap-bpf.c	2004-01-06 01:08:06.777209896 +0000
@@ -142,6 +142,8 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_h
 	int cc;
 	int n = 0;
 	register u_char *bp, *ep;
+        struct pcap_pkthdr *pcap_header;
+
 	struct bpf_insn *fcode;
 
 	fcode = p->md.use_bpf ? NULL : p->fcode.bf_insns;
@@ -273,7 +275,16 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_h
 			/*
 			 * XXX A bpf_hdr matches a pcap_pkthdr.
 			 */
-			(*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
+			pcap_header = pcap_header_new(p);
+			if ( ! pcap_header )
+				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;
diff -urp libpcap-0.8.1.orig/pcap-dag.c libpcap-0.8.1/pcap-dag.c
--- libpcap-0.8.1.orig/pcap-dag.c	2003-11-21 10:20:45.000000000 +0000
+++ libpcap-0.8.1/pcap-dag.c	2004-01-06 00:45:05.813148344 +0000
@@ -221,7 +221,7 @@ static int dag_read(pcap_t *p, int cnt, 
 
 			unsigned short packet_len = 0;
 			int caplen = 0;
-			struct pcap_pkthdr	pcap_header;
+			struct pcap_pkthdr	*pcap_header;
 
 			dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
 			u_char *dp = ((u_char *)header) + dag_record_size;
@@ -320,24 +320,28 @@ static int dag_read(pcap_t *p, int cnt, 
 					ts = header->ts;
 				}
 
-				pcap_header.ts.tv_sec  = ts >> 32;
+                                pcap_header = pcap_header_new(p);
+                                if ( ! pcap_header )
+                                        return -1;
+                                
+				pcap_header->ts.tv_sec  = ts >> 32;
 				ts = (ts & 0xffffffffULL) * 1000000;
 				ts += 0x80000000; /* rounding */
-				pcap_header.ts.tv_usec = ts >> 32;		
-				if (pcap_header.ts.tv_usec >= 1000000) {
-					pcap_header.ts.tv_usec -= 1000000;
-					pcap_header.ts.tv_sec++;
+				pcap_header->ts.tv_usec = ts >> 32;		
+				if (pcap_header->ts.tv_usec >= 1000000) {
+					pcap_header->ts.tv_usec -= 1000000;
+					pcap_header->ts.tv_sec++;
 				}
 
 				/* Fill in our own header data */
-				pcap_header.caplen = caplen;
-				pcap_header.len = packet_len;
+				pcap_header->caplen = caplen;
+				pcap_header->len = packet_len;
   
 				/* Count the packet. */
 				p->md.stat.ps_recv++;
   
 				/* Call the user supplied callback function */
-				callback(user, &pcap_header, dp);
+				callback(user, pcap_header, dp);
   
 				/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
 				processed++;
diff -urp libpcap-0.8.1.orig/pcap-dlpi.c libpcap-0.8.1/pcap-dlpi.c
--- libpcap-0.8.1.orig/pcap-dlpi.c	2003-11-21 10:20:46.000000000 +0000
+++ libpcap-0.8.1/pcap-dlpi.c	2004-01-05 21:48:52.000000000 +0000
@@ -198,7 +198,7 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_
 #endif
 	int flags;
 	struct strbuf data;
-	struct pcap_pkthdr pkthdr;
+	struct pcap_pkthdr *pkthdr;
 
 	flags = 0;
 	cc = p->cc;
@@ -281,18 +281,23 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_
 #endif
 		++p->md.stat.ps_recv;
 		if (bpf_filter(fcode, pk, origlen, caplen)) {
+
+			pkthdr = pcap_header_new(p);
+			if ( ! pkthdr )
+				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);
 #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 (pkthdr->caplen > p->snapshot)
+				pkthdr->caplen = p->snapshot;
+			(*callback)(user, pkthdr, pk);
 			if (++n >= cnt && cnt >= 0) {
 				p->cc = ep - bp;
 				p->bp = bp;
diff -urp libpcap-0.8.1.orig/pcap-int.h libpcap-0.8.1/pcap-int.h
--- libpcap-0.8.1.orig/pcap-int.h	2003-12-15 01:42:24.000000000 +0000
+++ libpcap-0.8.1/pcap-int.h	2004-01-06 01:10:27.240856176 +0000
@@ -160,6 +160,22 @@ struct pcap_timeval {
     bpf_int32 tv_usec;		/* microseconds */
 };
 
+
+struct buffer_head {
+	int refcount;
+	unsigned char buf;
+};
+
+
+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.
  *
@@ -218,6 +234,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 -urp libpcap-0.8.1.orig/pcap-linux.c libpcap-0.8.1/pcap-linux.c
--- libpcap-0.8.1.orig/pcap-linux.c	2003-11-21 10:20:46.000000000 +0000
+++ libpcap-0.8.1/pcap-linux.c	2004-01-05 23:11:39.000000000 +0000
@@ -447,7 +447,7 @@ pcap_read_packet(pcap_t *handle, pcap_ha
 #endif
 	socklen_t		fromlen;
 	int			packet_len, caplen;
-	struct pcap_pkthdr	pcap_header;
+	struct pcap_pkthdr	*pcap_header;
 
 #ifdef HAVE_PF_PACKET_SOCKETS
 	/*
@@ -623,13 +623,17 @@ pcap_read_packet(pcap_t *handle, pcap_ha
 
 	/* Fill in our own header data */
 
-	if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
+        pcap_header = pcap_header_new(handle);
+        if ( ! pcap_header )
+                return -1;
+        
+	if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header->ts) == -1) {
 		snprintf(handle->errbuf, sizeof(handle->errbuf),
 			 "ioctl: %s", pcap_strerror(errno));
 		return -1;
 	}
-	pcap_header.caplen	= caplen;
-	pcap_header.len		= packet_len;
+	pcap_header->caplen	= caplen;
+	pcap_header->len	= packet_len;
 
 	/*
 	 * Count the packet.
@@ -667,7 +671,7 @@ 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);
 
 	return 1;
 }
diff -urp libpcap-0.8.1.orig/pcap-nit.c libpcap-0.8.1/pcap-nit.c
--- libpcap-0.8.1.orig/pcap-nit.c	2003-11-21 10:20:47.000000000 +0000
+++ libpcap-0.8.1/pcap-nit.c	2004-01-06 00:40:51.495810456 +0000
@@ -176,11 +176,17 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_h
 		if (caplen > p->snapshot)
 			caplen = p->snapshot;
 		if (bpf_filter(fcode, cp, nh->nh_wirelen, caplen)) {
-			struct pcap_pkthdr h;
-			h.ts = nh->nh_timestamp;
-			h.len = nh->nh_wirelen;
-			h.caplen = caplen;
-			(*callback)(user, &h, cp);
+			struct pcap_pkthdr *h;
+
+                        h = pcap_header_new(p);
+                        if ( ! h )
+                                return -1;
+                        
+			h->ts = nh->nh_timestamp;
+			h->len = nh->nh_wirelen;
+			h->caplen = caplen;
+                        
+			(*callback)(user, h, cp);
 			if (++n >= cnt && cnt >= 0) {
 				p->cc = ep - bp;
 				p->bp = bp;
diff -urp libpcap-0.8.1.orig/pcap-pf.c libpcap-0.8.1/pcap-pf.c
--- libpcap-0.8.1.orig/pcap-pf.c	2003-11-22 00:32:55.000000000 +0000
+++ libpcap-0.8.1/pcap-pf.c	2004-01-06 00:42:02.024088528 +0000
@@ -198,16 +198,23 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_h
 		 */
 		if (fcode == NULL ||
 		    bpf_filter(fcode, p, sp->ens_count, buflen)) {
-			struct pcap_pkthdr h;
+			struct pcap_pkthdr *h;
+                        
 			pc->md.TotAccepted++;
-			h.ts = sp->ens_tstamp;
+
+                        h = pcap_header_new(pc);
+                        if ( ! h )
+                                return -1;
+                        
+			h->ts = sp->ens_tstamp;
 #ifdef PCAP_FDDIPAD
-			h.len = sp->ens_count - pad;
+			h->len = sp->ens_count - pad;
 #else
-			h.len = sp->ens_count;
+			h->len = sp->ens_count;
 #endif
-			h.caplen = buflen;
-			(*callback)(user, &h, p);
+			h->caplen = buflen;
+
+                        (*callback)(user, h, p);
 			if (++n >= cnt && cnt > 0) {
 				pc->cc = cc;
 				pc->bp = bp;
diff -urp libpcap-0.8.1.orig/pcap-snit.c libpcap-0.8.1/pcap-snit.c
--- libpcap-0.8.1.orig/pcap-snit.c	2003-11-21 10:20:48.000000000 +0000
+++ libpcap-0.8.1/pcap-snit.c	2004-01-06 00:38:26.353875384 +0000
@@ -188,11 +188,17 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_
 			caplen = p->snapshot;
 
 		if (bpf_filter(fcode, cp, nlp->nh_pktlen, caplen)) {
-			struct pcap_pkthdr h;
-			h.ts = ntp->nh_timestamp;
-			h.len = nlp->nh_pktlen;
-			h.caplen = caplen;
-			(*callback)(user, &h, cp);
+			struct pcap_pkthdr *h;
+
+                        h = pcap_header_new(p);
+                        if ( ! h )
+                                return -1;
+                        
+			h->ts = ntp->nh_timestamp;
+			h->len = nlp->nh_pktlen;
+			h->caplen = caplen;
+                        
+			(*callback)(user, h, cp);
 			if (++n >= cnt && cnt >= 0) {
 				p->cc = ep - bp;
 				p->bp = bp;
diff -urp libpcap-0.8.1.orig/pcap-snoop.c libpcap-0.8.1/pcap-snoop.c
--- libpcap-0.8.1.orig/pcap-snoop.c	2003-11-21 10:20:48.000000000 +0000
+++ libpcap-0.8.1/pcap-snoop.c	2004-01-06 00:41:02.626118392 +0000
@@ -113,13 +113,20 @@ again:
 
 	if (p->fcode.bf_insns == NULL ||
 	    bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
-		struct pcap_pkthdr h;
+		struct pcap_pkthdr *h;
+                
 		++p->md.stat.ps_recv;
-		h.ts.tv_sec = sh->snoop_timestamp.tv_sec;
-		h.ts.tv_usec = sh->snoop_timestamp.tv_usec;
-		h.len = datalen;
-		h.caplen = caplen;
-		(*callback)(user, &h, cp);
+
+                h = pcap_header_new(p);
+                if ( ! h )
+                        return -1;
+
+                h->len = datalen;
+                h->caplen = caplen;
+                h->ts.tv_sec = sh->snoop_timestamp.tv_sec;
+		h->ts.tv_usec = sh->snoop_timestamp.tv_usec;
+
+		(*callback)(user, h, cp);
 		return (1);
 	}
 	return (0);
diff -urp libpcap-0.8.1.orig/pcap-win32.c libpcap-0.8.1/pcap-win32.c
--- libpcap-0.8.1.orig/pcap-win32.c	2003-11-30 02:32:02.000000000 +0000
+++ libpcap-0.8.1/pcap-win32.c	2004-01-06 01:06:23.533905264 +0000
@@ -97,7 +97,8 @@ pcap_read_win32(pcap_t *p, int cnt, pcap
 	int cc;
 	int n = 0;
 	register u_char *bp, *ep;
-
+        struct pcap_pkthdr *pcap_header;
+        
 	cc = p->cc;
 	if (p->cc == 0) {
 		/*
@@ -162,7 +163,16 @@ pcap_read_win32(pcap_t *p, int cnt, pcap
 		/*
 		 * XXX A bpf_hdr matches a pcap_pkthdr.
 		 */
-		(*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
+                pcap_header = pcap_header_new(p);
+                if ( ! pcap_header ) 
+                        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;
diff -urp libpcap-0.8.1.orig/pcap.c libpcap-0.8.1/pcap.c
--- libpcap-0.8.1.orig/pcap.c	2003-11-21 10:20:49.000000000 +0000
+++ libpcap-0.8.1/pcap.c	2004-01-06 01:10:20.657856944 +0000
@@ -66,11 +66,141 @@ static const char rcsid[] _U_ =
 #include <dagapi.h>
 #endif
 
+
+#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;
+
+        if ( p->buffer )
+                free(p->buffer);
+
+        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)
 {
+        int ret;
+        
+        if ( p->cc == 0 ) {
+                ret = pcap_buffer_lock(p);
+                if ( ret < 0 )
+                        return -1;
+        }
+
+	ret = p->read_op(p, cnt, callback, user);
 
-	return p->read_op(p, cnt, callback, user);
+        if ( p->cc == 0 ) 
+                pcap_buffer_release(p);
+
+        return ret;
 }
 
 /*
@@ -79,14 +209,19 @@ pcap_dispatch(pcap_t *p, int cnt, pcap_h
 int
 pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 {
-
-	return p->read_op(p, cnt, callback, user);
+        return pcap_dispatch(p, cnt, callback, user);
 }
 
 int
 pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 {
 	register int n;
+         
+        if ( p->cc == 0 ) {
+                n = pcap_buffer_lock(p);
+                if ( n < 0 )
+                        return -1;
+        }
 
 	for (;;) {
 		if (p->sf.rfile != NULL) {
@@ -104,13 +239,21 @@ pcap_loop(pcap_t *p, int cnt, pcap_handl
 			} while (n == 0);
 		}
 		if (n <= 0)
-			return (n);
+                        break;
+                
 		if (cnt > 0) {
 			cnt -= n;
-			if (cnt <= 0)
-				return (0);
+			if (cnt <= 0) {
+                                n = 0;
+                                break;
+                        }
 		}
 	}
+
+        if ( p->cc == 0 ) 
+                pcap_buffer_release(p);
+
+        return n;
 }
 
 struct singleton {
@@ -139,7 +282,7 @@ pcap_next(pcap_t *p, struct pcap_pkthdr 
 }
 
 struct pkt_for_fakecallback {
-	struct pcap_pkthdr *hdr;
+	struct pcap_pkthdr **hdr;
 	const u_char **pkt;
 };
 
@@ -149,7 +292,7 @@ pcap_fakecallback(u_char *userData, cons
 {
 	struct pkt_for_fakecallback *sp = (struct pkt_for_fakecallback *)userData;
 
-	*sp->hdr = *h;
+	*sp->hdr = h;
 	*sp->pkt = pkt;
 }
 
@@ -158,13 +301,10 @@ pcap_next_ex(pcap_t *p, struct pcap_pkth
     const u_char **pkt_data)
 {
 	struct pkt_for_fakecallback s;
-
-	s.hdr = &p->pcap_header;
+        
+	s.hdr = pkt_header;
 	s.pkt = pkt_data;
-
-	/* Saves a pointer to the packet headers */
-	*pkt_header= &p->pcap_header;
-
+        
 	if (p->sf.rfile != NULL) {
 		int status;
 
@@ -199,7 +339,7 @@ pcap_next_ex(pcap_t *p, struct pcap_pkth
 	 * The first one ('0') conflicts with the return code of 0 from
 	 * pcap_offline_read() meaning "end of file".
 	*/
-	return (p->read_op(p, 1, pcap_fakecallback, (u_char *)&s));
+        return pcap_dispatch(p, 1, pcap_fakecallback, (u_char *)&s);
 }
 
 /*
diff -urp libpcap-0.8.1.orig/pcap.h libpcap-0.8.1/pcap.h
--- libpcap-0.8.1.orig/pcap.h	2003-11-21 10:20:50.000000000 +0000
+++ libpcap-0.8.1/pcap.h	2004-01-05 21:34:59.000000000 +0000
@@ -167,6 +167,10 @@ 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(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
 pcap_t	*pcap_open_live(const char *, int, int, int, char *);

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to