savefile.c revision 1.1 1 1.1 christos /*
2 1.1 christos * Copyright (c) 1993, 1994, 1995, 1996, 1997
3 1.1 christos * The Regents of the University of California. All rights reserved.
4 1.1 christos *
5 1.1 christos * Redistribution and use in source and binary forms, with or without
6 1.1 christos * modification, are permitted provided that: (1) source code distributions
7 1.1 christos * retain the above copyright notice and this paragraph in its entirety, (2)
8 1.1 christos * distributions including binary code include the above copyright notice and
9 1.1 christos * this paragraph in its entirety in the documentation or other materials
10 1.1 christos * provided with the distribution, and (3) all advertising materials mentioning
11 1.1 christos * features or use of this software display the following acknowledgement:
12 1.1 christos * ``This product includes software developed by the University of California,
13 1.1 christos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 1.1 christos * the University nor the names of its contributors may be used to endorse
15 1.1 christos * or promote products derived from this software without specific prior
16 1.1 christos * written permission.
17 1.1 christos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 1.1 christos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 1.1 christos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 1.1 christos *
21 1.1 christos * savefile.c - supports offline use of tcpdump
22 1.1 christos * Extraction/creation by Jeffrey Mogul, DECWRL
23 1.1 christos * Modified by Steve McCanne, LBL.
24 1.1 christos *
25 1.1 christos * Used to save the received packet headers, after filtering, to
26 1.1 christos * a file, and then read them later.
27 1.1 christos * The first record in the file contains saved values for the machine
28 1.1 christos * dependent values so we can print the dump file on any architecture.
29 1.1 christos */
30 1.1 christos
31 1.1 christos #ifndef lint
32 1.1 christos static const char rcsid[] _U_ =
33 1.1 christos "@(#) $Header: /tank/opengrok/rsync2/NetBSD/src/external/bsd/libpcap/dist/savefile.c,v 1.1 2010/12/05 01:20:44 christos Exp $ (LBL)";
34 1.1 christos #endif
35 1.1 christos
36 1.1 christos #ifdef HAVE_CONFIG_H
37 1.1 christos #include "config.h"
38 1.1 christos #endif
39 1.1 christos
40 1.1 christos #ifdef WIN32
41 1.1 christos #include <pcap-stdinc.h>
42 1.1 christos #else /* WIN32 */
43 1.1 christos #if HAVE_INTTYPES_H
44 1.1 christos #include <inttypes.h>
45 1.1 christos #elif HAVE_STDINT_H
46 1.1 christos #include <stdint.h>
47 1.1 christos #endif
48 1.1 christos #ifdef HAVE_SYS_BITYPES_H
49 1.1 christos #include <sys/bitypes.h>
50 1.1 christos #endif
51 1.1 christos #include <sys/types.h>
52 1.1 christos #endif /* WIN32 */
53 1.1 christos
54 1.1 christos #include <errno.h>
55 1.1 christos #include <memory.h>
56 1.1 christos #include <stdio.h>
57 1.1 christos #include <stdlib.h>
58 1.1 christos #include <string.h>
59 1.1 christos
60 1.1 christos #include "pcap-int.h"
61 1.1 christos #include "pcap/usb.h"
62 1.1 christos
63 1.1 christos #ifdef HAVE_OS_PROTO_H
64 1.1 christos #include "os-proto.h"
65 1.1 christos #endif
66 1.1 christos
67 1.1 christos #include "sf-pcap.h"
68 1.1 christos #include "sf-pcap-ng.h"
69 1.1 christos
70 1.1 christos /*
71 1.1 christos * Setting O_BINARY on DOS/Windows is a bit tricky
72 1.1 christos */
73 1.1 christos #if defined(WIN32)
74 1.1 christos #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY)
75 1.1 christos #elif defined(MSDOS)
76 1.1 christos #if defined(__HIGHC__)
77 1.1 christos #define SET_BINMODE(f) setmode(f, O_BINARY)
78 1.1 christos #else
79 1.1 christos #define SET_BINMODE(f) setmode(fileno(f), O_BINARY)
80 1.1 christos #endif
81 1.1 christos #endif
82 1.1 christos
83 1.1 christos static int
84 1.1 christos sf_getnonblock(pcap_t *p, char *errbuf)
85 1.1 christos {
86 1.1 christos /*
87 1.1 christos * This is a savefile, not a live capture file, so never say
88 1.1 christos * it's in non-blocking mode.
89 1.1 christos */
90 1.1 christos return (0);
91 1.1 christos }
92 1.1 christos
93 1.1 christos static int
94 1.1 christos sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
95 1.1 christos {
96 1.1 christos /*
97 1.1 christos * This is a savefile, not a live capture file, so ignore
98 1.1 christos * requests to put it in non-blocking mode.
99 1.1 christos */
100 1.1 christos return (0);
101 1.1 christos }
102 1.1 christos
103 1.1 christos static int
104 1.1 christos sf_stats(pcap_t *p, struct pcap_stat *ps)
105 1.1 christos {
106 1.1 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
107 1.1 christos "Statistics aren't available from savefiles");
108 1.1 christos return (-1);
109 1.1 christos }
110 1.1 christos
111 1.1 christos #ifdef WIN32
112 1.1 christos static int
113 1.1 christos sf_setbuff(pcap_t *p, int dim)
114 1.1 christos {
115 1.1 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
116 1.1 christos "The kernel buffer size cannot be set while reading from a file");
117 1.1 christos return (-1);
118 1.1 christos }
119 1.1 christos
120 1.1 christos static int
121 1.1 christos sf_setmode(pcap_t *p, int mode)
122 1.1 christos {
123 1.1 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
124 1.1 christos "impossible to set mode while reading from a file");
125 1.1 christos return (-1);
126 1.1 christos }
127 1.1 christos
128 1.1 christos static int
129 1.1 christos sf_setmintocopy(pcap_t *p, int size)
130 1.1 christos {
131 1.1 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
132 1.1 christos "The mintocopy parameter cannot be set while reading from a file");
133 1.1 christos return (-1);
134 1.1 christos }
135 1.1 christos #endif
136 1.1 christos
137 1.1 christos static int
138 1.1 christos sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
139 1.1 christos {
140 1.1 christos strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
141 1.1 christos PCAP_ERRBUF_SIZE);
142 1.1 christos return (-1);
143 1.1 christos }
144 1.1 christos
145 1.1 christos /*
146 1.1 christos * Set direction flag: Which packets do we accept on a forwarding
147 1.1 christos * single device? IN, OUT or both?
148 1.1 christos */
149 1.1 christos static int
150 1.1 christos sf_setdirection(pcap_t *p, pcap_direction_t d)
151 1.1 christos {
152 1.1 christos snprintf(p->errbuf, sizeof(p->errbuf),
153 1.1 christos "Setting direction is not supported on savefiles");
154 1.1 christos return (-1);
155 1.1 christos }
156 1.1 christos
157 1.1 christos static void
158 1.1 christos sf_cleanup(pcap_t *p)
159 1.1 christos {
160 1.1 christos if (p->sf.rfile != stdin)
161 1.1 christos (void)fclose(p->sf.rfile);
162 1.1 christos if (p->buffer != NULL)
163 1.1 christos free(p->buffer);
164 1.1 christos }
165 1.1 christos
166 1.1 christos pcap_t *
167 1.1 christos pcap_open_offline(const char *fname, char *errbuf)
168 1.1 christos {
169 1.1 christos FILE *fp;
170 1.1 christos pcap_t *p;
171 1.1 christos
172 1.1 christos if (fname[0] == '-' && fname[1] == '\0')
173 1.1 christos {
174 1.1 christos fp = stdin;
175 1.1 christos #if defined(WIN32) || defined(MSDOS)
176 1.1 christos /*
177 1.1 christos * We're reading from the standard input, so put it in binary
178 1.1 christos * mode, as savefiles are binary files.
179 1.1 christos */
180 1.1 christos SET_BINMODE(fp);
181 1.1 christos #endif
182 1.1 christos }
183 1.1 christos else {
184 1.1 christos #if !defined(WIN32) && !defined(MSDOS)
185 1.1 christos fp = fopen(fname, "r");
186 1.1 christos #else
187 1.1 christos fp = fopen(fname, "rb");
188 1.1 christos #endif
189 1.1 christos if (fp == NULL) {
190 1.1 christos snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
191 1.1 christos pcap_strerror(errno));
192 1.1 christos return (NULL);
193 1.1 christos }
194 1.1 christos }
195 1.1 christos p = pcap_fopen_offline(fp, errbuf);
196 1.1 christos if (p == NULL) {
197 1.1 christos if (fp != stdin)
198 1.1 christos fclose(fp);
199 1.1 christos }
200 1.1 christos return (p);
201 1.1 christos }
202 1.1 christos
203 1.1 christos #ifdef WIN32
204 1.1 christos pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
205 1.1 christos {
206 1.1 christos int fd;
207 1.1 christos FILE *file;
208 1.1 christos
209 1.1 christos fd = _open_osfhandle(osfd, _O_RDONLY);
210 1.1 christos if ( fd < 0 )
211 1.1 christos {
212 1.1 christos snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
213 1.1 christos return NULL;
214 1.1 christos }
215 1.1 christos
216 1.1 christos file = _fdopen(fd, "rb");
217 1.1 christos if ( file == NULL )
218 1.1 christos {
219 1.1 christos snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
220 1.1 christos return NULL;
221 1.1 christos }
222 1.1 christos
223 1.1 christos return pcap_fopen_offline(file, errbuf);
224 1.1 christos }
225 1.1 christos #endif
226 1.1 christos
227 1.1 christos static int (*check_headers[])(pcap_t *, bpf_u_int32, FILE *, char *) = {
228 1.1 christos pcap_check_header,
229 1.1 christos pcap_ng_check_header
230 1.1 christos };
231 1.1 christos
232 1.1 christos #define N_FILE_TYPES (sizeof check_headers / sizeof check_headers[0])
233 1.1 christos
234 1.1 christos #ifdef WIN32
235 1.1 christos static
236 1.1 christos #endif
237 1.1 christos pcap_t *
238 1.1 christos pcap_fopen_offline(FILE *fp, char *errbuf)
239 1.1 christos {
240 1.1 christos register pcap_t *p;
241 1.1 christos bpf_u_int32 magic;
242 1.1 christos size_t amt_read;
243 1.1 christos u_int i;
244 1.1 christos
245 1.1 christos p = pcap_create_common("(savefile)", errbuf);
246 1.1 christos if (p == NULL)
247 1.1 christos return (NULL);
248 1.1 christos
249 1.1 christos /*
250 1.1 christos * Read the first 4 bytes of the file; the network analyzer dump
251 1.1 christos * file formats we support (pcap and pcap-ng), and several other
252 1.1 christos * formats we might support in the future (such as snoop, DOS and
253 1.1 christos * Windows Sniffer, and Microsoft Network Monitor) all have magic
254 1.1 christos * numbers that are unique in their first 4 bytes.
255 1.1 christos */
256 1.1 christos amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
257 1.1 christos if (amt_read != sizeof(magic)) {
258 1.1 christos if (ferror(fp)) {
259 1.1 christos snprintf(errbuf, PCAP_ERRBUF_SIZE,
260 1.1 christos "error reading dump file: %s",
261 1.1 christos pcap_strerror(errno));
262 1.1 christos } else {
263 1.1 christos snprintf(errbuf, PCAP_ERRBUF_SIZE,
264 1.1 christos "truncated dump file; tried to read %lu file header bytes, only got %lu",
265 1.1 christos (unsigned long)sizeof(magic),
266 1.1 christos (unsigned long)amt_read);
267 1.1 christos }
268 1.1 christos goto bad;
269 1.1 christos }
270 1.1 christos
271 1.1 christos /*
272 1.1 christos * Try all file types.
273 1.1 christos */
274 1.1 christos for (i = 0; i < N_FILE_TYPES; i++) {
275 1.1 christos switch ((*check_headers[i])(p, magic, fp, errbuf)) {
276 1.1 christos
277 1.1 christos case -1:
278 1.1 christos /*
279 1.1 christos * Error trying to read the header.
280 1.1 christos */
281 1.1 christos goto bad;
282 1.1 christos
283 1.1 christos case 1:
284 1.1 christos /*
285 1.1 christos * Yup, that's it.
286 1.1 christos */
287 1.1 christos goto found;
288 1.1 christos }
289 1.1 christos }
290 1.1 christos
291 1.1 christos /*
292 1.1 christos * Well, who knows what this mess is....
293 1.1 christos */
294 1.1 christos snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
295 1.1 christos goto bad;
296 1.1 christos
297 1.1 christos found:
298 1.1 christos p->sf.rfile = fp;
299 1.1 christos
300 1.1 christos #ifdef PCAP_FDDIPAD
301 1.1 christos /* Padding only needed for live capture fcode */
302 1.1 christos p->fddipad = 0;
303 1.1 christos #endif
304 1.1 christos
305 1.1 christos #if !defined(WIN32) && !defined(MSDOS)
306 1.1 christos /*
307 1.1 christos * You can do "select()" and "poll()" on plain files on most
308 1.1 christos * platforms, and should be able to do so on pipes.
309 1.1 christos *
310 1.1 christos * You can't do "select()" on anything other than sockets in
311 1.1 christos * Windows, so, on Win32 systems, we don't have "selectable_fd".
312 1.1 christos */
313 1.1 christos p->selectable_fd = fileno(fp);
314 1.1 christos #endif
315 1.1 christos
316 1.1 christos p->read_op = pcap_offline_read;
317 1.1 christos p->inject_op = sf_inject;
318 1.1 christos p->setfilter_op = install_bpf_program;
319 1.1 christos p->setdirection_op = sf_setdirection;
320 1.1 christos p->set_datalink_op = NULL; /* we don't support munging link-layer headers */
321 1.1 christos p->getnonblock_op = sf_getnonblock;
322 1.1 christos p->setnonblock_op = sf_setnonblock;
323 1.1 christos p->stats_op = sf_stats;
324 1.1 christos #ifdef WIN32
325 1.1 christos p->setbuff_op = sf_setbuff;
326 1.1 christos p->setmode_op = sf_setmode;
327 1.1 christos p->setmintocopy_op = sf_setmintocopy;
328 1.1 christos #endif
329 1.1 christos p->cleanup_op = sf_cleanup;
330 1.1 christos p->activated = 1;
331 1.1 christos
332 1.1 christos return (p);
333 1.1 christos bad:
334 1.1 christos free(p);
335 1.1 christos return (NULL);
336 1.1 christos }
337 1.1 christos
338 1.1 christos /*
339 1.1 christos * Read packets from a capture file, and call the callback for each
340 1.1 christos * packet.
341 1.1 christos * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
342 1.1 christos */
343 1.1 christos int
344 1.1 christos pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
345 1.1 christos {
346 1.1 christos struct bpf_insn *fcode;
347 1.1 christos int status = 0;
348 1.1 christos int n = 0;
349 1.1 christos u_char *data;
350 1.1 christos
351 1.1 christos while (status == 0) {
352 1.1 christos struct pcap_pkthdr h;
353 1.1 christos
354 1.1 christos /*
355 1.1 christos * Has "pcap_breakloop()" been called?
356 1.1 christos * If so, return immediately - if we haven't read any
357 1.1 christos * packets, clear the flag and return -2 to indicate
358 1.1 christos * that we were told to break out of the loop, otherwise
359 1.1 christos * leave the flag set, so that the *next* call will break
360 1.1 christos * out of the loop without having read any packets, and
361 1.1 christos * return the number of packets we've processed so far.
362 1.1 christos */
363 1.1 christos if (p->break_loop) {
364 1.1 christos if (n == 0) {
365 1.1 christos p->break_loop = 0;
366 1.1 christos return (-2);
367 1.1 christos } else
368 1.1 christos return (n);
369 1.1 christos }
370 1.1 christos
371 1.1 christos status = p->sf.next_packet_op(p, &h, &data);
372 1.1 christos if (status) {
373 1.1 christos if (status == 1)
374 1.1 christos return (0);
375 1.1 christos return (status);
376 1.1 christos }
377 1.1 christos
378 1.1 christos if ((fcode = p->fcode.bf_insns) == NULL ||
379 1.1 christos bpf_filter(fcode, p->buffer, h.len, h.caplen)) {
380 1.1 christos (*callback)(user, &h, data);
381 1.1 christos if (++n >= cnt && cnt > 0)
382 1.1 christos break;
383 1.1 christos }
384 1.1 christos }
385 1.1 christos /*XXX this breaks semantics tcpslice expects */
386 1.1 christos return (n);
387 1.1 christos }
388