Hi,
I have a simulation setup where one process acts as a network
sniffer/spoofer and the clients connect to it via TCP connections. In
order to debug it, I needed a client which would attach to the
sniffer/spoofer, read the Ethernet traffic over TCP and write it out in
the archive format suitable for `tcpdump -r'. As it is, libpcap accepts
only two kinds of input: live captures and stored archive files. I
needed to extend this with a third type of input where the caller
supplies its own pcap_read() function which would get called by other
pcap functions.
I am enclosing a patch which extends pcap_open_dead() interface by
allowing user to specify a input callback (reader) function. Other
library functions (pcap_loop() and friends) then invoke the callback
instead of calling the internal pcap_read() function directly. I have
implemented this by storing the callback function as a pointer in struct
pcap. The only change to the API is the extra argument to
pcap_open_dead(). Let me know if this change is acceptable for
inclusion in the libpcap source tree.
Thanks,
Uros
--
Uros Prestor
[EMAIL PROTECTED]
Index: gencode.c
===================================================================
RCS file: /tcpdump/master/libpcap/gencode.c,v
retrieving revision 1.149
diff -u -r1.149 gencode.c
--- gencode.c 2001/02/21 09:33:04 1.149
+++ gencode.c 2001/02/21 22:45:08
@@ -335,7 +335,7 @@
pcap_t *p;
int ret;
- p = pcap_open_dead(linktype_arg, snaplen_arg);
+ p = pcap_open_dead(linktype_arg, snaplen_arg, 0);
if (p == NULL)
return (-1);
ret = pcap_compile(p, program, buf, optimize, mask);
Index: pcap-bpf.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-bpf.c,v
retrieving revision 1.44
diff -u -r1.44 pcap-bpf.c
--- pcap-bpf.c 2000/10/28 00:01:28 1.44
+++ pcap-bpf.c 2001/02/21 22:45:08
@@ -356,6 +356,7 @@
pcap_strerror(errno));
goto bad;
}
+ p->reader = pcap_read;
return (p);
bad:
Index: pcap-dlpi.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-dlpi.c,v
retrieving revision 1.64
diff -u -r1.64 pcap-dlpi.c
--- pcap-dlpi.c 2001/02/21 09:07:41 1.64
+++ pcap-dlpi.c 2001/02/21 22:45:09
@@ -549,6 +549,7 @@
/* Allocate data buffer */
p->bufsize = MAXDLBUF * sizeof(bpf_u_int32);
p->buffer = (u_char *)malloc(p->bufsize + p->offset);
+ p->reader = pcap_read;
return (p);
bad:
Index: pcap-int.h
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-int.h,v
retrieving revision 1.32
diff -u -r1.32 pcap-int.h
--- pcap-int.h 2000/12/21 10:29:23 1.32
+++ pcap-int.h 2001/02/21 22:45:09
@@ -93,6 +93,9 @@
u_char *bp;
int cc;
+ /* input function */
+ pcap_reader reader;
+
/*
* Place holder for pcap_next().
*/
Index: pcap-linux.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-linux.c,v
retrieving revision 1.55
diff -u -r1.55 pcap-linux.c
--- pcap-linux.c 2001/01/20 07:47:54 1.55
+++ pcap-linux.c 2001/02/21 22:45:09
@@ -233,6 +233,7 @@
free(handle);
return NULL;
}
+ handle->reader = pcap_read;
return handle;
}
Index: pcap-nit.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-nit.c,v
retrieving revision 1.39
diff -u -r1.39 pcap-nit.c
--- pcap-nit.c 2000/10/28 00:01:29 1.39
+++ pcap-nit.c 2001/02/21 22:45:09
@@ -233,6 +233,7 @@
strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
goto bad;
}
+ p->reader = pcap_read;
return (p);
bad:
if (fd >= 0)
Index: pcap-pf.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-pf.c,v
retrieving revision 1.62
diff -u -r1.62 pcap-pf.c
--- pcap-pf.c 2000/10/28 00:01:30 1.62
+++ pcap-pf.c 2001/02/21 22:45:09
@@ -315,6 +315,7 @@
}
p->bufsize = BUFSPACE;
p->buffer = (u_char*)malloc(p->bufsize + p->offset);
+ p->reader = pcap_read;
return (p);
bad:
Index: pcap-snit.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-snit.c,v
retrieving revision 1.54
diff -u -r1.54 pcap-snit.c
--- pcap-snit.c 2000/10/28 00:01:30 1.54
+++ pcap-snit.c 2001/02/21 22:45:10
@@ -290,6 +290,7 @@
strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
goto bad;
}
+ p->reader = pcap_read;
return (p);
bad:
if (fd >= 0)
Index: pcap-snoop.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-snoop.c,v
retrieving revision 1.30
diff -u -r1.30 pcap-snoop.c
--- pcap-snoop.c 2000/10/28 00:01:30 1.30
+++ pcap-snoop.c 2001/02/21 22:45:10
@@ -262,6 +262,7 @@
pcap_strerror(errno));
goto bad;
}
+ p->reader = pcap_read;
return (p);
bad:
Index: pcap.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap.c,v
retrieving revision 1.36
diff -u -r1.36 pcap.c
--- pcap.c 2000/12/16 10:43:31 1.36
+++ pcap.c 2001/02/21 22:45:10
@@ -56,10 +56,10 @@
int
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ if (p->reader == NULL)
+ return -1;
- if (p->sf.rfile != NULL)
- return (pcap_offline_read(p, cnt, callback, user));
- return (pcap_read(p, cnt, callback, user));
+ return (*p->reader)(p, cnt, callback, user);
}
int
@@ -68,23 +68,28 @@
register int n;
for (;;) {
- if (p->sf.rfile != NULL)
- n = pcap_offline_read(p, cnt, callback, user);
- else {
- /*
- * XXX keep reading until we get something
- * (or an error occurs)
- */
- do {
- n = pcap_read(p, cnt, callback, user);
- } while (n == 0);
- }
- if (n <= 0)
+ /*
+ * XXX keep reading until we get something
+ * (or an error occurs)
+ */
+ do {
+ n = (*p->reader)(p, cnt, callback, user);
+ } while (n == 0);
+
+ switch (n) {
+ case -1: /* true error */
return (n);
- if (cnt > 0) {
- cnt -= n;
- if (cnt <= 0)
- return (0);
+
+ case -2: /* end-of-file */
+ return 0;
+
+ default:
+ if (cnt > 0) {
+ cnt -= n;
+ if (cnt <= 0)
+ return (0);
+ }
+ break;
}
}
}
@@ -189,7 +194,7 @@
}
pcap_t *
-pcap_open_dead(int linktype, int snaplen)
+pcap_open_dead(int linktype, int snaplen, pcap_reader reader)
{
pcap_t *p;
@@ -200,6 +205,7 @@
p->fd = -1;
p->snapshot = snaplen;
p->linktype = linktype;
+ p->reader = reader;
return p;
}
Index: pcap.h
===================================================================
RCS file: /tcpdump/master/libpcap/pcap.h,v
retrieving revision 1.31
diff -u -r1.31 pcap.h
--- pcap.h 2000/10/28 00:01:31 1.31
+++ pcap.h 2001/02/21 22:45:10
@@ -131,10 +131,12 @@
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
const u_char *);
+typedef int (*pcap_reader)(pcap_t*, int, pcap_handler, u_char*);
+
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 *);
-pcap_t *pcap_open_dead(int, int);
+pcap_t *pcap_open_dead(int, int, pcap_reader);
pcap_t *pcap_open_offline(const char *, char *);
void pcap_close(pcap_t *);
int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
Index: savefile.c
===================================================================
RCS file: /tcpdump/master/libpcap/savefile.c,v
retrieving revision 1.49
diff -u -r1.49 savefile.c
--- savefile.c 2000/12/21 10:29:23 1.49
+++ savefile.c 2001/02/21 22:45:10
@@ -413,6 +413,8 @@
pcap_fddipad = 0;
#endif
+ p->reader = pcap_offline_read;
+
return (p);
bad:
free(p);
@@ -538,8 +540,8 @@
status = sf_next_packet(p, &h, p->buffer, p->bufsize);
if (status) {
- if (status == 1)
- return (0);
+ if (status == 1) /* end of file */
+ return (-2);
return (status);
}