pcap.c revision 75107
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.36 2000/12/16 10:43:31 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
50#ifdef HAVE_OS_PROTO_H
51#include "os-proto.h"
52#endif
53
54#include "pcap-int.h"
55
56int
57pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
58{
59
60	if (p->sf.rfile != NULL)
61		return (pcap_offline_read(p, cnt, callback, user));
62	return (pcap_read(p, cnt, callback, user));
63}
64
65int
66pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
67{
68	register int n;
69
70	for (;;) {
71		if (p->sf.rfile != NULL)
72			n = pcap_offline_read(p, cnt, callback, user);
73		else {
74			/*
75			 * XXX keep reading until we get something
76			 * (or an error occurs)
77			 */
78			do {
79				n = pcap_read(p, cnt, callback, user);
80			} while (n == 0);
81		}
82		if (n <= 0)
83			return (n);
84		if (cnt > 0) {
85			cnt -= n;
86			if (cnt <= 0)
87				return (0);
88		}
89	}
90}
91
92struct singleton {
93	struct pcap_pkthdr *hdr;
94	const u_char *pkt;
95};
96
97
98static void
99pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt)
100{
101	struct singleton *sp = (struct singleton *)userData;
102	*sp->hdr = *h;
103	sp->pkt = pkt;
104}
105
106const u_char *
107pcap_next(pcap_t *p, struct pcap_pkthdr *h)
108{
109	struct singleton s;
110
111	s.hdr = h;
112	if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0)
113		return (0);
114	return (s.pkt);
115}
116
117int
118pcap_datalink(pcap_t *p)
119{
120	return (p->linktype);
121}
122
123int
124pcap_snapshot(pcap_t *p)
125{
126	return (p->snapshot);
127}
128
129int
130pcap_is_swapped(pcap_t *p)
131{
132	return (p->sf.swapped);
133}
134
135int
136pcap_major_version(pcap_t *p)
137{
138	return (p->sf.version_major);
139}
140
141int
142pcap_minor_version(pcap_t *p)
143{
144	return (p->sf.version_minor);
145}
146
147FILE *
148pcap_file(pcap_t *p)
149{
150	return (p->sf.rfile);
151}
152
153int
154pcap_fileno(pcap_t *p)
155{
156	return (p->fd);
157}
158
159void
160pcap_perror(pcap_t *p, char *prefix)
161{
162	fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
163}
164
165char *
166pcap_geterr(pcap_t *p)
167{
168	return (p->errbuf);
169}
170
171/*
172 * Not all systems have strerror().
173 */
174char *
175pcap_strerror(int errnum)
176{
177#ifdef HAVE_STRERROR
178	return (strerror(errnum));
179#else
180	extern int sys_nerr;
181	extern const char *const sys_errlist[];
182	static char ebuf[20];
183
184	if ((unsigned int)errnum < sys_nerr)
185		return ((char *)sys_errlist[errnum]);
186	(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
187	return(ebuf);
188#endif
189}
190
191pcap_t *
192pcap_open_dead(int linktype, int snaplen)
193{
194	pcap_t *p;
195
196	p = malloc(sizeof(*p));
197	if (p == NULL)
198		return NULL;
199	memset (p, 0, sizeof(*p));
200	p->fd = -1;
201	p->snapshot = snaplen;
202	p->linktype = linktype;
203	return p;
204}
205
206void
207pcap_close(pcap_t *p)
208{
209	/*XXX*/
210	if (p->fd >= 0) {
211#ifdef linux
212		pcap_close_linux(p);
213#endif
214		close(p->fd);
215	}
216	if (p->sf.rfile != NULL) {
217		if (p->sf.rfile != stdin)
218			(void)fclose(p->sf.rfile);
219		if (p->sf.base != NULL)
220			free(p->sf.base);
221	} else if (p->buffer != NULL)
222		free(p->buffer);
223
224	pcap_freecode(&p->fcode);
225	free(p);
226}
227