xref: /openbsd-src/lib/libpcap/pcap.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: pcap.c,v 1.6 1999/07/20 04:49:55 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
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 the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the Computer Systems
18  *	Engineering Group at Lawrence Berkeley Laboratory.
19  * 4. Neither the name of the University nor of the Laboratory may be used
20  *    to endorse or promote products derived from this software without
21  *    specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifndef lint
37 static const char rcsid[] =
38     "@(#) $Header: /home/cvs/src/lib/libpcap/pcap.c,v 1.6 1999/07/20 04:49:55 deraadt Exp $ (LBL)";
39 #endif
40 
41 #include <sys/types.h>
42 
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 
48 #ifdef HAVE_OS_PROTO_H
49 #include "os-proto.h"
50 #endif
51 
52 #include "pcap-int.h"
53 
54 int
55 pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
56 {
57 
58 	if (p->sf.rfile != NULL)
59 		return (pcap_offline_read(p, cnt, callback, user));
60 	return (pcap_read(p, cnt, callback, user));
61 }
62 
63 int
64 pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
65 {
66 	register int n;
67 
68 	for (;;) {
69 		if (p->sf.rfile != NULL)
70 			n = pcap_offline_read(p, cnt, callback, user);
71 		else {
72 			/*
73 			 * XXX keep reading until we get something
74 			 * (or an error occurs)
75 			 */
76 			do {
77 				n = pcap_read(p, cnt, callback, user);
78 			} while (n == 0);
79 		}
80 		if (n <= 0)
81 			return (n);
82 		if (cnt > 0) {
83 			cnt -= n;
84 			if (cnt <= 0)
85 				return (0);
86 		}
87 	}
88 }
89 
90 struct singleton {
91 	struct pcap_pkthdr *hdr;
92 	const u_char *pkt;
93 };
94 
95 
96 static void
97 pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt)
98 {
99 	struct singleton *sp = (struct singleton *)userData;
100 	*sp->hdr = *h;
101 	sp->pkt = pkt;
102 }
103 
104 const u_char *
105 pcap_next(pcap_t *p, struct pcap_pkthdr *h)
106 {
107 	struct singleton s;
108 
109 	s.hdr = h;
110 	if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0)
111 		return (0);
112 	return (s.pkt);
113 }
114 
115 int
116 pcap_datalink(pcap_t *p)
117 {
118 	return (p->linktype);
119 }
120 
121 int
122 pcap_snapshot(pcap_t *p)
123 {
124 	return (p->snapshot);
125 }
126 
127 int
128 pcap_is_swapped(pcap_t *p)
129 {
130 	return (p->sf.swapped);
131 }
132 
133 int
134 pcap_major_version(pcap_t *p)
135 {
136 	return (p->sf.version_major);
137 }
138 
139 int
140 pcap_minor_version(pcap_t *p)
141 {
142 	return (p->sf.version_minor);
143 }
144 
145 FILE *
146 pcap_file(pcap_t *p)
147 {
148 	return (p->sf.rfile);
149 }
150 
151 int
152 pcap_fileno(pcap_t *p)
153 {
154 	return (p->fd);
155 }
156 
157 void
158 pcap_perror(pcap_t *p, char *prefix)
159 {
160 	fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
161 }
162 
163 char *
164 pcap_geterr(pcap_t *p)
165 {
166 	return (p->errbuf);
167 }
168 
169 /*
170  * Not all systems have strerror().
171  */
172 char *
173 pcap_strerror(int errnum)
174 {
175 #ifdef HAVE_STRERROR
176 	return (strerror(errnum));
177 #else
178 	extern int sys_nerr;
179 	extern const char *const sys_errlist[];
180 	static char ebuf[20];
181 
182 	if ((unsigned int)errnum < sys_nerr)
183 		return ((char *)sys_errlist[errnum]);
184 	(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
185 	return(ebuf);
186 #endif
187 }
188 
189 void
190 pcap_close(pcap_t *p)
191 {
192 	/*XXX*/
193 	if (p->fd >= 0)
194 		close(p->fd);
195 	if (p->sf.rfile != NULL) {
196 		(void)fclose(p->sf.rfile);
197 		if (p->sf.base != NULL)
198 			free(p->sf.base);
199 	} else if (p->buffer != NULL)
200 		free(p->buffer);
201 #ifdef linux
202 	if (p->md.device != NULL)
203 		free(p->md.device);
204 #endif
205 
206 	free(p);
207 }
208