1*aa4ed2b9Ssthen /* $OpenBSD: pcap.c,v 1.24 2018/06/03 10:29:28 sthen Exp $ */
2df930be7Sderaadt
3df930be7Sderaadt /*
401efc7efSderaadt * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
5df930be7Sderaadt * The Regents of the University of California. All rights reserved.
6df930be7Sderaadt *
7df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
8df930be7Sderaadt * modification, are permitted provided that the following conditions
9df930be7Sderaadt * are met:
10df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
11df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
12df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
13df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
14df930be7Sderaadt * documentation and/or other materials provided with the distribution.
15df930be7Sderaadt * 3. All advertising materials mentioning features or use of this software
16df930be7Sderaadt * must display the following acknowledgement:
17df930be7Sderaadt * This product includes software developed by the Computer Systems
18df930be7Sderaadt * Engineering Group at Lawrence Berkeley Laboratory.
19df930be7Sderaadt * 4. Neither the name of the University nor of the Laboratory may be used
20df930be7Sderaadt * to endorse or promote products derived from this software without
21df930be7Sderaadt * specific prior written permission.
22df930be7Sderaadt *
23df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33df930be7Sderaadt * SUCH DAMAGE.
34df930be7Sderaadt */
35df930be7Sderaadt
36df930be7Sderaadt #include <sys/types.h>
37df930be7Sderaadt
389b113833Smickey #include <stdio.h>
399b113833Smickey #include <stdlib.h>
40df930be7Sderaadt #include <string.h>
41df930be7Sderaadt #include <unistd.h>
42a878b819Sdjm #include <errno.h>
43a878b819Sdjm #include <fcntl.h>
44df930be7Sderaadt
459b113833Smickey #ifdef HAVE_OS_PROTO_H
469b113833Smickey #include "os-proto.h"
479b113833Smickey #endif
489b113833Smickey
49df930be7Sderaadt #include "pcap-int.h"
50df930be7Sderaadt
51a878b819Sdjm static const char pcap_version_string[] = "OpenBSD libpcap";
52a878b819Sdjm
53df930be7Sderaadt int
pcap_dispatch(pcap_t * p,int cnt,pcap_handler callback,u_char * user)54df930be7Sderaadt pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
55df930be7Sderaadt {
569b113833Smickey
57df930be7Sderaadt if (p->sf.rfile != NULL)
58df930be7Sderaadt return (pcap_offline_read(p, cnt, callback, user));
5901efc7efSderaadt return (pcap_read(p, cnt, callback, user));
60df930be7Sderaadt }
61df930be7Sderaadt
62df930be7Sderaadt int
pcap_loop(pcap_t * p,int cnt,pcap_handler callback,u_char * user)63df930be7Sderaadt pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
64df930be7Sderaadt {
65d0438536Smmcc int n;
6601efc7efSderaadt
67df930be7Sderaadt for (;;) {
6801efc7efSderaadt if (p->sf.rfile != NULL)
6901efc7efSderaadt n = pcap_offline_read(p, cnt, callback, user);
7001efc7efSderaadt else {
7101efc7efSderaadt /*
7201efc7efSderaadt * XXX keep reading until we get something
7301efc7efSderaadt * (or an error occurs)
7401efc7efSderaadt */
7501efc7efSderaadt do {
7601efc7efSderaadt n = pcap_read(p, cnt, callback, user);
7701efc7efSderaadt } while (n == 0);
7801efc7efSderaadt }
799b113833Smickey if (n <= 0)
80df930be7Sderaadt return (n);
81df930be7Sderaadt if (cnt > 0) {
82df930be7Sderaadt cnt -= n;
83df930be7Sderaadt if (cnt <= 0)
84df930be7Sderaadt return (0);
85df930be7Sderaadt }
86df930be7Sderaadt }
87df930be7Sderaadt }
88df930be7Sderaadt
89df930be7Sderaadt struct singleton {
90df930be7Sderaadt struct pcap_pkthdr *hdr;
91df930be7Sderaadt const u_char *pkt;
92df930be7Sderaadt };
93df930be7Sderaadt
94df930be7Sderaadt
95df930be7Sderaadt static void
pcap_oneshot(u_char * userData,const struct pcap_pkthdr * h,const u_char * pkt)96df930be7Sderaadt pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt)
97df930be7Sderaadt {
98df930be7Sderaadt struct singleton *sp = (struct singleton *)userData;
99df930be7Sderaadt *sp->hdr = *h;
100df930be7Sderaadt sp->pkt = pkt;
101df930be7Sderaadt }
102df930be7Sderaadt
103df930be7Sderaadt const u_char *
pcap_next(pcap_t * p,struct pcap_pkthdr * h)104df930be7Sderaadt pcap_next(pcap_t *p, struct pcap_pkthdr *h)
105df930be7Sderaadt {
106df930be7Sderaadt struct singleton s;
107df930be7Sderaadt
108df930be7Sderaadt s.hdr = h;
1099b113833Smickey if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0)
110df930be7Sderaadt return (0);
111df930be7Sderaadt return (s.pkt);
112df930be7Sderaadt }
113df930be7Sderaadt
114c1bf1209Sdjm struct pkt_for_fakecallback {
115c1bf1209Sdjm struct pcap_pkthdr *hdr;
116c1bf1209Sdjm const u_char **pkt;
117c1bf1209Sdjm };
118c1bf1209Sdjm
119c1bf1209Sdjm static void
pcap_fakecallback(u_char * userData,const struct pcap_pkthdr * h,const u_char * pkt)120c1bf1209Sdjm pcap_fakecallback(u_char *userData, const struct pcap_pkthdr *h,
121c1bf1209Sdjm const u_char *pkt)
122c1bf1209Sdjm {
123c1bf1209Sdjm struct pkt_for_fakecallback *sp = (struct pkt_for_fakecallback *)userData;
124c1bf1209Sdjm
125c1bf1209Sdjm *sp->hdr = *h;
126c1bf1209Sdjm *sp->pkt = pkt;
127c1bf1209Sdjm }
128c1bf1209Sdjm
129c1bf1209Sdjm int
pcap_next_ex(pcap_t * p,struct pcap_pkthdr ** pkt_header,const u_char ** pkt_data)130c1bf1209Sdjm pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
131c1bf1209Sdjm const u_char **pkt_data)
132c1bf1209Sdjm {
133c1bf1209Sdjm struct pkt_for_fakecallback s;
134c1bf1209Sdjm
135c1bf1209Sdjm s.hdr = &p->pcap_header;
136c1bf1209Sdjm s.pkt = pkt_data;
137c1bf1209Sdjm
138c1bf1209Sdjm /* Saves a pointer to the packet headers */
139c1bf1209Sdjm *pkt_header= &p->pcap_header;
140c1bf1209Sdjm
141c1bf1209Sdjm if (p->sf.rfile != NULL) {
142c1bf1209Sdjm int status;
143c1bf1209Sdjm
144c1bf1209Sdjm /* We are on an offline capture */
145c1bf1209Sdjm status = pcap_offline_read(p, 1, pcap_fakecallback,
146c1bf1209Sdjm (u_char *)&s);
147c1bf1209Sdjm
148c1bf1209Sdjm /*
149c1bf1209Sdjm * Return codes for pcap_offline_read() are:
150c1bf1209Sdjm * - 0: EOF
151c1bf1209Sdjm * - -1: error
152c1bf1209Sdjm * - >1: OK
153c1bf1209Sdjm * The first one ('0') conflicts with the return code of
154c1bf1209Sdjm * 0 from pcap_read() meaning "no packets arrived before
155c1bf1209Sdjm * the timeout expired", so we map it to -2 so you can
156c1bf1209Sdjm * distinguish between an EOF from a savefile and a
157c1bf1209Sdjm * "no packets arrived before the timeout expired, try
158c1bf1209Sdjm * again" from a live capture.
159c1bf1209Sdjm */
160c1bf1209Sdjm if (status == 0)
161c1bf1209Sdjm return (-2);
162c1bf1209Sdjm else
163c1bf1209Sdjm return (status);
164c1bf1209Sdjm }
165c1bf1209Sdjm
166c1bf1209Sdjm /*
167c1bf1209Sdjm * Return codes for pcap_read() are:
168c1bf1209Sdjm * - 0: timeout
169c1bf1209Sdjm * - -1: error
170c1bf1209Sdjm * - -2: loop was broken out of with pcap_breakloop()
171c1bf1209Sdjm * - >1: OK
172c1bf1209Sdjm * The first one ('0') conflicts with the return code of 0 from
173c1bf1209Sdjm * pcap_offline_read() meaning "end of file".
174c1bf1209Sdjm */
175c1bf1209Sdjm return (pcap_read(p, 1, pcap_fakecallback, (u_char *)&s));
176c1bf1209Sdjm }
177c1bf1209Sdjm
17811297935Slteo int
pcap_check_activated(pcap_t * p)17911297935Slteo pcap_check_activated(pcap_t *p)
18011297935Slteo {
18111297935Slteo if (p->activated) {
18211297935Slteo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
18311297935Slteo " operation on activated capture");
18411297935Slteo return -1;
18511297935Slteo }
18611297935Slteo return 0;
18711297935Slteo }
18811297935Slteo
18911297935Slteo int
pcap_set_snaplen(pcap_t * p,int snaplen)19011297935Slteo pcap_set_snaplen(pcap_t *p, int snaplen)
19111297935Slteo {
19211297935Slteo if (pcap_check_activated(p))
19311297935Slteo return PCAP_ERROR_ACTIVATED;
19411297935Slteo p->snapshot = snaplen;
19511297935Slteo return 0;
19611297935Slteo }
19711297935Slteo
19811297935Slteo int
pcap_set_promisc(pcap_t * p,int promisc)19911297935Slteo pcap_set_promisc(pcap_t *p, int promisc)
20011297935Slteo {
20111297935Slteo if (pcap_check_activated(p))
20211297935Slteo return PCAP_ERROR_ACTIVATED;
20311297935Slteo p->opt.promisc = promisc;
20411297935Slteo return 0;
20511297935Slteo }
20611297935Slteo
20711297935Slteo int
pcap_set_rfmon(pcap_t * p,int rfmon)20811297935Slteo pcap_set_rfmon(pcap_t *p, int rfmon)
20911297935Slteo {
21011297935Slteo if (pcap_check_activated(p))
21111297935Slteo return PCAP_ERROR_ACTIVATED;
21211297935Slteo p->opt.rfmon = rfmon;
21311297935Slteo return 0;
21411297935Slteo }
21511297935Slteo
21611297935Slteo int
pcap_set_timeout(pcap_t * p,int timeout_ms)21711297935Slteo pcap_set_timeout(pcap_t *p, int timeout_ms)
21811297935Slteo {
21911297935Slteo if (pcap_check_activated(p))
22011297935Slteo return PCAP_ERROR_ACTIVATED;
22111297935Slteo p->md.timeout = timeout_ms;
22211297935Slteo return 0;
22311297935Slteo }
22411297935Slteo
22511297935Slteo int
pcap_set_immediate_mode(pcap_t * p,int immediate)226346f594fSlteo pcap_set_immediate_mode(pcap_t *p, int immediate)
227346f594fSlteo {
228346f594fSlteo if (pcap_check_activated(p))
229346f594fSlteo return PCAP_ERROR_ACTIVATED;
230346f594fSlteo p->opt.immediate = immediate;
231346f594fSlteo return 0;
232346f594fSlteo }
233346f594fSlteo
234346f594fSlteo int
pcap_set_buffer_size(pcap_t * p,int buffer_size)23511297935Slteo pcap_set_buffer_size(pcap_t *p, int buffer_size)
23611297935Slteo {
23711297935Slteo if (pcap_check_activated(p))
23811297935Slteo return PCAP_ERROR_ACTIVATED;
23911297935Slteo p->opt.buffer_size = buffer_size;
24011297935Slteo return 0;
24111297935Slteo }
24211297935Slteo
243a878b819Sdjm /*
244a878b819Sdjm * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
245a878b819Sdjm */
246a878b819Sdjm void
pcap_breakloop(pcap_t * p)247a878b819Sdjm pcap_breakloop(pcap_t *p)
248a878b819Sdjm {
249a878b819Sdjm p->break_loop = 1;
250a878b819Sdjm }
251a878b819Sdjm
252df930be7Sderaadt int
pcap_datalink(pcap_t * p)253df930be7Sderaadt pcap_datalink(pcap_t *p)
254df930be7Sderaadt {
255df930be7Sderaadt return (p->linktype);
256df930be7Sderaadt }
257df930be7Sderaadt
258df930be7Sderaadt int
pcap_list_datalinks(pcap_t * p,int ** dlt_buffer)259a878b819Sdjm pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
260a878b819Sdjm {
261a878b819Sdjm if (p->dlt_count == 0) {
262a878b819Sdjm /*
263a878b819Sdjm * We couldn't fetch the list of DLTs, which means
264a878b819Sdjm * this platform doesn't support changing the
265a878b819Sdjm * DLT for an interface. Return a list of DLTs
266a878b819Sdjm * containing only the DLT this device supports.
267a878b819Sdjm */
2681b8dcd42Slteo *dlt_buffer = malloc(sizeof(**dlt_buffer));
269a878b819Sdjm if (*dlt_buffer == NULL) {
270a878b819Sdjm (void)snprintf(p->errbuf, sizeof(p->errbuf),
271a878b819Sdjm "malloc: %s", pcap_strerror(errno));
272a878b819Sdjm return (-1);
273a878b819Sdjm }
274a878b819Sdjm **dlt_buffer = p->linktype;
275a878b819Sdjm return (1);
276a878b819Sdjm } else {
277b8f389f9Slteo *dlt_buffer = reallocarray(NULL, sizeof(**dlt_buffer),
278b8f389f9Slteo p->dlt_count);
279a878b819Sdjm if (*dlt_buffer == NULL) {
280a878b819Sdjm (void)snprintf(p->errbuf, sizeof(p->errbuf),
281a878b819Sdjm "malloc: %s", pcap_strerror(errno));
282a878b819Sdjm return (-1);
283a878b819Sdjm }
284a878b819Sdjm (void)memcpy(*dlt_buffer, p->dlt_list,
285a878b819Sdjm sizeof(**dlt_buffer) * p->dlt_count);
286a878b819Sdjm return (p->dlt_count);
287a878b819Sdjm }
288a878b819Sdjm }
289a878b819Sdjm
2901f92dbfeSjasper /*
2911f92dbfeSjasper * In Windows, you might have a library built with one version of the
2921f92dbfeSjasper * C runtime library and an application built with another version of
2931f92dbfeSjasper * the C runtime library, which means that the library might use one
2941f92dbfeSjasper * version of malloc() and free() and the application might use another
2951f92dbfeSjasper * version of malloc() and free(). If so, that means something
2961f92dbfeSjasper * allocated by the library cannot be freed by the application, so we
2971f92dbfeSjasper * need to have a pcap_free_datalinks() routine to free up the list
2981f92dbfeSjasper * allocated by pcap_list_datalinks(), even though it's just a wrapper
2991f92dbfeSjasper * around free().
3001f92dbfeSjasper */
3011f92dbfeSjasper void
pcap_free_datalinks(int * dlt_list)3021f92dbfeSjasper pcap_free_datalinks(int *dlt_list)
3031f92dbfeSjasper {
3041f92dbfeSjasper free(dlt_list);
3051f92dbfeSjasper }
3061f92dbfeSjasper
307a878b819Sdjm struct dlt_choice {
308a878b819Sdjm const char *name;
309a878b819Sdjm const char *description;
310a878b819Sdjm int dlt;
311a878b819Sdjm };
312a878b819Sdjm
313a878b819Sdjm static struct dlt_choice dlts[] = {
314a878b819Sdjm #define DLT_CHOICE(code, description) { #code, description, code }
315a878b819Sdjm DLT_CHOICE(DLT_NULL, "no link-layer encapsulation"),
316a878b819Sdjm DLT_CHOICE(DLT_EN10MB, "Ethernet (10Mb)"),
317a878b819Sdjm DLT_CHOICE(DLT_EN3MB, "Experimental Ethernet (3Mb)"),
318a878b819Sdjm DLT_CHOICE(DLT_AX25, "Amateur Radio AX.25"),
319a878b819Sdjm DLT_CHOICE(DLT_PRONET, "Proteon ProNET Token Ring"),
320a878b819Sdjm DLT_CHOICE(DLT_CHAOS, "Chaos"),
321a878b819Sdjm DLT_CHOICE(DLT_IEEE802, "IEEE 802 Networks"),
322a878b819Sdjm DLT_CHOICE(DLT_ARCNET, "ARCNET"),
323a878b819Sdjm DLT_CHOICE(DLT_SLIP, "Serial Line IP"),
324a878b819Sdjm DLT_CHOICE(DLT_PPP, "Point-to-point Protocol"),
3252524a2d3Sdlg DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
326a878b819Sdjm DLT_CHOICE(DLT_FDDI, "FDDI"),
327a878b819Sdjm DLT_CHOICE(DLT_ATM_RFC1483, "LLC/SNAP encapsulated atm"),
328a878b819Sdjm DLT_CHOICE(DLT_LOOP, "loopback type (af header)"),
329a878b819Sdjm DLT_CHOICE(DLT_ENC, "IPSEC enc type (af header, spi, flags)"),
330a878b819Sdjm DLT_CHOICE(DLT_RAW, "raw IP"),
331a878b819Sdjm DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS Serial Line IP"),
332a878b819Sdjm DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS Point-to-point Protocol"),
333a878b819Sdjm DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"),
334a878b819Sdjm DLT_CHOICE(DLT_PPP_ETHER, "PPP over Ethernet; session only w/o ether header"),
335a878b819Sdjm DLT_CHOICE(DLT_IEEE802_11, "IEEE 802.11 wireless"),
336a878b819Sdjm DLT_CHOICE(DLT_PFLOG, "Packet filter logging, by pcap people"),
337a878b819Sdjm DLT_CHOICE(DLT_IEEE802_11_RADIO, "IEEE 802.11 plus WLAN header"),
3387a61d4b0Sreyk DLT_CHOICE(DLT_OPENFLOW, "OpenFlow"),
339d00b8992Smpi DLT_CHOICE(DLT_USBPCAP, "USB"),
340a878b819Sdjm #undef DLT_CHOICE
341a878b819Sdjm { NULL, NULL, -1}
342a878b819Sdjm };
343a878b819Sdjm
344a878b819Sdjm int
pcap_datalink_name_to_val(const char * name)345a878b819Sdjm pcap_datalink_name_to_val(const char *name)
346a878b819Sdjm {
347a878b819Sdjm int i;
348a878b819Sdjm
349a878b819Sdjm for (i = 0; dlts[i].name != NULL; i++) {
350a878b819Sdjm /* Skip leading "DLT_" */
351a878b819Sdjm if (strcasecmp(dlts[i].name + 4, name) == 0)
352a878b819Sdjm return (dlts[i].dlt);
353a878b819Sdjm }
354a878b819Sdjm return (-1);
355a878b819Sdjm }
356a878b819Sdjm
357a878b819Sdjm const char *
pcap_datalink_val_to_name(int dlt)358a878b819Sdjm pcap_datalink_val_to_name(int dlt)
359a878b819Sdjm {
360a878b819Sdjm int i;
361a878b819Sdjm
362a878b819Sdjm for (i = 0; dlts[i].name != NULL; i++) {
363a878b819Sdjm if (dlts[i].dlt == dlt)
364a878b819Sdjm return (dlts[i].name + 4); /* Skip leading "DLT_" */
365a878b819Sdjm }
366a878b819Sdjm return (NULL);
367a878b819Sdjm }
368a878b819Sdjm
369a878b819Sdjm const char *
pcap_datalink_val_to_description(int dlt)370a878b819Sdjm pcap_datalink_val_to_description(int dlt)
371a878b819Sdjm {
372a878b819Sdjm int i;
373a878b819Sdjm
374a878b819Sdjm for (i = 0; dlts[i].name != NULL; i++) {
375a878b819Sdjm if (dlts[i].dlt == dlt)
376a878b819Sdjm return (dlts[i].description);
377a878b819Sdjm }
378a878b819Sdjm return (NULL);
379a878b819Sdjm }
380a878b819Sdjm
381a878b819Sdjm int
pcap_snapshot(pcap_t * p)382df930be7Sderaadt pcap_snapshot(pcap_t *p)
383df930be7Sderaadt {
384df930be7Sderaadt return (p->snapshot);
385df930be7Sderaadt }
386df930be7Sderaadt
387df930be7Sderaadt int
pcap_is_swapped(pcap_t * p)388df930be7Sderaadt pcap_is_swapped(pcap_t *p)
389df930be7Sderaadt {
390df930be7Sderaadt return (p->sf.swapped);
391df930be7Sderaadt }
392df930be7Sderaadt
393df930be7Sderaadt int
pcap_major_version(pcap_t * p)394df930be7Sderaadt pcap_major_version(pcap_t *p)
395df930be7Sderaadt {
396df930be7Sderaadt return (p->sf.version_major);
397df930be7Sderaadt }
398df930be7Sderaadt
399df930be7Sderaadt int
pcap_minor_version(pcap_t * p)400df930be7Sderaadt pcap_minor_version(pcap_t *p)
401df930be7Sderaadt {
402df930be7Sderaadt return (p->sf.version_minor);
403df930be7Sderaadt }
404df930be7Sderaadt
405df930be7Sderaadt FILE *
pcap_file(pcap_t * p)406df930be7Sderaadt pcap_file(pcap_t *p)
407df930be7Sderaadt {
408df930be7Sderaadt return (p->sf.rfile);
409df930be7Sderaadt }
410df930be7Sderaadt
411df930be7Sderaadt int
pcap_fileno(pcap_t * p)412df930be7Sderaadt pcap_fileno(pcap_t *p)
413df930be7Sderaadt {
414df930be7Sderaadt return (p->fd);
415df930be7Sderaadt }
416df930be7Sderaadt
417df930be7Sderaadt void
pcap_perror(pcap_t * p,const char * prefix)418*aa4ed2b9Ssthen pcap_perror(pcap_t *p, const char *prefix)
419df930be7Sderaadt {
420df930be7Sderaadt fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
421df930be7Sderaadt }
422df930be7Sderaadt
423c1bf1209Sdjm int
pcap_get_selectable_fd(pcap_t * p)424c1bf1209Sdjm pcap_get_selectable_fd(pcap_t *p)
425c1bf1209Sdjm {
426c1bf1209Sdjm return (p->fd);
427c1bf1209Sdjm }
428c1bf1209Sdjm
429df930be7Sderaadt char *
pcap_geterr(pcap_t * p)430df930be7Sderaadt pcap_geterr(pcap_t *p)
431df930be7Sderaadt {
432df930be7Sderaadt return (p->errbuf);
433df930be7Sderaadt }
434df930be7Sderaadt
435a878b819Sdjm int
pcap_getnonblock(pcap_t * p,char * errbuf)436a878b819Sdjm pcap_getnonblock(pcap_t *p, char *errbuf)
437a878b819Sdjm {
438a878b819Sdjm int fdflags;
439a878b819Sdjm
44042596f13Skrw fdflags = fcntl(p->fd, F_GETFL);
441a878b819Sdjm if (fdflags == -1) {
442a878b819Sdjm snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
443a878b819Sdjm pcap_strerror(errno));
444a878b819Sdjm return (-1);
445a878b819Sdjm }
446a878b819Sdjm if (fdflags & O_NONBLOCK)
447a878b819Sdjm return (1);
448a878b819Sdjm else
449a878b819Sdjm return (0);
450a878b819Sdjm }
451a878b819Sdjm
452a878b819Sdjm int
pcap_setnonblock(pcap_t * p,int nonblock,char * errbuf)453a878b819Sdjm pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
454a878b819Sdjm {
455a878b819Sdjm int fdflags;
456a878b819Sdjm
45742596f13Skrw fdflags = fcntl(p->fd, F_GETFL);
458a878b819Sdjm if (fdflags == -1) {
459a878b819Sdjm snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
460a878b819Sdjm pcap_strerror(errno));
461a878b819Sdjm return (-1);
462a878b819Sdjm }
463a878b819Sdjm if (nonblock)
464a878b819Sdjm fdflags |= O_NONBLOCK;
465a878b819Sdjm else
466a878b819Sdjm fdflags &= ~O_NONBLOCK;
467a878b819Sdjm if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
468a878b819Sdjm snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
469a878b819Sdjm pcap_strerror(errno));
470a878b819Sdjm return (-1);
471a878b819Sdjm }
472a878b819Sdjm return (0);
473a878b819Sdjm }
474a878b819Sdjm
475df930be7Sderaadt /*
47611297935Slteo * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
47711297935Slteo */
47811297935Slteo const char *
pcap_statustostr(int errnum)47911297935Slteo pcap_statustostr(int errnum)
48011297935Slteo {
48111297935Slteo static char ebuf[15+10+1];
48211297935Slteo
48311297935Slteo switch (errnum) {
48411297935Slteo
48511297935Slteo case PCAP_WARNING:
48611297935Slteo return("Generic warning");
48711297935Slteo
48811297935Slteo case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
48911297935Slteo return ("That type of time stamp is not supported by that device");
49011297935Slteo
49111297935Slteo case PCAP_WARNING_PROMISC_NOTSUP:
49211297935Slteo return ("That device doesn't support promiscuous mode");
49311297935Slteo
49411297935Slteo case PCAP_ERROR:
49511297935Slteo return("Generic error");
49611297935Slteo
49711297935Slteo case PCAP_ERROR_BREAK:
49811297935Slteo return("Loop terminated by pcap_breakloop");
49911297935Slteo
50011297935Slteo case PCAP_ERROR_NOT_ACTIVATED:
50111297935Slteo return("The pcap_t has not been activated");
50211297935Slteo
50311297935Slteo case PCAP_ERROR_ACTIVATED:
50411297935Slteo return ("The setting can't be changed after the pcap_t is activated");
50511297935Slteo
50611297935Slteo case PCAP_ERROR_NO_SUCH_DEVICE:
50711297935Slteo return ("No such device exists");
50811297935Slteo
50911297935Slteo case PCAP_ERROR_RFMON_NOTSUP:
51011297935Slteo return ("That device doesn't support monitor mode");
51111297935Slteo
51211297935Slteo case PCAP_ERROR_NOT_RFMON:
51311297935Slteo return ("That operation is supported only in monitor mode");
51411297935Slteo
51511297935Slteo case PCAP_ERROR_PERM_DENIED:
51611297935Slteo return ("You don't have permission to capture on that device");
51711297935Slteo
51811297935Slteo case PCAP_ERROR_IFACE_NOT_UP:
51911297935Slteo return ("That device is not up");
52011297935Slteo
52111297935Slteo case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
52211297935Slteo return ("That device doesn't support setting the time stamp type");
52311297935Slteo
52411297935Slteo case PCAP_ERROR_PROMISC_PERM_DENIED:
52511297935Slteo return ("You don't have permission to capture in promiscuous mode on that device");
52611297935Slteo }
52711297935Slteo (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
52811297935Slteo return(ebuf);
52911297935Slteo }
53011297935Slteo
53111297935Slteo /*
532df930be7Sderaadt * Not all systems have strerror().
533df930be7Sderaadt */
534*aa4ed2b9Ssthen const char *
pcap_strerror(int errnum)535df930be7Sderaadt pcap_strerror(int errnum)
536df930be7Sderaadt {
5379b113833Smickey #ifdef HAVE_STRERROR
538df930be7Sderaadt return (strerror(errnum));
5399b113833Smickey #else
5409b113833Smickey extern int sys_nerr;
5419b113833Smickey extern const char *const sys_errlist[];
5429b113833Smickey static char ebuf[20];
5439b113833Smickey
5449b113833Smickey if ((unsigned int)errnum < sys_nerr)
5459b113833Smickey return ((char *)sys_errlist[errnum]);
54613c7aa11Sderaadt (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
5479b113833Smickey return(ebuf);
5489b113833Smickey #endif
549df930be7Sderaadt }
550df930be7Sderaadt
55111297935Slteo /*
55211297935Slteo * On some platforms, we need to clean up promiscuous or monitor mode
55311297935Slteo * when we close a device - and we want that to happen even if the
55411297935Slteo * application just exits without explicitl closing devices.
55511297935Slteo * On those platforms, we need to register a "close all the pcaps"
55611297935Slteo * routine to be called when we exit, and need to maintain a list of
55711297935Slteo * pcaps that need to be closed to clean up modes.
55811297935Slteo *
55911297935Slteo * XXX - not thread-safe.
56011297935Slteo */
56111297935Slteo
56211297935Slteo /*
56311297935Slteo * List of pcaps on which we've done something that needs to be
56411297935Slteo * cleaned up.
56511297935Slteo * If there are any such pcaps, we arrange to call "pcap_close_all()"
56611297935Slteo * when we exit, and have it close all of them.
56711297935Slteo */
56811297935Slteo static struct pcap *pcaps_to_close;
56911297935Slteo
57011297935Slteo /*
57111297935Slteo * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to
57211297935Slteo * be called on exit.
57311297935Slteo */
57411297935Slteo static int did_atexit;
57511297935Slteo
57611297935Slteo static void
pcap_close_all(void)57711297935Slteo pcap_close_all(void)
57811297935Slteo {
57911297935Slteo struct pcap *handle;
58011297935Slteo
58111297935Slteo while ((handle = pcaps_to_close) != NULL)
58211297935Slteo pcap_close(handle);
58311297935Slteo }
58411297935Slteo
58511297935Slteo int
pcap_do_addexit(pcap_t * p)58611297935Slteo pcap_do_addexit(pcap_t *p)
58711297935Slteo {
58811297935Slteo /*
58911297935Slteo * If we haven't already done so, arrange to have
59011297935Slteo * "pcap_close_all()" called when we exit.
59111297935Slteo */
59211297935Slteo if (!did_atexit) {
59311297935Slteo if (atexit(pcap_close_all) == -1) {
59411297935Slteo /*
59511297935Slteo * "atexit()" failed; let our caller know.
59611297935Slteo */
59711297935Slteo (void)strlcpy(p->errbuf, "atexit failed",
59811297935Slteo PCAP_ERRBUF_SIZE);
59911297935Slteo return (0);
60011297935Slteo }
60111297935Slteo did_atexit = 1;
60211297935Slteo }
60311297935Slteo return (1);
60411297935Slteo }
60511297935Slteo
60611297935Slteo void
pcap_add_to_pcaps_to_close(pcap_t * p)60711297935Slteo pcap_add_to_pcaps_to_close(pcap_t *p)
60811297935Slteo {
60911297935Slteo p->md.next = pcaps_to_close;
61011297935Slteo pcaps_to_close = p;
61111297935Slteo }
61211297935Slteo
61311297935Slteo void
pcap_remove_from_pcaps_to_close(pcap_t * p)61411297935Slteo pcap_remove_from_pcaps_to_close(pcap_t *p)
61511297935Slteo {
61611297935Slteo pcap_t *pc, *prevpc;
61711297935Slteo
61811297935Slteo for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
61911297935Slteo prevpc = pc, pc = pc->md.next) {
62011297935Slteo if (pc == p) {
62111297935Slteo /*
62211297935Slteo * Found it. Remove it from the list.
62311297935Slteo */
62411297935Slteo if (prevpc == NULL) {
62511297935Slteo /*
62611297935Slteo * It was at the head of the list.
62711297935Slteo */
62811297935Slteo pcaps_to_close = pc->md.next;
62911297935Slteo } else {
63011297935Slteo /*
63111297935Slteo * It was in the middle of the list.
63211297935Slteo */
63311297935Slteo prevpc->md.next = pc->md.next;
63411297935Slteo }
63511297935Slteo break;
63611297935Slteo }
63711297935Slteo }
63811297935Slteo }
63911297935Slteo
640a878b819Sdjm pcap_t *
pcap_open_dead(int linktype,int snaplen)641a878b819Sdjm pcap_open_dead(int linktype, int snaplen)
642a878b819Sdjm {
643a878b819Sdjm pcap_t *p;
644a878b819Sdjm
6458d365cd4Slteo p = calloc(1, sizeof(*p));
646a878b819Sdjm if (p == NULL)
647a878b819Sdjm return NULL;
648a878b819Sdjm p->snapshot = snaplen;
649a878b819Sdjm p->linktype = linktype;
650a878b819Sdjm p->fd = -1;
651a878b819Sdjm return p;
652a878b819Sdjm }
653a878b819Sdjm
6541f92dbfeSjasper /*
6551f92dbfeSjasper * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw
6561f92dbfeSjasper * data for the packet, check whether the packet passes the filter.
6571f92dbfeSjasper * Returns the return value of the filter program, which will be zero if
6581f92dbfeSjasper * the packet doesn't pass and non-zero if the packet does pass.
6591f92dbfeSjasper */
6601f92dbfeSjasper int
pcap_offline_filter(const struct bpf_program * fp,const struct pcap_pkthdr * h,const u_char * pkt)6611f92dbfeSjasper pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h,
6621f92dbfeSjasper const u_char *pkt)
6631f92dbfeSjasper {
6641f92dbfeSjasper struct bpf_insn *fcode = fp->bf_insns;
6651f92dbfeSjasper
6661f92dbfeSjasper if (fcode != NULL)
6671f92dbfeSjasper return (bpf_filter(fcode, pkt, h->len, h->caplen));
6681f92dbfeSjasper else
6691f92dbfeSjasper return (0);
6701f92dbfeSjasper }
6711f92dbfeSjasper
672a878b819Sdjm const char *
pcap_lib_version(void)673a878b819Sdjm pcap_lib_version(void)
674a878b819Sdjm {
675a878b819Sdjm return (pcap_version_string);
676a878b819Sdjm }
677a878b819Sdjm
678