Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 395 lines (352 sloc) 9.466 kb
b11ddf8 Initial revision
mcr authored
1 /*
2 * Copyright (c) 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * savefile.c - supports offline use of tcpdump
22 * Extraction/creation by Jeffrey Mogul, DECWRL
23 * Modified by Steve McCanne, LBL.
24 *
25 * Used to save the received packet headers, after filtering, to
26 * a file, and then read them later.
27 * The first record in the file contains saved values for the machine
28 * dependent values so we can print the dump file on any architecture.
29 */
30
31 #ifndef lint
30e89f1 @yuguy Add _U_ to "rcsid[]" definitions, to eliminate "unused variable"
yuguy authored
32 static const char rcsid[] _U_ =
b908482 @yuguy Update CHANGES for USB fixes.
yuguy authored
33 "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.183 2008-12-23 20:13:29 guy Exp $ (LBL)";
0e2f8c8 add config.h, remove gnuc.h. remove __dead
assar authored
34 #endif
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
b11ddf8 Initial revision
mcr authored
38 #endif
39
2723ec4 Check for the intN_t and u_intN_t types the same way we do for tcpdump;
Guy Harris authored
40 #ifdef WIN32
41 #include <pcap-stdinc.h>
42 #else /* WIN32 */
43 #if HAVE_INTTYPES_H
44 #include <inttypes.h>
45 #elif HAVE_STDINT_H
46 #include <stdint.h>
47 #endif
48 #ifdef HAVE_SYS_BITYPES_H
49 #include <sys/bitypes.h>
50 #endif
51 #include <sys/types.h>
52 #endif /* WIN32 */
53
b11ddf8 Initial revision
mcr authored
54 #include <errno.h>
55 #include <memory.h>
56 #include <stdio.h>
57 #include <stdlib.h>
fd7f1bf @yuguy Include <string.h> to declare various string-manipulating routines.
yuguy authored
58 #include <string.h>
b11ddf8 Initial revision
mcr authored
59
60 #include "pcap-int.h"
b4c382f @yuguy From Paolo Abeni:
yuguy authored
61 #include "pcap/usb.h"
b11ddf8 Initial revision
mcr authored
62
63 #ifdef HAVE_OS_PROTO_H
64 #include "os-proto.h"
65 #endif
66
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
67 #include "sf-pcap.h"
68 #include "sf-pcap-ng.h"
2c961ff @yuguy Get rid of the PCAP_ENCAP_ values - if an application uses them, that
yuguy authored
69
afbb1ce @yuguy Based on work from Florent Drouin, split the 32-bit link-layer type
yuguy authored
70 /*
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
71 * Setting O_BINARY on DOS/Windows is a bit tricky
afbb1ce @yuguy Based on work from Florent Drouin, split the 32-bit link-layer type
yuguy authored
72 */
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
73 #if defined(WIN32)
74 #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY)
75 #elif defined(MSDOS)
76 #if defined(__HIGHC__)
77 #define SET_BINMODE(f) setmode(f, O_BINARY)
78 #else
79 #define SET_BINMODE(f) setmode(fileno(f), O_BINARY)
80 #endif
81 #endif
b11ddf8 Initial revision
mcr authored
82
9792990 @yuguy Add a "stats" function pointer to the pcap_t structure, which handles
yuguy authored
83 static int
2c618b9 @yuguy Add "getnonblock" and "setnonblock" operations, and set the function
yuguy authored
84 sf_getnonblock(pcap_t *p, char *errbuf)
85 {
86 /*
87 * This is a savefile, not a live capture file, so never say
88 * it's in non-blocking mode.
89 */
90 return (0);
91 }
92
93 static int
94 sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
95 {
96 /*
65f960d @guyharris Reject attempts to put savefiles into non-blocking mode.
guyharris authored
97 * This is a savefile, not a live capture file, so reject
98 * requests to put it in non-blocking mode. (If it's a
99 * pipe, it could be put in non-blocking mode, but that
100 * would significantly complicate the code to read packets,
101 * as it would have to handle reading partial packets and
102 * keeping the state of the read.)
2c618b9 @yuguy Add "getnonblock" and "setnonblock" operations, and set the function
yuguy authored
103 */
65f960d @guyharris Reject attempts to put savefiles into non-blocking mode.
guyharris authored
104 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
105 "Savefiles cannot be put into non-blocking mode");
106 return (-1);
2c618b9 @yuguy Add "getnonblock" and "setnonblock" operations, and set the function
yuguy authored
107 }
108
109 static int
9792990 @yuguy Add a "stats" function pointer to the pcap_t structure, which handles
yuguy authored
110 sf_stats(pcap_t *p, struct pcap_stat *ps)
111 {
112 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
113 "Statistics aren't available from savefiles");
114 return (-1);
115 }
116
3a0937c @yuguy On Win32, have pcap_setbuff, pcap_setmode, and pcap_setmintocopy ops, so
yuguy authored
117 #ifdef WIN32
118 static int
119 sf_setbuff(pcap_t *p, int dim)
120 {
121 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
122 "The kernel buffer size cannot be set while reading from a file");
123 return (-1);
124 }
125
126 static int
127 sf_setmode(pcap_t *p, int mode)
128 {
129 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
130 "impossible to set mode while reading from a file");
131 return (-1);
132 }
133
134 static int
135 sf_setmintocopy(pcap_t *p, int size)
136 {
137 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
138 "The mintocopy parameter cannot be set while reading from a file");
139 return (-1);
140 }
141 #endif
142
2d2890d @yuguy Add support for sending packets; includes contributions from Mark
yuguy authored
143 static int
144 sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
145 {
146 strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
147 PCAP_ERRBUF_SIZE);
148 return (-1);
149 }
150
9c2ab75 @yuguy Give a more correct error if you try to set the direction when reading
yuguy authored
151 /*
152 * Set direction flag: Which packets do we accept on a forwarding
153 * single device? IN, OUT or both?
154 */
155 static int
75b14d2 @yuguy OK, we'll be putting out 0.9.2 soon, so add the API changes back in
yuguy authored
156 sf_setdirection(pcap_t *p, pcap_direction_t d)
9c2ab75 @yuguy Give a more correct error if you try to set the direction when reading
yuguy authored
157 {
158 snprintf(p->errbuf, sizeof(p->errbuf),
159 "Setting direction is not supported on savefiles");
160 return (-1);
161 }
162
e648c9e @yuguy Add a "close" function pointer to the pcap_t structure, which handles
yuguy authored
163 static void
2527d1a @yuguy Turn close_op into cleanup_op; the routine that handles it can also be
yuguy authored
164 sf_cleanup(pcap_t *p)
e648c9e @yuguy Add a "close" function pointer to the pcap_t structure, which handles
yuguy authored
165 {
166 if (p->sf.rfile != stdin)
167 (void)fclose(p->sf.rfile);
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
168 if (p->buffer != NULL)
169 free(p->buffer);
b372da4 Free any filter set on a savefile when the savefile is closed.
nvercamm authored
170 pcap_freecode(&p->fcode);
e648c9e @yuguy Add a "close" function pointer to the pcap_t structure, which handles
yuguy authored
171 }
172
b11ddf8 Initial revision
mcr authored
173 pcap_t *
174 pcap_open_offline(const char *fname, char *errbuf)
175 {
cccbf10 @yuguy From Chris Lightfoot <cwrl@users.sourceforge.net>: add
yuguy authored
176 FILE *fp;
875d609 @yuguy Don't close the input stream if "pcap_fopen_offline()" fails; only do so
yuguy authored
177 pcap_t *p;
178
b11ddf8 Initial revision
mcr authored
179 if (fname[0] == '-' && fname[1] == '\0')
8c2c2e8 Fixed the definition of SET_BINMODE(): the correct flag under VC6 is
risso authored
180 {
b11ddf8 Initial revision
mcr authored
181 fp = stdin;
8c2c2e8 Fixed the definition of SET_BINMODE(): the correct flag under VC6 is
risso authored
182 #if defined(WIN32) || defined(MSDOS)
183 /*
37bd041 @yuguy Get rid of a redundant test (if we're in that branch of code, we've set
yuguy authored
184 * We're reading from the standard input, so put it in binary
9942a5d @yuguy Clean up white space.
yuguy authored
185 * mode, as savefiles are binary files.
186 */
37bd041 @yuguy Get rid of a redundant test (if we're in that branch of code, we've set
yuguy authored
187 SET_BINMODE(fp);
8c2c2e8 Fixed the definition of SET_BINMODE(): the correct flag under VC6 is
risso authored
188 #endif
189 }
b11ddf8 Initial revision
mcr authored
190 else {
f8a76d1 @yuguy From Gisle Vanem: MS-DOS support.
yuguy authored
191 #if !defined(WIN32) && !defined(MSDOS)
b11ddf8 Initial revision
mcr authored
192 fp = fopen(fname, "r");
6831542 Added support for Win32, based on WinPcap.
risso authored
193 #else
194 fp = fopen(fname, "rb");
195 #endif
b11ddf8 Initial revision
mcr authored
196 if (fp == NULL) {
20d9e08 do not use sprintf(). always use snprintf().
itojun authored
197 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
198 pcap_strerror(errno));
875d609 @yuguy Don't close the input stream if "pcap_fopen_offline()" fails; only do so
yuguy authored
199 return (NULL);
b11ddf8 Initial revision
mcr authored
200 }
201 }
875d609 @yuguy Don't close the input stream if "pcap_fopen_offline()" fails; only do so
yuguy authored
202 p = pcap_fopen_offline(fp, errbuf);
203 if (p == NULL) {
204 if (fp != stdin)
205 fclose(fp);
206 }
207 return (p);
cccbf10 @yuguy From Chris Lightfoot <cwrl@users.sourceforge.net>: add
yuguy authored
208 }
209
854adf5 Implemented pcap_hopen_offline(). This "internal" function allows us to
gianluca authored
210 #ifdef WIN32
211 pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
212 {
213 int fd;
214 FILE *file;
215
216 fd = _open_osfhandle(osfd, _O_RDONLY);
217 if ( fd < 0 )
218 {
219 snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
220 return NULL;
221 }
222
223 file = _fdopen(fd, "rb");
224 if ( file == NULL )
225 {
226 snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
227 return NULL;
228 }
229
230 return pcap_fopen_offline(file, errbuf);
231 }
232 #endif
233
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
234 static int (*check_headers[])(pcap_t *, bpf_u_int32, FILE *, char *) = {
235 pcap_check_header,
236 pcap_ng_check_header
237 };
238
239 #define N_FILE_TYPES (sizeof check_headers / sizeof check_headers[0])
240
854adf5 Implemented pcap_hopen_offline(). This "internal" function allows us to
gianluca authored
241 #ifdef WIN32
242 static
243 #endif
cccbf10 @yuguy From Chris Lightfoot <cwrl@users.sourceforge.net>: add
yuguy authored
244 pcap_t *
245 pcap_fopen_offline(FILE *fp, char *errbuf)
246 {
247 register pcap_t *p;
248 bpf_u_int32 magic;
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
249 size_t amt_read;
250 u_int i;
cccbf10 @yuguy From Chris Lightfoot <cwrl@users.sourceforge.net>: add
yuguy authored
251
8b04d92 @guyharris No, that's not an issue - it'll be a strdup() in any case, and safe to
guyharris authored
252 p = pcap_create_common("(savefile)", errbuf);
b93bc35 @guyharris From Dustin Spicuzza: use pcap_create_common() to allocate the pcap_t in
guyharris authored
253 if (p == NULL)
cccbf10 @yuguy From Chris Lightfoot <cwrl@users.sourceforge.net>: add
yuguy authored
254 return (NULL);
255
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
256 /*
257 * Read the first 4 bytes of the file; the network analyzer dump
258 * file formats we support (pcap and pcap-ng), and several other
259 * formats we might support in the future (such as snoop, DOS and
260 * Windows Sniffer, and Microsoft Network Monitor) all have magic
261 * numbers that are unique in their first 4 bytes.
262 */
263 amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
264 if (amt_read != sizeof(magic)) {
efca1c6 @yuguy Report short reads on the file header (as opposed to errors on it)
yuguy authored
265 if (ferror(fp)) {
266 snprintf(errbuf, PCAP_ERRBUF_SIZE,
267 "error reading dump file: %s",
268 pcap_strerror(errno));
269 } else {
270 snprintf(errbuf, PCAP_ERRBUF_SIZE,
271 "truncated dump file; tried to read %lu file header bytes, only got %lu",
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
272 (unsigned long)sizeof(magic),
54b7cfb @yuguy Squelch a (valid) compiler warning.
yuguy authored
273 (unsigned long)amt_read);
efca1c6 @yuguy Report short reads on the file header (as opposed to errors on it)
yuguy authored
274 }
b11ddf8 Initial revision
mcr authored
275 goto bad;
276 }
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
277
278 /*
279 * Try all file types.
280 */
281 for (i = 0; i < N_FILE_TYPES; i++) {
282 switch ((*check_headers[i])(p, magic, fp, errbuf)) {
283
284 case -1:
285 /*
286 * Error trying to read the header.
287 */
b11ddf8 Initial revision
mcr authored
288 goto bad;
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
289
290 case 1:
291 /*
292 * Yup, that's it.
293 */
294 goto found;
b11ddf8 Initial revision
mcr authored
295 }
296 }
297
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
298 /*
299 * Well, who knows what this mess is....
300 */
301 snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
302 goto bad;
b11ddf8 Initial revision
mcr authored
303
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
304 found:
305 p->sf.rfile = fp;
b11ddf8 Initial revision
mcr authored
306
307 #ifdef PCAP_FDDIPAD
3573dfd @yuguy Put the FDDI padding (if any) into the pcap_t structure on platforms
yuguy authored
308 /* Padding only needed for live capture fcode */
309 p->fddipad = 0;
b11ddf8 Initial revision
mcr authored
310 #endif
311
f8a76d1 @yuguy From Gisle Vanem: MS-DOS support.
yuguy authored
312 #if !defined(WIN32) && !defined(MSDOS)
c98ffbc @yuguy Add a "pcap_get_selectable_fd()" API to get an FD on which you can do a
yuguy authored
313 /*
314 * You can do "select()" and "poll()" on plain files on most
315 * platforms, and should be able to do so on pipes.
175b9d7 @yuguy "selectable_fd" doesn't make sense on Windows.
yuguy authored
316 *
317 * You can't do "select()" on anything other than sockets in
318 * Windows, so, on Win32 systems, we don't have "selectable_fd".
c98ffbc @yuguy Add a "pcap_get_selectable_fd()" API to get an FD on which you can do a
yuguy authored
319 */
320 p->selectable_fd = fileno(fp);
175b9d7 @yuguy "selectable_fd" doesn't make sense on Windows.
yuguy authored
321 #endif
c98ffbc @yuguy Add a "pcap_get_selectable_fd()" API to get an FD on which you can do a
yuguy authored
322
cd0d893 @yuguy Add a "read" function pointer to the pcap_t structure, which handles
yuguy authored
323 p->read_op = pcap_offline_read;
2d2890d @yuguy Add support for sending packets; includes contributions from Mark
yuguy authored
324 p->inject_op = sf_inject;
cd2807e @yuguy Add a "setfilter" function pointer to the pcap_t structure, which
yuguy authored
325 p->setfilter_op = install_bpf_program;
9c2ab75 @yuguy Give a more correct error if you try to set the direction when reading
yuguy authored
326 p->setdirection_op = sf_setdirection;
08658f1 @yuguy Add a "set_datalink" function pointer to the pcap_t structure, whichhand...
yuguy authored
327 p->set_datalink_op = NULL; /* we don't support munging link-layer headers */
2c618b9 @yuguy Add "getnonblock" and "setnonblock" operations, and set the function
yuguy authored
328 p->getnonblock_op = sf_getnonblock;
329 p->setnonblock_op = sf_setnonblock;
9792990 @yuguy Add a "stats" function pointer to the pcap_t structure, which handles
yuguy authored
330 p->stats_op = sf_stats;
3a0937c @yuguy On Win32, have pcap_setbuff, pcap_setmode, and pcap_setmintocopy ops, so
yuguy authored
331 #ifdef WIN32
332 p->setbuff_op = sf_setbuff;
333 p->setmode_op = sf_setmode;
334 p->setmintocopy_op = sf_setmintocopy;
335 #endif
2527d1a @yuguy Turn close_op into cleanup_op; the routine that handles it can also be
yuguy authored
336 p->cleanup_op = sf_cleanup;
d9b4202 @yuguy From Paolo Abeni and me: split pcap_open_live() into a "get a pcap_t
yuguy authored
337 p->activated = 1;
e648c9e @yuguy Add a "close" function pointer to the pcap_t structure, which handles
yuguy authored
338
b11ddf8 Initial revision
mcr authored
339 return (p);
340 bad:
341 free(p);
342 return (NULL);
343 }
344
345 /*
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
346 * Read packets from a capture file, and call the callback for each
347 * packet.
b11ddf8 Initial revision
mcr authored
348 * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
349 */
350 int
351 pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
352 {
6dc4f10 @yuguy From Dug Song <dugsong@monkey.org>: don't fetch the filter code until
yuguy authored
353 struct bpf_insn *fcode;
b11ddf8 Initial revision
mcr authored
354 int status = 0;
355 int n = 0;
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
356 u_char *data;
b11ddf8 Initial revision
mcr authored
357
358 while (status == 0) {
359 struct pcap_pkthdr h;
360
991d444 @yuguy Add a "pcap_breakloop()" API to break out of the loop in
yuguy authored
361 /*
362 * Has "pcap_breakloop()" been called?
363 * If so, return immediately - if we haven't read any
364 * packets, clear the flag and return -2 to indicate
365 * that we were told to break out of the loop, otherwise
366 * leave the flag set, so that the *next* call will break
367 * out of the loop without having read any packets, and
368 * return the number of packets we've processed so far.
369 */
370 if (p->break_loop) {
371 if (n == 0) {
372 p->break_loop = 0;
373 return (-2);
374 } else
375 return (n);
376 }
377
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
378 status = p->sf.next_packet_op(p, &h, &data);
b11ddf8 Initial revision
mcr authored
379 if (status) {
380 if (status == 1)
381 return (0);
382 return (status);
383 }
384
6dc4f10 @yuguy From Dug Song <dugsong@monkey.org>: don't fetch the filter code until
yuguy authored
385 if ((fcode = p->fcode.bf_insns) == NULL ||
3127856 @guyharris Pass the right packet data pointer to bpf_filter().
guyharris authored
386 bpf_filter(fcode, data, h.len, h.caplen)) {
b4b6648 @guyharris Add limited support for reading pcap-ng files.
guyharris authored
387 (*callback)(user, &h, data);
b11ddf8 Initial revision
mcr authored
388 if (++n >= cnt && cnt > 0)
389 break;
390 }
391 }
392 /*XXX this breaks semantics tcpslice expects */
393 return (n);
394 }
Something went wrong with that request. Please try again.