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);