diff options
author | Guy Harris <guy@alum.mit.edu> | 1999-08-18 04:17:38 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 1999-08-18 04:17:38 +0000 |
commit | df490a7085f382fbf4867fe9811af2653af91c17 (patch) | |
tree | a92c1601d9398fedcf8cdde8585a1acdfbb17e74 /wiretap | |
parent | bc3c8c0641c3422133de1444fd214d223fb2ee80 (diff) |
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/file.c | 106 | ||||
-rw-r--r-- | wiretap/libpcap.c | 154 | ||||
-rw-r--r-- | wiretap/libpcap.h | 4 | ||||
-rw-r--r-- | wiretap/netmon.c | 7 | ||||
-rw-r--r-- | wiretap/netxray.c | 8 | ||||
-rw-r--r-- | wiretap/wtap.c | 26 | ||||
-rw-r--r-- | wiretap/wtap.h | 69 |
7 files changed, 323 insertions, 51 deletions
diff --git a/wiretap/file.c b/wiretap/file.c index 1e08ffb821..0d10aa62b4 100644 --- a/wiretap/file.c +++ b/wiretap/file.c @@ -1,6 +1,6 @@ /* file.c * - * $Id: file.c,v 1.13 1999/08/15 06:59:13 guy Exp $ + * $Id: file.c,v 1.14 1999/08/18 04:17:37 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -100,16 +100,15 @@ wtap* wtap_open_offline(const char *filename, int *err) if ((wth->file_type = iptrace_open(wth)) != WTAP_FILE_UNKNOWN) { goto success; } - /* WTAP_FILE_NETMON */ + /* WTAP_FILE_NETMON_xxx */ if ((wth->file_type = netmon_open(wth)) != WTAP_FILE_UNKNOWN) { goto success; } - /* WTAP_FILE_NETXRAY */ + /* WTAP_FILE_NETXRAY_xxx */ if ((wth->file_type = netxray_open(wth)) != WTAP_FILE_UNKNOWN) { goto success; } - /* failure: */ fclose(wth->fh); free(wth); @@ -121,3 +120,102 @@ success: buffer_init(wth->frame_buffer, 1500); return wth; } + + +static wtap_dumper* wtap_dump_open_common(FILE *fh, int filetype, + int encap, int snaplen, int *err); + +wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap, + int snaplen, int *err) +{ + FILE *fh; + + /* In case "fopen()" fails but doesn't set "errno", set "errno" + to a generic "the open failed" error. */ + errno = WTAP_ERR_CANT_OPEN; + fh = fopen(filename, "w"); + if (fh == NULL) { + *err = errno; + return NULL; /* can't create file */ + } + return wtap_dump_open_common(fh, filetype, encap, snaplen, err); +} + +wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen, + int *err) +{ + FILE *fh; + + /* In case "fopen()" fails but doesn't set "errno", set "errno" + to a generic "the open failed" error. */ + errno = WTAP_ERR_CANT_OPEN; + fh = fdopen(fd, "w"); + if (fh == NULL) { + *err = errno; + return NULL; /* can't create standard I/O stream */ + } + return wtap_dump_open_common(fh, filetype, encap, snaplen, err); +} + +static wtap_dumper* wtap_dump_open_common(FILE *fh, int filetype, int encap, + int snaplen, int *err) +{ + wtap_dumper *wdh; + + wdh = malloc(sizeof (wtap_dumper)); + if (wdh == NULL) { + *err = errno; + /* NOTE: this means the FD handed to "wtap_dump_fdopen()" + will be closed if the malloc fails. */ + fclose(fh); + return NULL; + } + wdh->fh = fh; + wdh->file_type = filetype; + wdh->snaplen = snaplen; + wdh->encap = encap; + + switch (filetype) { + + case WTAP_FILE_PCAP: + if (!libpcap_dump_open(wdh, err)) + goto fail; + break; + + default: + /* We currently only support dumping "libpcap" files */ + *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE; + goto fail; + } + return wdh; + +fail: + free(wdh); + fclose(fh); + return NULL; /* XXX - provide a reason why we failed */ +} + +FILE* wtap_dump_file(wtap_dumper *wdh) +{ + return wdh->fh; +} + +int wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, + const u_char *pd) +{ + return (wdh->subtype_write)(wdh, phdr, pd); +} + +int wtap_dump_close(wtap_dumper *wdh) +{ + int ret = 1; + + if (!(wdh->subtype_close)(wdh)) + ret = 0; + ret = fclose(wdh->fh); + if (ret == EOF) + ret = 0; + free(wdh); + return ret; +} + diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c index 34232712de..c44eeee62e 100644 --- a/wiretap/libpcap.c +++ b/wiretap/libpcap.c @@ -1,6 +1,6 @@ /* libpcap.c * - * $Id: libpcap.c,v 1.6 1999/07/28 23:16:42 guy Exp $ + * $Id: libpcap.c,v 1.7 1999/08/18 04:17:35 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -23,6 +23,8 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include <stdlib.h> +#include <errno.h> #include "wtap.h" #include "buffer.h" #include "libpcap.h" @@ -64,39 +66,45 @@ struct pcap_hdr { struct pcaprec_hdr { guint32 ts_sec; /* timestamp seconds */ guint32 ts_usec; /* timestamp microseconds */ - guint32 incl_len; /* number of octets captured in file */ + guint32 incl_len; /* number of octets of packet saved in file */ guint32 orig_len; /* actual length of packet */ }; +static int libpcap_read(wtap *wth); +static int libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, + const u_char *pd); +static int libpcap_dump_close(wtap_dumper *wdh); + +static const int pcap_encap[] = { + WTAP_ENCAP_NONE, /* no encapsulation */ + WTAP_ENCAP_ETHERNET, + WTAP_ENCAP_NONE, /* 3Mb experimental Ethernet */ + WTAP_ENCAP_NONE, /* Amateur Radio AX.25 */ + WTAP_ENCAP_NONE, /* Proteon ProNET Token Ring */ + WTAP_ENCAP_NONE, /* Chaos */ + WTAP_ENCAP_TR, /* IEEE 802 Networks - assume token ring */ + WTAP_ENCAP_ARCNET, + WTAP_ENCAP_SLIP, + WTAP_ENCAP_PPP, + WTAP_ENCAP_FDDI, + WTAP_ENCAP_ATM_RFC1483, + WTAP_ENCAP_RAW_IP, + WTAP_ENCAP_NONE, + WTAP_ENCAP_NONE, + WTAP_ENCAP_NONE, + WTAP_ENCAP_NONE, + WTAP_ENCAP_NONE, + WTAP_ENCAP_NONE, + WTAP_ENCAP_LINUX_ATM_CLIP +}; +#define NUM_PCAP_ENCAPS (sizeof pcap_encap / sizeof pcap_encap[0]) + /* Returns WTAP_FILE_PCAP on success, WTAP_FILE_UNKNOWN on failure */ int libpcap_open(wtap *wth) { int bytes_read; guint32 magic; struct pcap_hdr hdr; - static const int pcap_encap[] = { - WTAP_ENCAP_NONE, /* no encapsulation */ - WTAP_ENCAP_ETHERNET, - WTAP_ENCAP_NONE, /* 3Mb experimental Ethernet */ - WTAP_ENCAP_NONE, /* Amateur Radio AX.25 */ - WTAP_ENCAP_NONE, /* Proteon ProNET Token Ring */ - WTAP_ENCAP_NONE, /* Chaos */ - WTAP_ENCAP_TR, /* IEEE 802 Networks - assume token ring */ - WTAP_ENCAP_ARCNET, - WTAP_ENCAP_SLIP, - WTAP_ENCAP_PPP, - WTAP_ENCAP_FDDI, - WTAP_ENCAP_ATM_RFC1483, - WTAP_ENCAP_RAW_IP, - WTAP_ENCAP_NONE, - WTAP_ENCAP_NONE, - WTAP_ENCAP_NONE, - WTAP_ENCAP_NONE, - WTAP_ENCAP_NONE, - WTAP_ENCAP_NONE, - WTAP_ENCAP_LINUX_ATM_CLIP - }; - #define NUM_PCAP_ENCAPS (sizeof pcap_encap / sizeof pcap_encap[0]) int byte_swapped = 0; /* Read in the number that should be at the start of a "libpcap" file */ @@ -151,7 +159,7 @@ int libpcap_open(wtap *wth) } /* Read the next packet */ -int libpcap_read(wtap *wth) +static int libpcap_read(wtap *wth) { int packet_size; int bytes_read; @@ -220,3 +228,97 @@ int libpcap_read(wtap *wth) return data_offset; } + +int wtap_pcap_encap_to_wtap_encap(int encap) +{ + if (encap < 0 || encap >= NUM_PCAP_ENCAPS) + return WTAP_FILE_UNKNOWN; + return pcap_encap[encap]; +} + +/* Returns 1 on success, 0 on failure; sets "*err" to an error code on + failure */ +int libpcap_dump_open(wtap_dumper *wdh, int *err) +{ + static const guint32 pcap_magic = PCAP_MAGIC; + struct pcap_hdr file_hdr; + static const int wtap_encap[] = { + 0, /* WTAP_ENCAP_NONE */ + 1, /* WTAP_ENCAP_ETHERNET */ + 6, /* WTAP_ENCAP_TR */ + 8, /* WTAP_ENCAP_SLIP */ + 9, /* WTAP_ENCAP_PPP */ + 10, /* WTAP_ENCAP_FDDI */ + 12, /* WTAP_ENCAP_RAW_IP */ + 7, /* WTAP_ENCAP_ARCNET */ + 11, /* WTAP_ENCAP_ATM_RFC1483 */ + 19 /* WTAP_ENCAP_LINUX_ATM_CLIP */ + }; + int nwritten; + + /* Per-packet encapsulations aren't supported. */ + if (wdh->encap == WTAP_ENCAP_PER_PACKET) { + *err = WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED; + return 0; + } + + /* This is a libpcap file */ + wdh->subtype_write = libpcap_dump; + wdh->subtype_close = libpcap_dump_close; + + /* Write the file header. */ + nwritten = fwrite(&pcap_magic, 1, sizeof pcap_magic, wdh->fh); + if (nwritten != sizeof pcap_magic) { + if (nwritten < 0) + *err = errno; + else + *err = WTAP_ERR_SHORT_WRITE; + return 0; + } + + /* current "libpcap" format is 2.4 */ + file_hdr.version_major = 2; + file_hdr.version_minor = 4; + file_hdr.thiszone = 0; /* XXX - current offset? */ + file_hdr.sigfigs = 0; /* unknown, but also apparently unused */ + file_hdr.snaplen = wdh->snaplen; + file_hdr.network = wtap_encap[wdh->encap]; + nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, wdh->fh); + if (nwritten != sizeof file_hdr) { + if (nwritten < 0) + *err = errno; + else + *err = WTAP_ERR_SHORT_WRITE; + return 0; + } + + return 1; +} + +/* Write a record for a packet to a dump file. + Returns 1 on success, 0 on failure. */ +static int libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, + const u_char *pd) +{ + struct pcaprec_hdr rec_hdr; + int nwritten; + + rec_hdr.ts_sec = phdr->ts.tv_sec; + rec_hdr.ts_usec = phdr->ts.tv_usec; + rec_hdr.incl_len = phdr->caplen; + rec_hdr.orig_len = phdr->len; + nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, wdh->fh); + if (nwritten != sizeof rec_hdr) + return 0; /* failed (XXX - save reason why) */ + nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh); + if (nwritten != phdr->caplen) + return 0; /* failed (XXX - save reason why) */ + return 1; +} + +/* Close a dump file. + Returns 1 on success, 0 on failure. */ +static int libpcap_dump_close(wtap_dumper *wdh) +{ + return 1; +} diff --git a/wiretap/libpcap.h b/wiretap/libpcap.h index 5de0a34e71..2bd1449996 100644 --- a/wiretap/libpcap.h +++ b/wiretap/libpcap.h @@ -1,6 +1,6 @@ /* libpcap.h * - * $Id: libpcap.h,v 1.1 1998/11/15 05:29:12 guy Exp $ + * $Id: libpcap.h,v 1.2 1999/08/18 04:17:36 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -22,4 +22,4 @@ */ int libpcap_open(wtap *wth); -int libpcap_read(wtap *wth); +int libpcap_dump_open(wtap_dumper *wdh, int *err); diff --git a/wiretap/netmon.c b/wiretap/netmon.c index dba0cf5784..32ce63e1b1 100644 --- a/wiretap/netmon.c +++ b/wiretap/netmon.c @@ -1,6 +1,6 @@ /* netmon.c * - * $Id: netmon.c,v 1.8 1999/07/13 02:53:24 gram Exp $ + * $Id: netmon.c,v 1.9 1999/08/18 04:17:38 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -95,6 +95,7 @@ int netmon_open(wtap *wth) int bytes_read; char magic[sizeof netmon_1_x_magic]; struct netmon_hdr hdr; + int file_type; static const int netmon_encap[] = { WTAP_ENCAP_NONE, WTAP_ENCAP_ETHERNET, @@ -135,9 +136,11 @@ int netmon_open(wtap *wth) switch (hdr.ver_major) { case 1: + file_type = WTAP_FILE_NETMON_1_x; break; case 2: + file_type = WTAP_FILE_NETMON_2_x; break; default: @@ -195,7 +198,7 @@ int netmon_open(wtap *wth) /* Seek to the beginning of the data records. */ fseek(wth->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET); - return WTAP_FILE_NETMON; + return file_type; } /* Read the next packet */ diff --git a/wiretap/netxray.c b/wiretap/netxray.c index 92fe34a398..17ce354b43 100644 --- a/wiretap/netxray.c +++ b/wiretap/netxray.c @@ -1,6 +1,6 @@ /* netxray.c * - * $Id: netxray.c,v 1.8 1999/07/13 02:53:25 gram Exp $ + * $Id: netxray.c,v 1.9 1999/08/18 04:17:37 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -94,6 +94,7 @@ int netxray_open(wtap *wth) struct netxray_hdr hdr; double timeunit; int version_major; + int file_type; double t; static const int netxray_encap[] = { WTAP_ENCAP_ETHERNET, @@ -139,12 +140,15 @@ int netxray_open(wtap *wth) if (memcmp(hdr.version, vers_1_0, sizeof vers_1_0) == 0) { timeunit = 1000.0; version_major = 1; + file_type = WTAP_FILE_NETXRAY_1_0; } else if (memcmp(hdr.version, vers_1_1, sizeof vers_1_1) == 0) { timeunit = 1000000.0; version_major = 1; + file_type = WTAP_FILE_NETXRAY_1_1; } else if (memcmp(hdr.version, vers_2_001, sizeof vers_2_001) == 0) { timeunit = 1000000.0; version_major = 2; + file_type = WTAP_FILE_NETXRAY_2_001; } else { return WTAP_FILE_UNKNOWN; } @@ -179,7 +183,7 @@ int netxray_open(wtap *wth) /* Seek to the beginning of the data records. */ fseek(wth->fh, pletohl(&hdr.start_offset), SEEK_SET); - return WTAP_FILE_NETXRAY; + return file_type; } /* Read the next packet */ diff --git a/wiretap/wtap.c b/wiretap/wtap.c index aae8794639..49f9312f42 100644 --- a/wiretap/wtap.c +++ b/wiretap/wtap.c @@ -1,6 +1,6 @@ /* wtap.c * - * $Id: wtap.c,v 1.13 1999/08/02 02:35:57 guy Exp $ + * $Id: wtap.c,v 1.14 1999/08/18 04:17:37 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -62,11 +62,20 @@ const char *wtap_file_type_string(wtap *wth) case WTAP_FILE_IPTRACE: return "iptrace"; - case WTAP_FILE_NETMON: - return "Microsoft Network Monitor"; + case WTAP_FILE_NETMON_1_x: + return "Microsoft Network Monitor 1.x"; - case WTAP_FILE_NETXRAY: - return "Cinco Networks NetXRay/Network Associates Sniffer (Windows-based)"; + case WTAP_FILE_NETMON_2_x: + return "Microsoft Network Monitor 2.x"; + + case WTAP_FILE_NETXRAY_1_0: + return "Cinco Networks NetXRay"; + + case WTAP_FILE_NETXRAY_1_1: + return "Network Associates Sniffer (Windows-based) 1.1"; + + case WTAP_FILE_NETXRAY_2_001: + return "Network Associates Sniffer (Windows-based) 2.001"; case WTAP_FILE_RADCOM: return "RADCOM WAN/LAN analyzer"; @@ -100,11 +109,14 @@ void wtap_close(wtap *wth) g_free(wth->capture.radcom); break; - case WTAP_FILE_NETMON: + case WTAP_FILE_NETMON_1_x: + case WTAP_FILE_NETMON_2_x: g_free(wth->capture.netmon); break; - case WTAP_FILE_NETXRAY: + case WTAP_FILE_NETXRAY_1_0: + case WTAP_FILE_NETXRAY_1_1: + case WTAP_FILE_NETXRAY_2_001: g_free(wth->capture.netxray); break; diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 9664d2a427..e1a7465460 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -1,6 +1,6 @@ /* wtap.h * - * $Id: wtap.h,v 1.23 1999/08/15 06:59:13 guy Exp $ + * $Id: wtap.h,v 1.24 1999/08/18 04:17:36 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -32,7 +32,13 @@ * that code adds a DLT_ATM_CLIP DLT_ code of 19, and that * encapsulation isn't the same as the DLT_ATM_RFC1483 encapsulation * presumably used on some BSD systems, which we turn into - * WTAP_ENCAP_ATM_RFC1483. */ + * WTAP_ENCAP_ATM_RFC1483. + * + * WTAP_ENCAP_PER_PACKET is a value passed to "wtap_dump_open()" or + * "wtap_dump_fdopen()" to indicate that there is no single encapsulation + * type for all packets in the file; this may cause those routines to + * fail if the capture file format being written can't support that. */ +#define WTAP_ENCAP_PER_PACKET -1 #define WTAP_ENCAP_NONE 0 #define WTAP_ENCAP_ETHERNET 1 #define WTAP_ENCAP_TR 2 @@ -48,7 +54,9 @@ /* last WTAP_ENCAP_ value + 1 */ #define WTAP_NUM_ENCAP_TYPES 11 -/* File types that can be read by wiretap */ +/* File types that can be read by wiretap. + We may eventually support writing some or all of these file types, + too, so we distinguish between different versions of them. */ #define WTAP_FILE_UNKNOWN 0 #define WTAP_FILE_WTAP 1 #define WTAP_FILE_PCAP 2 @@ -56,9 +64,12 @@ #define WTAP_FILE_NGSNIFFER 4 #define WTAP_FILE_SNOOP 6 #define WTAP_FILE_IPTRACE 7 -#define WTAP_FILE_NETMON 8 -#define WTAP_FILE_NETXRAY 9 -#define WTAP_FILE_RADCOM 10 +#define WTAP_FILE_NETMON_1_x 8 +#define WTAP_FILE_NETMON_2_x 9 +#define WTAP_FILE_NETXRAY_1_0 10 +#define WTAP_FILE_NETXRAY_1_1 11 +#define WTAP_FILE_NETXRAY_2_001 12 +#define WTAP_FILE_RADCOM 13 /* Filter types that wiretap can create. An 'offline' filter is really * a BPF filter, but it is treated specially because wiretap might not know @@ -162,12 +173,25 @@ typedef struct wtap { types */ } wtap; +struct wtap_dumper; + +typedef int (*subtype_write_func)(struct wtap_dumper*, + const struct wtap_pkthdr*, const u_char*); +typedef int (*subtype_close_func)(struct wtap_dumper *); +typedef struct wtap_dumper { + FILE* fh; + int file_type; + int snaplen; + int encap; + + subtype_write_func subtype_write; + subtype_close_func subtype_close; +} wtap_dumper; + /* * On failure, "wtap_open_offline()" returns NULL, and puts into the * "int" pointed to by its second argument: * - * 0 on success; - * * a positive "errno" value if the capture file can't be opened; * * a negative number, indicating the type of error, on other failures. @@ -184,6 +208,35 @@ int wtap_file_type(wtap *wth); const char *wtap_file_type_string(wtap *wth); void wtap_close(wtap *wth); +/* + * On failure, "wtap_dump_open()" and "wtap_dump_fdopen()" return NULL, + * and put into the "int" pointed to by its second argument: + * + * a positive "errno" value if the capture file can't be created, or + * some other failure that sets "errno" occurs; + * + * a negative number, indicating the type of error, on other failures. + */ +#define WTAP_ERR_CANT_OPEN -1 + /* couldn't open, reason unknown */ +#define WTAP_ERR_UNSUPPORTED_FILE_TYPE -2 + /* can't save files in that format */ +#define WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED -3 + /* that format doesn't support per-packet encapsulations */ +#define WTAP_ERR_SHORT_WRITE -4 + /* write wrote less data than it should have */ + +wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap, + int snaplen, int *err); +wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen, + int *err); +int wtap_dump(wtap_dumper *, const struct wtap_pkthdr *, const u_char *); +FILE* wtap_dump_file(wtap_dumper *); +int wtap_dump_close(wtap_dumper *); + +/* XXX - needed until "wiretap" can do live packet captures */ +int wtap_pcap_encap_to_wtap_encap(int encap); + /* Pointer versions of ntohs and ntohl. Given a pointer to a member of a * byte array, returns the value of the two or four bytes at the pointer. * The pletoh[sl] versions return the little-endian representation. |