source: rtems-libbsd/freebsd/contrib/libpcap/savefile.c @ 3d1e767

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 3d1e767 was 3d1e767, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/16 at 08:25:22

Directly use <sys/types.h> provided by Newlib

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