pcap.c revision 109839
1/*
2 * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
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 the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the Computer Systems
16 *	Engineering Group at Lawrence Berkeley Laboratory.
17 * 4. Neither the name of the University nor of the Laboratory may be used
18 *    to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static const char rcsid[] =
36    "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.38 2001/12/29 21:55:32 guy Exp $ (LBL)";
37#endif
38
39#ifdef HAVE_CONFIG_H
40#include "config.h"
41#endif
42
43#include <sys/types.h>
44
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49#include <fcntl.h>
50#include <errno.h>
51
52#ifdef HAVE_OS_PROTO_H
53#include "os-proto.h"
54#endif
55
56#include "pcap-int.h"
57
58int
59pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
60{
61
62	if (p->sf.rfile != NULL)
63		return (pcap_offline_read(p, cnt, callback, user));
64	return (pcap_read(p, cnt, callback, user));
65}
66
67int
68pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
69{
70	register int n;
71
72	for (;;) {
73		if (p->sf.rfile != NULL)
74			n = pcap_offline_read(p, cnt, callback, user);
75		else {
76			/*
77			 * XXX keep reading until we get something
78			 * (or an error occurs)
79			 */
80			do {
81				n = pcap_read(p, cnt, callback, user);
82			} while (n == 0);
83		}
84		if (n <= 0)
85			return (n);
86		if (cnt > 0) {
87			cnt -= n;
88			if (cnt <= 0)
89				return (0);
90		}
91	}
92}
93
94struct singleton {
95	struct pcap_pkthdr *hdr;
96	const u_char *pkt;
97};
98
99
100static void
101pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt)
102{
103	struct singleton *sp = (struct singleton *)userData;
104	*sp->hdr = *h;
105	sp->pkt = pkt;
106}
107
108const u_char *
109pcap_next(pcap_t *p, struct pcap_pkthdr *h)
110{
111	struct singleton s;
112
113	s.hdr = h;
114	if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0)
115		return (0);
116	return (s.pkt);
117}
118
119int
120pcap_datalink(pcap_t *p)
121{
122	return (p->linktype);
123}
124
125int
126pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
127{
128	if (p->dlt_count <= 0) {
129		*dlt_buffer = NULL;
130		return -1;
131	}
132	*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer) * p->dlt_count);
133	if (*dlt_buffer == NULL) {
134		(void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s",
135		    pcap_strerror(errno));
136		return -1;
137	}
138	(void)memcpy(*dlt_buffer, p->dlt_list,
139	    sizeof(**dlt_buffer) * p->dlt_count);
140	return (p->dlt_count);
141}
142
143int
144pcap_snapshot(pcap_t *p)
145{
146	return (p->snapshot);
147}
148
149int
150pcap_is_swapped(pcap_t *p)
151{
152	return (p->sf.swapped);
153}
154
155int
156pcap_major_version(pcap_t *p)
157{
158	return (p->sf.version_major);
159}
160
161int
162pcap_minor_version(pcap_t *p)
163{
164	return (p->sf.version_minor);
165}
166
167FILE *
168pcap_file(pcap_t *p)
169{
170	return (p->sf.rfile);
171}
172
173int
174pcap_fileno(pcap_t *p)
175{
176	return (p->fd);
177}
178
179void
180pcap_perror(pcap_t *p, char *prefix)
181{
182	fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
183}
184
185char *
186pcap_geterr(pcap_t *p)
187{
188	return (p->errbuf);
189}
190
191/*
192 * NOTE: in the future, these may need to call platform-dependent routines,
193 * e.g. on platforms with memory-mapped packet-capture mechanisms where
194 * "pcap_read()" uses "select()" or "poll()" to wait for packets to arrive.
195 */
196int
197pcap_getnonblock(pcap_t *p, char *errbuf)
198{
199	int fdflags;
200
201	if (p->sf.rfile != NULL) {
202		/*
203		 * This is a savefile, not a live capture file, so
204		 * never say it's in non-blocking mode.
205		 */
206		return (0);
207	}
208	fdflags = fcntl(p->fd, F_GETFL, 0);
209	if (fdflags == -1) {
210		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
211		    pcap_strerror(errno));
212		return (-1);
213	}
214	if (fdflags & O_NONBLOCK)
215		return (1);
216	else
217		return (0);
218}
219
220int
221pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
222{
223	int fdflags;
224
225	if (p->sf.rfile != NULL) {
226		/*
227		 * This is a savefile, not a live capture file, so
228		 * ignore requests to put it in non-blocking mode.
229		 */
230		return (0);
231	}
232	fdflags = fcntl(p->fd, F_GETFL, 0);
233	if (fdflags == -1) {
234		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
235		    pcap_strerror(errno));
236		return (-1);
237	}
238	if (nonblock)
239		fdflags |= O_NONBLOCK;
240	else
241		fdflags &= ~O_NONBLOCK;
242	if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
243		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
244		    pcap_strerror(errno));
245		return (-1);
246	}
247	return (0);
248}
249
250/*
251 * Not all systems have strerror().
252 */
253char *
254pcap_strerror(int errnum)
255{
256#ifdef HAVE_STRERROR
257	return (strerror(errnum));
258#else
259	extern int sys_nerr;
260	extern const char *const sys_errlist[];
261	static char ebuf[20];
262
263	if ((unsigned int)errnum < sys_nerr)
264		return ((char *)sys_errlist[errnum]);
265	(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
266	return(ebuf);
267#endif
268}
269
270pcap_t *
271pcap_open_dead(int linktype, int snaplen)
272{
273	pcap_t *p;
274
275	p = malloc(sizeof(*p));
276	if (p == NULL)
277		return NULL;
278	memset (p, 0, sizeof(*p));
279	p->fd = -1;
280	p->snapshot = snaplen;
281	p->linktype = linktype;
282	return p;
283}
284
285void
286pcap_close(pcap_t *p)
287{
288	/*XXX*/
289	if (p->fd >= 0) {
290#ifdef linux
291		pcap_close_linux(p);
292#endif
293		close(p->fd);
294	}
295	if (p->sf.rfile != NULL) {
296		if (p->sf.rfile != stdin)
297			(void)fclose(p->sf.rfile);
298		if (p->sf.base != NULL)
299			free(p->sf.base);
300	} else if (p->buffer != NULL)
301		free(p->buffer);
302	if (p->dlt_list != NULL)
303		free(p->dlt_list);
304
305	pcap_freecode(&p->fcode);
306	free(p);
307}
308