From: guy Date: Sat, 28 Oct 2000 00:01:26 +0000 (+0000) Subject: When attaching a "bpf_program" to a "pcap_t" to use as a userland X-Git-Tag: libpcap-0.6.1~52 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/82547471f79c2cf4a9943a222d006edc4add2d76?ds=sidebyside When attaching a "bpf_program" to a "pcap_t" to use as a userland filter, always attach a copy, as "pcap-linux.c" does; that way, after a program uses "pcap_setfilter()", it can safely use "pcap_freecode()" to free up the BPF instructions allocated by "pcap_compile()". Also, always free it up when the "pcap_t" is closed. Get rid of the "pcap_t *" argument to "pcap_freecode()", as it's not necessary. Document "pcap_freecode()", for the benefit of programs that might repeatedly compile filter programs and attach them, so that they can free them up after attaching them and avoid leaking memory for them. --- diff --git a/gencode.c b/gencode.c index 0ff11fc9..12706b65 100644 --- a/gencode.c +++ b/gencode.c @@ -21,7 +21,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.125 2000-10-25 07:28:22 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.126 2000-10-28 00:01:26 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -377,7 +377,7 @@ pcap_compile_nopcap(int snaplen_arg, int linktype_arg, * in it. */ void -pcap_freecode(pcap_t *p, struct bpf_program *program) +pcap_freecode(struct bpf_program *program) { program->bf_len = 0; if (program->bf_insns != NULL) { diff --git a/gencode.h b/gencode.h index 8feffb06..96c2bdee 100644 --- a/gencode.h +++ b/gencode.h @@ -18,7 +18,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.42 2000-10-22 04:15:56 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.43 2000-10-28 00:01:27 guy Exp $ (LBL) */ /* Address qualifiers. */ @@ -186,6 +186,7 @@ void finish_parse(struct block *); char *sdup(const char *); struct bpf_insn *icode_to_fcode(struct block *, int *); +int install_bpf_program(pcap_t *, struct bpf_program *); int pcap_parse(void); void lex_init(char *); void lex_cleanup(void); diff --git a/optimize.c b/optimize.c index c39f8992..fe2c2cae 100644 --- a/optimize.c +++ b/optimize.c @@ -22,7 +22,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.64 2000-09-06 07:40:03 itojun Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.65 2000-10-28 00:01:27 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -36,6 +36,8 @@ static const char rcsid[] = #include #include +#include + #include "pcap-int.h" #include "gencode.h" @@ -2077,6 +2079,36 @@ icode_to_fcode(root, lenp) return fp; } +/* + * Make a copy of a BPF program and put it in the "fcode" member of + * a "pcap_t". + * + * If we fail to allocate memory for the copy, fill in the "errbuf" + * member of the "pcap_t" with an error message, and return -1; + * otherwise, return 0. + */ +int +install_bpf_program(pcap_t *p, struct bpf_program *fp) +{ + size_t prog_size; + + /* + * Free up any already installed program. + */ + pcap_freecode(&p->fcode); + + prog_size = sizeof(*fp->bf_insns) * fp->bf_len; + p->fcode.bf_len = fp->bf_len; + p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size); + if (p->fcode.bf_insns == NULL) { + snprintf(p->errbuf, sizeof(p->errbuf), + "malloc: %s", pcap_strerror(errno)); + return (-1); + } + memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size); + return (0); +} + #ifdef BDEBUG static void opt_dump(root) diff --git a/pcap-bpf.c b/pcap-bpf.c index a0d89ed6..e8a2d404 100644 --- a/pcap-bpf.c +++ b/pcap-bpf.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.43 2000-10-12 03:53:58 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.44 2000-10-28 00:01:28 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -372,11 +372,13 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp) * compatible with some of kernel BPF code (for example BSD/OS 3.1). * Take a safer side for now. */ - if (no_optimize) - p->fcode = *fp; - else if (p->sf.rfile != NULL) - p->fcode = *fp; - else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { + if (no_optimize) { + if (install_bpf_program(p, fp) < 0) + return (-1); + } else if (p->sf.rfile != NULL) { + if (install_bpf_program(p, fp) < 0) + return (-1); + } else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", pcap_strerror(errno)); return (-1); diff --git a/pcap-dlpi.c b/pcap-dlpi.c index 608c8a23..153896a0 100644 --- a/pcap-dlpi.c +++ b/pcap-dlpi.c @@ -38,7 +38,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.61 2000-10-12 03:53:58 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.62 2000-10-28 00:01:28 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -555,7 +555,8 @@ int pcap_setfilter(pcap_t *p, struct bpf_program *fp) { - p->fcode = *fp; + if (install_bpf_program(p, fp) < 0) + return (-1); return (0); } diff --git a/pcap-linux.c b/pcap-linux.c index d5e4f53d..f3a636f9 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -26,7 +26,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.38 2000-10-25 07:46:50 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.39 2000-10-28 00:01:29 guy Exp $ (LBL)"; #endif /* @@ -432,22 +432,13 @@ pcap_setfilter(pcap_t *handle, struct bpf_program *filter) return -1; } - /* Free old filter code if existing */ - - pcap_freecode(handle, &handle->fcode); - /* Make our private copy of the filter */ - handle->fcode.bf_len = filter->bf_len; - handle->fcode.bf_insns = - malloc(filter->bf_len * sizeof(*filter->bf_insns)); - if (handle->fcode.bf_insns == NULL) { + if (install_bpf_program(handle, filter) < 0) { snprintf(handle->errbuf, sizeof(handle->errbuf), "malloc: %s", pcap_strerror(errno)); return -1; - } - memcpy(handle->fcode.bf_insns, filter->bf_insns, - filter->bf_len * sizeof(*filter->bf_insns)); + } /* * Run user level packet filter by default. Will be overriden if diff --git a/pcap-nit.c b/pcap-nit.c index c15704b4..524d8c38 100644 --- a/pcap-nit.c +++ b/pcap-nit.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.38 2000-10-12 03:54:00 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.39 2000-10-28 00:01:29 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -245,6 +245,7 @@ int pcap_setfilter(pcap_t *p, struct bpf_program *fp) { - p->fcode = *fp; + if (install_bpf_program(p, fp) < 0) + return (-1); return (0); } diff --git a/pcap-null.c b/pcap-null.c index 588c4d32..e952c988 100644 --- a/pcap-null.c +++ b/pcap-null.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.12 2000-07-11 00:37:06 assar Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.13 2000-10-28 00:01:29 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -68,6 +68,7 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp) "pcap_setfilter: %s", nosup); return (-1); } - p->fcode = *fp; + if (install_bpf_program(p, fp) < 0) + return (-1); return (0); } diff --git a/pcap-pf.c b/pcap-pf.c index 58e85269..6a68a504 100644 --- a/pcap-pf.c +++ b/pcap-pf.c @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.61 2000-10-12 03:54:00 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.62 2000-10-28 00:01:30 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -347,8 +347,10 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp) /* don't give up, just be inefficient */ p->md.use_bpf = 0; } - } else - p->fcode = *fp; + } else { + if (install_bpf_program(p, fp) < 0) + return (-1); + } /*XXX this goes in tcpdump*/ if (p->md.use_bpf) diff --git a/pcap-snit.c b/pcap-snit.c index e20a28ae..47818e4f 100644 --- a/pcap-snit.c +++ b/pcap-snit.c @@ -25,7 +25,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.53 2000-10-12 03:54:00 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.54 2000-10-28 00:01:30 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -302,6 +302,7 @@ int pcap_setfilter(pcap_t *p, struct bpf_program *fp) { - p->fcode = *fp; + if (install_bpf_program(p, fp) < 0) + return (-1); return (0); } diff --git a/pcap-snoop.c b/pcap-snoop.c index 7268500c..82e51c4f 100644 --- a/pcap-snoop.c +++ b/pcap-snoop.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.29 2000-10-12 03:54:01 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.30 2000-10-28 00:01:30 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -274,6 +274,7 @@ int pcap_setfilter(pcap_t *p, struct bpf_program *fp) { - p->fcode = *fp; + if (install_bpf_program(p, fp) < 0) + return (-1); return (0); } diff --git a/pcap.3 b/pcap.3 index 18bcb4ad..2dc98ea7 100644 --- a/pcap.3 +++ b/pcap.3 @@ -1,4 +1,4 @@ -.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.12 2000-10-22 02:21:34 guy Exp $ +.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.13 2000-10-28 00:01:31 guy Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -62,6 +62,7 @@ int pcap_compile(pcap_t *p, struct bpf_program *fp, .ti +8 char *str, int optimize, bpf_u_int32 netmask) int pcap_setfilter(pcap_t *p, struct bpf_program *fp) +void pcap_freecode(struct bpf_program *); .ft .LP .ft B @@ -256,14 +257,14 @@ is similar to .B pcap_compile() except that instead of passing a pcap structure, one passes the snaplen and linktype explicitly. It is intended to be used for -compiling filters for direct bpf usage, without necessarily having +compiling filters for direct BPF usage, without necessarily having called .BR pcap_open() . .PP .B pcap_setfilter() is used to specify a filter program. .I fp -is a pointer to an array of +is a pointer to a .I bpf_program struct, usually the result of a call to .BR pcap_compile() . @@ -272,6 +273,15 @@ is returned on failure; .B 0 is returned on success. .PP +.B pcap_freecode() +is used to free up allocated memory pointed to by a +.I bpf_program +struct generated by +.B pcap_compile() +when that BPF program is no longer needed, for example after it +has been made the filter program for a pcap structure by a call to +.BR pcap_setfilter() . +.PP .B pcap_loop() is similar to .B pcap_dispatch() diff --git a/pcap.c b/pcap.c index 72caa6fb..fd9dc9f1 100644 --- a/pcap.c +++ b/pcap.c @@ -33,7 +33,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.34 2000-10-25 06:59:10 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.35 2000-10-28 00:01:31 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -219,8 +219,8 @@ pcap_close(pcap_t *p) #ifdef linux if (p->md.device != NULL) free(p->md.device); - pcap_freecode(p, &p->fcode); #endif + pcap_freecode(&p->fcode); free(p); } diff --git a/pcap.h b/pcap.h index 57b7bc9c..7d62728f 100644 --- a/pcap.h +++ b/pcap.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.30 2000-10-25 06:59:10 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.31 2000-10-28 00:01:31 guy Exp $ (LBL) */ #ifndef lib_pcap_h @@ -150,7 +150,7 @@ int pcap_compile(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32); int pcap_compile_nopcap(int, int, struct bpf_program *, char *, int, bpf_u_int32); -void pcap_freecode(pcap_t *, struct bpf_program *); +void pcap_freecode(struct bpf_program *); int pcap_datalink(pcap_t *); int pcap_snapshot(pcap_t *); int pcap_is_swapped(pcap_t *);