1 /* $OpenBSD: pcap-bpf.c,v 1.20 2006/03/26 20:58:51 djm Exp $ */
2
3 /*
4 * Copyright (c) 1993, 1994, 1995, 1996, 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: (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
24 #include <sys/param.h> /* optionally get BSD define */
25 #include <sys/time.h>
26 #include <sys/timeb.h>
27 #include <sys/socket.h>
28 #include <sys/ioctl.h>
29
30 #include <net/if.h>
31
32 #include <ctype.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <netdb.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include "pcap-int.h"
42
43 #ifdef HAVE_OS_PROTO_H
44 #include "os-proto.h"
45 #endif
46
47 #include "gencode.h"
48
49 int
pcap_stats(pcap_t * p,struct pcap_stat * ps)50 pcap_stats(pcap_t *p, struct pcap_stat *ps)
51 {
52 struct bpf_stat s;
53
54 if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
55 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
56 pcap_strerror(errno));
57 return (-1);
58 }
59
60 ps->ps_recv = s.bs_recv;
61 ps->ps_drop = s.bs_drop;
62 return (0);
63 }
64
65 int
pcap_read(pcap_t * p,int cnt,pcap_handler callback,u_char * user)66 pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
67 {
68 int cc;
69 int n = 0;
70 register u_char *bp, *ep;
71
72 again:
73 /*
74 * Has "pcap_breakloop()" been called?
75 */
76 if (p->break_loop) {
77 /*
78 * Yes - clear the flag that indicates that it
79 * has, and return -2 to indicate that we were
80 * told to break out of the loop.
81 */
82 p->break_loop = 0;
83 return (-2);
84 }
85
86 cc = p->cc;
87 if (p->cc == 0) {
88 cc = read(p->fd, (char *)p->buffer, p->bufsize);
89 if (cc < 0) {
90 /* Don't choke when we get ptraced */
91 switch (errno) {
92
93 case EINTR:
94 goto again;
95
96 case EWOULDBLOCK:
97 return (0);
98 #if defined(sun) && !defined(BSD)
99 /*
100 * Due to a SunOS bug, after 2^31 bytes, the kernel
101 * file offset overflows and read fails with EINVAL.
102 * The lseek() to 0 will fix things.
103 */
104 case EINVAL:
105 if (lseek(p->fd, 0L, SEEK_CUR) +
106 p->bufsize < 0) {
107 (void)lseek(p->fd, 0L, SEEK_SET);
108 goto again;
109 }
110 /* FALLTHROUGH */
111 #endif
112 }
113 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
114 pcap_strerror(errno));
115 return (-1);
116 }
117 bp = p->buffer;
118 } else
119 bp = p->bp;
120
121 /*
122 * Loop through each packet.
123 */
124 #define bhp ((struct bpf_hdr *)bp)
125 ep = bp + cc;
126 while (bp < ep) {
127 register int caplen, hdrlen;
128
129 /*
130 * Has "pcap_breakloop()" been called?
131 * If so, return immediately - if we haven't read any
132 * packets, clear the flag and return -2 to indicate
133 * that we were told to break out of the loop, otherwise
134 * leave the flag set, so that the *next* call will break
135 * out of the loop without having read any packets, and
136 * return the number of packets we've processed so far.
137 */
138 if (p->break_loop) {
139 if (n == 0) {
140 p->break_loop = 0;
141 return (-2);
142 } else {
143 p->bp = bp;
144 p->cc = ep - bp;
145 return (n);
146 }
147 }
148
149 caplen = bhp->bh_caplen;
150 hdrlen = bhp->bh_hdrlen;
151 /*
152 * XXX A bpf_hdr matches a pcap_pkthdr.
153 */
154 (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
155 bp += BPF_WORDALIGN(caplen + hdrlen);
156 if (++n >= cnt && cnt > 0) {
157 p->bp = bp;
158 p->cc = ep - bp;
159 return (n);
160 }
161 }
162 #undef bhp
163 p->cc = 0;
164 return (n);
165 }
166
167 int
pcap_inject(pcap_t * p,const void * buf,size_t len)168 pcap_inject(pcap_t *p, const void *buf, size_t len)
169 {
170 return (write(p->fd, buf, len));
171 }
172
173 int
pcap_sendpacket(pcap_t * p,const u_char * buf,int size)174 pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
175 {
176 return (pcap_inject(p, buf, size) == -1 ? -1 : 0);
177 }
178
179 /* ARGSUSED */
180 static __inline int
bpf_open(pcap_t * p,char * errbuf)181 bpf_open(pcap_t *p, char *errbuf)
182 {
183 int fd;
184 int n = 0;
185 char device[sizeof "/dev/bpf0000000000"];
186
187 /*
188 * Go through all the minors and find one that isn't in use.
189 */
190 do {
191 (void)snprintf(device, sizeof device, "/dev/bpf%d", n++);
192 fd = open(device, O_RDWR);
193 if (fd < 0 && errno == EACCES)
194 fd = open(device, O_RDONLY);
195 } while (fd < 0 && errno == EBUSY);
196
197 /*
198 * XXX better message for all minors used
199 */
200 if (fd < 0)
201 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
202 device, pcap_strerror(errno));
203
204 return (fd);
205 }
206
207 pcap_t *
pcap_open_live(const char * device,int snaplen,int promisc,int to_ms,char * ebuf)208 pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
209 char *ebuf)
210 {
211 int fd;
212 struct ifreq ifr;
213 struct bpf_version bv;
214 u_int v;
215 pcap_t *p;
216 #ifdef BIOCGDLTLIST
217 struct bpf_dltlist bdl;
218
219 bzero(&bdl, sizeof(bdl));
220 #endif
221 p = (pcap_t *)malloc(sizeof(*p));
222 if (p == NULL) {
223 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
224 pcap_strerror(errno));
225 return (NULL);
226 }
227 bzero(p, sizeof(*p));
228 fd = bpf_open(p, ebuf);
229 if (fd < 0)
230 goto bad;
231
232 p->fd = fd;
233 p->snapshot = snaplen;
234
235 if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
236 snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
237 pcap_strerror(errno));
238 goto bad;
239 }
240 if (bv.bv_major != BPF_MAJOR_VERSION ||
241 bv.bv_minor < BPF_MINOR_VERSION) {
242 snprintf(ebuf, PCAP_ERRBUF_SIZE,
243 "kernel bpf filter out of date");
244 goto bad;
245 }
246 #if 0
247 /* Just use the kernel default */
248 v = 32768; /* XXX this should be a user-accessible hook */
249 /* Ignore the return value - this is because the call fails on
250 * BPF systems that don't have kernel malloc. And if the call
251 * fails, it's no big deal, we just continue to use the standard
252 * buffer size.
253 */
254 (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
255 #endif
256
257 (void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
258 if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
259 snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s",
260 device, pcap_strerror(errno));
261 goto bad;
262 }
263 /* Get the data link layer type. */
264 if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
265 snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
266 pcap_strerror(errno));
267 goto bad;
268 }
269 #if _BSDI_VERSION - 0 >= 199510
270 /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */
271 switch (v) {
272
273 case DLT_SLIP:
274 v = DLT_SLIP_BSDOS;
275 break;
276
277 case DLT_PPP:
278 v = DLT_PPP_BSDOS;
279 break;
280 }
281 #endif
282 p->linktype = v;
283
284 #ifdef BIOCGDLTLIST
285 /*
286 * We know the default link type -- now determine all the DLTs
287 * this interface supports. If this fails with EINVAL, it's
288 * not fatal; we just don't get to use the feature later.
289 */
290 if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) == 0) {
291 bdl.bfl_list = (u_int *) calloc(bdl.bfl_len + 1, sizeof(u_int));
292 if (bdl.bfl_list == NULL) {
293 (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
294 pcap_strerror(errno));
295 goto bad;
296 }
297
298 if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) < 0) {
299 (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
300 "BIOCGDLTLIST: %s", pcap_strerror(errno));
301 goto bad;
302 }
303 p->dlt_count = bdl.bfl_len;
304 p->dlt_list = bdl.bfl_list;
305 } else {
306 if (errno != EINVAL) {
307 (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
308 "BIOCGDLTLIST: %s", pcap_strerror(errno));
309 goto bad;
310 }
311 }
312 #endif
313
314 /* set timeout */
315 if (to_ms != 0) {
316 struct timeval to;
317 to.tv_sec = to_ms / 1000;
318 to.tv_usec = (to_ms * 1000) % 1000000;
319 if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
320 snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s",
321 pcap_strerror(errno));
322 goto bad;
323 }
324 }
325 if (promisc)
326 /* set promiscuous mode, okay if it fails */
327 (void)ioctl(p->fd, BIOCPROMISC, NULL);
328
329 if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
330 snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
331 pcap_strerror(errno));
332 goto bad;
333 }
334 p->bufsize = v;
335 p->buffer = (u_char *)malloc(p->bufsize);
336 if (p->buffer == NULL) {
337 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
338 pcap_strerror(errno));
339 goto bad;
340 }
341
342 return (p);
343 bad:
344 if (fd >= 0)
345 (void)close(fd);
346 #ifdef BIOCGDLTLIST
347 free(bdl.bfl_list);
348 #endif
349 free(p);
350 return (NULL);
351 }
352
353 int
pcap_setfilter(pcap_t * p,struct bpf_program * fp)354 pcap_setfilter(pcap_t *p, struct bpf_program *fp)
355 {
356 size_t buflen;
357 /*
358 * It looks that BPF code generated by gen_protochain() is not
359 * compatible with some of kernel BPF code (for example BSD/OS 3.1).
360 * Take a safer side for now.
361 */
362 if (no_optimize || (p->sf.rfile != NULL)){
363 if (p->fcode.bf_insns != NULL)
364 pcap_freecode(&p->fcode);
365 buflen = sizeof(*fp->bf_insns) * fp->bf_len;
366 p->fcode.bf_len = fp->bf_len;
367 p->fcode.bf_insns = malloc(buflen);
368 if (p->fcode.bf_insns == NULL) {
369 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
370 pcap_strerror(errno));
371 return (-1);
372 }
373 memcpy(p->fcode.bf_insns, fp->bf_insns, buflen);
374 } else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
375 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
376 pcap_strerror(errno));
377 return (-1);
378 }
379 return (0);
380 }
381
382 int
pcap_setdirection(pcap_t * p,pcap_direction_t d)383 pcap_setdirection(pcap_t *p, pcap_direction_t d)
384 {
385 #ifndef BIOCSDIRFILT
386 return (-1);
387 #else
388 u_int dirfilt;
389
390 switch (d) {
391 case PCAP_D_INOUT:
392 dirfilt = 0;
393 break;
394 case PCAP_D_IN:
395 dirfilt = BPF_DIRECTION_OUT;
396 break;
397 case PCAP_D_OUT:
398 dirfilt = BPF_DIRECTION_IN;
399 break;
400 default:
401 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Invalid direction");
402 return (-1);
403 }
404 if (ioctl(p->fd, BIOCSDIRFILT, &dirfilt) < 0) {
405 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSDIRFILT: %s",
406 pcap_strerror(errno));
407 return (-1);
408 }
409 return (0);
410 #endif
411 }
412
413 int
pcap_set_datalink(pcap_t * p,int dlt)414 pcap_set_datalink(pcap_t *p, int dlt)
415 {
416 #ifdef BIOCSDLT
417 int i;
418
419 if (p->dlt_count == 0) {
420 #endif
421 /*
422 * We couldn't fetch the list of DLTs, or we don't
423 * have a "set datalink" operation, which means
424 * this platform doesn't support changing the
425 * DLT for an interface. Check whether the new
426 * DLT is the one this interface supports.
427 */
428 if (p->linktype != dlt)
429 goto unsupported;
430
431 /*
432 * It is, so there's nothing we need to do here.
433 */
434 return (0);
435 #ifdef BIOCSDLT
436 }
437 for (i = 0; i < p->dlt_count; i++)
438 if (p->dlt_list[i] == dlt)
439 break;
440 if (i >= p->dlt_count)
441 goto unsupported;
442 if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
443 (void) snprintf(p->errbuf, sizeof(p->errbuf),
444 "Cannot set DLT %d: %s", dlt, strerror(errno));
445 return (-1);
446 }
447 p->linktype = dlt;
448 return (0);
449 #endif
450
451 unsupported:
452 (void) snprintf(p->errbuf, sizeof(p->errbuf),
453 "DLT %d is not one of the DLTs supported by this device",
454 dlt);
455 return (-1);
456 }
457
458