diff options
-rw-r--r-- | lib/libpcap/inet.c | 12 | ||||
-rw-r--r-- | lib/libpcap/pcap-bpf.c | 38 | ||||
-rw-r--r-- | lib/libpcap/pcap-int.h | 6 | ||||
-rw-r--r-- | lib/libpcap/pcap.3 | 53 | ||||
-rw-r--r-- | lib/libpcap/pcap.c | 72 | ||||
-rw-r--r-- | lib/libpcap/pcap.h | 32 | ||||
-rw-r--r-- | lib/libpcap/savefile.c | 87 | ||||
-rw-r--r-- | lib/libpcap/shlib_version | 2 |
8 files changed, 264 insertions, 38 deletions
diff --git a/lib/libpcap/inet.c b/lib/libpcap/inet.c index 1382ae97b4b..48aca3d437a 100644 --- a/lib/libpcap/inet.c +++ b/lib/libpcap/inet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: inet.c,v 1.18 2005/11/25 20:25:44 krw Exp $ */ +/* $OpenBSD: inet.c,v 1.19 2006/03/26 20:58:50 djm Exp $ */ /* * Copyright (c) 1994, 1995, 1996, 1997, 1998 @@ -246,13 +246,11 @@ pcap_lookupdev(errbuf) } int -pcap_lookupnet(device, netp, maskp, errbuf) - register char *device; - register bpf_u_int32 *netp, *maskp; - register char *errbuf; +pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, + char *errbuf) { - register int fd; - register struct sockaddr_in *sin; + int fd; + struct sockaddr_in *sin; struct ifreq ifr; fd = socket(AF_INET, SOCK_DGRAM, 0); diff --git a/lib/libpcap/pcap-bpf.c b/lib/libpcap/pcap-bpf.c index 60b5cc7b140..bc988b1325f 100644 --- a/lib/libpcap/pcap-bpf.c +++ b/lib/libpcap/pcap-bpf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcap-bpf.c,v 1.19 2006/01/16 22:45:57 reyk Exp $ */ +/* $OpenBSD: pcap-bpf.c,v 1.20 2006/03/26 20:58:51 djm Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1998 @@ -170,6 +170,13 @@ pcap_inject(pcap_t *p, const void *buf, size_t len) return (write(p->fd, buf, len)); } +int +pcap_sendpacket(pcap_t *p, const u_char *buf, int size) +{ + return (pcap_inject(p, buf, size) == -1 ? -1 : 0); +} + +/* ARGSUSED */ static __inline int bpf_open(pcap_t *p, char *errbuf) { @@ -340,7 +347,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, int pcap_setfilter(pcap_t *p, struct bpf_program *fp) { - int buflen; + size_t buflen; /* * It looks that BPF code generated by gen_protochain() is not * compatible with some of kernel BPF code (for example BSD/OS 3.1). @@ -367,6 +374,33 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp) } int +pcap_setdirection(pcap_t *p, pcap_direction_t d) +{ + u_int dirfilt; + + switch (d) { + case PCAP_D_INOUT: + dirfilt = 0; + break; + case PCAP_D_IN: + dirfilt = BPF_DIRECTION_OUT; + break; + case PCAP_D_OUT: + dirfilt = BPF_DIRECTION_IN; + break; + default: + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Invalid direction"); + return (-1); + } + if (ioctl(p->fd, BIOCSDIRFILT, &dirfilt) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSDIRFILT: %s", + pcap_strerror(errno)); + return (-1); + } + return (0); +} + +int pcap_set_datalink(pcap_t *p, int dlt) { int i; diff --git a/lib/libpcap/pcap-int.h b/lib/libpcap/pcap-int.h index e5d2e204b33..d870d326bca 100644 --- a/lib/libpcap/pcap-int.h +++ b/lib/libpcap/pcap-int.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcap-int.h,v 1.10 2005/11/18 11:05:39 djm Exp $ */ +/* $OpenBSD: pcap-int.h,v 1.11 2006/03/26 20:58:51 djm Exp $ */ /* * Copyright (c) 1994, 1995, 1996 @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap-int.h,v 1.10 2005/11/18 11:05:39 djm Exp $ (LBL) + * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap-int.h,v 1.11 2006/03/26 20:58:51 djm Exp $ (LBL) */ #ifndef pcap_int_h @@ -104,6 +104,8 @@ struct pcap { u_int *dlt_list; char errbuf[PCAP_ERRBUF_SIZE]; + + struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */ }; /* diff --git a/lib/libpcap/pcap.3 b/lib/libpcap/pcap.3 index 3a4c30774ee..5e35c94d456 100644 --- a/lib/libpcap/pcap.3 +++ b/lib/libpcap/pcap.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pcap.3,v 1.27 2005/11/18 15:27:09 jmc Exp $ +.\" $OpenBSD: pcap.3,v 1.28 2006/03/26 20:58:51 djm Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -33,10 +33,12 @@ .Fn pcap_open_offline "char *fname" "char *errbuf" .Ft "pcap_dumper_t *" .Fn pcap_dump_open "pcap_t *p" "char *fname" +.Ft "pcap_dumper_t *" +.Fn pcap_dump_fopen "pcap_t *p" "FILE *f" .Ft "char *" .Fn pcap_lookupdev "char *errbuf" .Ft uint -.Fn pcap_lookupnet "char *device" "bpf_u_int32 *netp" "bpf_u_int32 *maskp" "char *errbuf" +.Fn pcap_lookupnet "const char *device" "bpf_u_int32 *netp" "bpf_u_int32 *maskp" "char *errbuf" .Ft int .Fn pcap_dispatch "pcap_t *p" "int cnt" "pcap_handler callback" "u_char *user" .Ft int @@ -46,6 +48,8 @@ .Ft int .Fn pcap_inject "pcap_t *p" "void *, size_t" .Ft int +.Fn pcap_sendpacket "pcap_t *p" "void *, int" +.Ft int .Fn pcap_compile "pcap_t *p" "struct bpf_program *fp" "char *str" "int optimize" "bpf_u_int32 netmask" .Ft int .Fn pcap_setfilter "pcap_t *p" "struct bpf_program *fp" @@ -54,6 +58,10 @@ .Ft "u_char *" .Fn pcap_next "pcap_t *p" "struct pcap_pkthdr *h" .Ft int +.Fn pcap_next_ex "pcap_t *p" "struct pcap_pkthdr **hp" "const u_char **pktp" +.Ft int +.Fn pcap_setdirection "pcap_t *p" "pcap_direction_t dir" +.Ft int .Fn pcap_datalink "pcap_t *p" .Ft int .Fn pcap_snapshot "pcap_t *p" @@ -77,6 +85,12 @@ .Fn pcap_strerror "int error" .Ft void .Fn pcap_close "pcap_t *p" +.Ft "FILE *" +.Fn pcap_dump_file "pcap_dumper_t *p" +.Ft long +.Fn pcap_dump_ftell "pcap_dumper_t *p" +.Ft int +.Fn pcap_dump_flush "pcap_dumper_t *p" .Ft void .Fn pcap_dump_close "pcap_dumper_t *p" .Ft int @@ -95,6 +109,8 @@ .Fn pcap_list_datalinks "pcap_t *p" "int **dlts" .Ft pcap_t .Fn pcap_open_dead "int linktype" "int snaplen" +.Ft pcap_t +.Fn pcap_fopen_offline "FILE *fp" "char *errbuf" .Ft const char * .Fn pcap_lib_version "void" .Ft const char * @@ -187,6 +203,10 @@ is returned, .Fn pcap_geterr can be used to get the error text. .Pp +.Fn pcap_dump_fopen +allows the use of savefile functions on the already-opened stream +.Dq f . +.Pp .Fn pcap_lookupdev returns a pointer to a network device suitable for use with .Fn pcap_open_live @@ -257,6 +277,11 @@ Note that its calling arguments are suitable for use with uses .Xr write 2 to inject a raw packet through the network interface. +It returns the number of bytes written or \-1 on failure. +.Pp +.Fn pcap_sendpacket +is an alternate interface for packet injection (provided for compatibility). +It returns 0 on success or \-1 on failure. .Pp .Fn pcap_compile is used to compile the string @@ -325,6 +350,13 @@ returns a .Fa u_char pointer to the next packet. .Pp +.Fn pcap_next_ex +reads the next packet and returns a success/failure indication: a +return value of 1 indicates success, 0 means that the timeout was exceeded +on a live capture, \-1 indicates that an error occurred whilst reading +the packet and \-2 is returned when there are no more packets to read in a +savefile. +.Pp .Fn pcap_datalink returns the link layer type, e.g., .Tn DLT_EN10MB . @@ -382,6 +414,15 @@ closes the files associated with .Fa p and deallocates resources. .Pp +.Fn pcap_dump_file +returns the stream associated with a savefile. +.Pp +.Fn pcap_dump_ftell +returns the current file offset within a savefile. +.Pp +.Fn pcap_dump_flush +ensures that any buffered data has been written to a savefile. +.Pp .Fn pcap_dump_close closes the savefile. .Pp @@ -405,6 +446,10 @@ sets or resets non-blocking mode on a capture file descriptor. sets the datalink type on a live capture device that supports multiple datalink types. .Pp +.Fn pcap_setdirection +is used to limit the direction that packets must be flowing in order +to be captured. +.Pp .Fn pcap_list_datalinks returns an array of the supported datalink types for an opened live capture device as a \-1 terminated array. @@ -421,6 +466,10 @@ is used for creating a pcap_t structure to use when calling the other functions in libpcap. It is typically used when just using libpcap for compiling BPF code. .Pp +.Fn pcap_fopen_offline +may be used to read dumped data from an existing open stream +.Dq fp . +.Pp .Fn pcap_lib_version returns a string describing the version of libpcap. .Fn pcap_datalink_val_to_name diff --git a/lib/libpcap/pcap.c b/lib/libpcap/pcap.c index 30f58292718..6c516f39e32 100644 --- a/lib/libpcap/pcap.c +++ b/lib/libpcap/pcap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcap.c,v 1.9 2005/11/18 11:05:39 djm Exp $ */ +/* $OpenBSD: pcap.c,v 1.10 2006/03/26 20:58:51 djm Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998 @@ -111,6 +111,70 @@ pcap_next(pcap_t *p, struct pcap_pkthdr *h) return (s.pkt); } +struct pkt_for_fakecallback { + struct pcap_pkthdr *hdr; + const u_char **pkt; +}; + +static void +pcap_fakecallback(u_char *userData, const struct pcap_pkthdr *h, + const u_char *pkt) +{ + struct pkt_for_fakecallback *sp = (struct pkt_for_fakecallback *)userData; + + *sp->hdr = *h; + *sp->pkt = pkt; +} + +int +pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, + const u_char **pkt_data) +{ + struct pkt_for_fakecallback s; + + s.hdr = &p->pcap_header; + s.pkt = pkt_data; + + /* Saves a pointer to the packet headers */ + *pkt_header= &p->pcap_header; + + if (p->sf.rfile != NULL) { + int status; + + /* We are on an offline capture */ + status = pcap_offline_read(p, 1, pcap_fakecallback, + (u_char *)&s); + + /* + * Return codes for pcap_offline_read() are: + * - 0: EOF + * - -1: error + * - >1: OK + * The first one ('0') conflicts with the return code of + * 0 from pcap_read() meaning "no packets arrived before + * the timeout expired", so we map it to -2 so you can + * distinguish between an EOF from a savefile and a + * "no packets arrived before the timeout expired, try + * again" from a live capture. + */ + if (status == 0) + return (-2); + else + return (status); + } + + /* + * Return codes for pcap_read() are: + * - 0: timeout + * - -1: error + * - -2: loop was broken out of with pcap_breakloop() + * - >1: OK + * The first one ('0') conflicts with the return code of 0 from + * pcap_offline_read() meaning "end of file". + */ + return (pcap_read(p, 1, pcap_fakecallback, (u_char *)&s)); +} + /* * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate. */ @@ -271,6 +335,12 @@ pcap_perror(pcap_t *p, char *prefix) fprintf(stderr, "%s: %s\n", prefix, p->errbuf); } +int +pcap_get_selectable_fd(pcap_t *p) +{ + return (p->fd); +} + char * pcap_geterr(pcap_t *p) { diff --git a/lib/libpcap/pcap.h b/lib/libpcap/pcap.h index f4c0e2eade6..bb71365e32a 100644 --- a/lib/libpcap/pcap.h +++ b/lib/libpcap/pcap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcap.h,v 1.13 2005/11/18 11:05:39 djm Exp $ */ +/* $OpenBSD: pcap.h,v 1.14 2006/03/26 20:58:51 djm Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap.h,v 1.13 2005/11/18 11:05:39 djm Exp $ (LBL) + * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap.h,v 1.14 2006/03/26 20:58:51 djm Exp $ (LBL) */ #ifndef lib_pcap_h @@ -80,6 +80,12 @@ struct pcap_file_header { bpf_u_int32 linktype; /* data link type (DLT_*) */ }; +typedef enum { + PCAP_D_INOUT = 0, + PCAP_D_IN, + PCAP_D_OUT +} pcap_direction_t; + /* * Each packet in the dump file is prepended with this generic header. * This gets around the problem of different headers for different @@ -129,21 +135,26 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, __BEGIN_DECLS char *pcap_lookupdev(char *); -int pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, 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_offline(const char *, char *); pcap_t *pcap_open_dead(int, int); +pcap_t *pcap_open_offline(const char *, char *); +pcap_t *pcap_fopen_offline(FILE *, char *); void pcap_close(pcap_t *); int pcap_loop(pcap_t *, int, pcap_handler, u_char *); int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); const u_char* pcap_next(pcap_t *, struct pcap_pkthdr *); +int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **); +void pcap_breakloop(pcap_t *); int pcap_stats(pcap_t *, struct pcap_stat *); -int pcap_inject(pcap_t *, const void *, size_t); int pcap_setfilter(pcap_t *, struct bpf_program *); +int pcap_setdirection(pcap_t *, pcap_direction_t); int pcap_getnonblock(pcap_t *, char *); int pcap_setnonblock(pcap_t *, int, char *); void pcap_perror(pcap_t *, char *); +int pcap_inject(pcap_t *, const void *, size_t); +int pcap_sendpacket(pcap_t *, const u_char *, int); char *pcap_strerror(int); char *pcap_geterr(pcap_t *); int pcap_compile(pcap_t *, struct bpf_program *, char *, int, @@ -151,14 +162,12 @@ int pcap_compile(pcap_t *, struct bpf_program *, char *, int, int pcap_compile_nopcap(int, int, struct bpf_program *, char *, int, bpf_u_int32); void pcap_freecode(struct bpf_program *); -void pcap_breakloop(pcap_t *); int pcap_datalink(pcap_t *); int pcap_list_datalinks(pcap_t *, int **); int pcap_set_datalink(pcap_t *, int); int pcap_datalink_name_to_val(const char *); const char *pcap_datalink_val_to_name(int); const char *pcap_datalink_val_to_description(int); -const char *pcap_lib_version(void); int pcap_snapshot(pcap_t *); int pcap_is_swapped(pcap_t *); int pcap_major_version(pcap_t *); @@ -169,14 +178,23 @@ FILE *pcap_file(pcap_t *); int pcap_fileno(pcap_t *); pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); +pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp); +FILE *pcap_dump_file(pcap_dumper_t *); +long pcap_dump_ftell(pcap_dumper_t *); +int pcap_dump_flush(pcap_dumper_t *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); int pcap_findalldevs(pcap_if_t **, char *); void pcap_freealldevs(pcap_if_t *); +const char *pcap_lib_version(void); + /* XXX this guy lives in the bpf tree */ u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); char *bpf_image(struct bpf_insn *, int); + +int pcap_get_selectable_fd(pcap_t *); + __END_DECLS #endif diff --git a/lib/libpcap/savefile.c b/lib/libpcap/savefile.c index 7652fa9fa23..e9ccefff3c0 100644 --- a/lib/libpcap/savefile.c +++ b/lib/libpcap/savefile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: savefile.c,v 1.8 2004/01/27 06:58:03 tedu Exp $ */ +/* $OpenBSD: savefile.c,v 1.9 2006/03/26 20:58:51 djm Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -101,8 +101,31 @@ swap_hdr(struct pcap_file_header *hp) pcap_t * pcap_open_offline(const char *fname, char *errbuf) { - register pcap_t *p; - register FILE *fp; + pcap_t *p; + FILE *fp; + + if (fname[0] == '-' && fname[1] == '\0') + fp = stdin; + else { + fp = fopen(fname, "r"); + if (fp == NULL) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, + pcap_strerror(errno)); + return (NULL); + } + } + p = pcap_fopen_offline(fp, errbuf); + if (p == NULL) { + if (fp != stdin) + fclose(fp); + } + return (p); +} + +pcap_t * +pcap_fopen_offline(FILE *fp, char *errbuf) +{ + pcap_t *p; struct pcap_file_header hdr; int linklen; @@ -114,20 +137,10 @@ pcap_open_offline(const char *fname, char *errbuf) memset((char *)p, 0, sizeof(*p)); /* - * Set this field so we don't close stdin in pcap_close! + * Set this field so we don't double-close in pcap_close! */ p->fd = -1; - if (fname[0] == '-' && fname[1] == '\0') - fp = stdin; - else { - fp = fopen(fname, "r"); - if (fp == NULL) { - snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, - pcap_strerror(errno)); - goto bad; - } - } if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "fread: %s", pcap_strerror(errno)); @@ -328,6 +341,19 @@ pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) (void)fwrite((char *)sp, h->caplen, 1, f); } +static pcap_dumper_t * +pcap_setup_dump(pcap_t *p, FILE *f, const char *fname) +{ + if (sf_write_header(f, p->linktype, p->tzoff, p->snapshot) == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s", + fname, pcap_strerror(errno)); + if (f != stdout) + (void)fclose(f); + return (NULL); + } + return ((pcap_dumper_t *)f); +} + /* * Initialize so that sf_write() will output to the file named 'fname'. */ @@ -345,8 +371,37 @@ pcap_dump_open(pcap_t *p, const char *fname) return (NULL); } } - (void)sf_write_header(f, p->linktype, p->tzoff, p->snapshot); - return ((pcap_dumper_t *)f); + return (pcap_setup_dump(p, f, fname)); +} + +/* + * Initialize so that sf_write() will output to the given stream. + */ +pcap_dumper_t * +pcap_dump_fopen(pcap_t *p, FILE *f) +{ + return (pcap_setup_dump(p, f, "stream")); +} + +FILE * +pcap_dump_file(pcap_dumper_t *p) +{ + return ((FILE *)p); +} + +long +pcap_dump_ftell(pcap_dumper_t *p) +{ + return (ftell((FILE *)p)); +} + +pcap_dump_flush(pcap_dumper_t *p) +{ + + if (fflush((FILE *)p) == EOF) + return (-1); + else + return (0); } void diff --git a/lib/libpcap/shlib_version b/lib/libpcap/shlib_version index d9961ea9fef..3066b9771e7 100644 --- a/lib/libpcap/shlib_version +++ b/lib/libpcap/shlib_version @@ -1,2 +1,2 @@ -major=4 +major=5 minor=0 |