1*afdbf109SJoseph Mingrone /*
2*afdbf109SJoseph Mingrone * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3*afdbf109SJoseph Mingrone * Distributed under the terms of the MIT License.
4*afdbf109SJoseph Mingrone *
5*afdbf109SJoseph Mingrone * Authors:
6*afdbf109SJoseph Mingrone * Axel Dörfler, axeld@pinc-software.de
7*afdbf109SJoseph Mingrone * James Woodcock
8*afdbf109SJoseph Mingrone */
9*afdbf109SJoseph Mingrone
10*afdbf109SJoseph Mingrone
11*afdbf109SJoseph Mingrone #include <config.h>
12*afdbf109SJoseph Mingrone #include "pcap-int.h"
13*afdbf109SJoseph Mingrone
14*afdbf109SJoseph Mingrone #include <OS.h>
15*afdbf109SJoseph Mingrone
16*afdbf109SJoseph Mingrone #include <sys/socket.h>
17*afdbf109SJoseph Mingrone #include <sys/sockio.h>
18*afdbf109SJoseph Mingrone #include <sys/utsname.h>
19*afdbf109SJoseph Mingrone
20*afdbf109SJoseph Mingrone #include <net/if.h>
21*afdbf109SJoseph Mingrone #include <net/if_dl.h>
22*afdbf109SJoseph Mingrone #include <net/if_types.h>
23*afdbf109SJoseph Mingrone #include <net/if_media.h>
24*afdbf109SJoseph Mingrone
25*afdbf109SJoseph Mingrone #include <errno.h>
26*afdbf109SJoseph Mingrone #include <stdio.h>
27*afdbf109SJoseph Mingrone #include <stdlib.h>
28*afdbf109SJoseph Mingrone #include <string.h>
29*afdbf109SJoseph Mingrone #include <unistd.h>
30*afdbf109SJoseph Mingrone #include <stdint.h>
31*afdbf109SJoseph Mingrone
32*afdbf109SJoseph Mingrone
33*afdbf109SJoseph Mingrone // IFT_TUN was renamed to IFT_TUNNEL in the master branch after R1/beta4 (the
34*afdbf109SJoseph Mingrone // integer value didn't change). Even though IFT_TUN is a no-op in versions
35*afdbf109SJoseph Mingrone // that define it, for the time being it is desirable to support compiling
36*afdbf109SJoseph Mingrone // libpcap on versions with the old macro and using it on later versions that
37*afdbf109SJoseph Mingrone // support tunnel interfaces.
38*afdbf109SJoseph Mingrone #ifndef IFT_TUNNEL
39*afdbf109SJoseph Mingrone #define IFT_TUNNEL IFT_TUN
40*afdbf109SJoseph Mingrone #endif
41*afdbf109SJoseph Mingrone
42*afdbf109SJoseph Mingrone /*
43*afdbf109SJoseph Mingrone * Private data for capturing on Haiku sockets.
44*afdbf109SJoseph Mingrone */
45*afdbf109SJoseph Mingrone struct pcap_haiku {
46*afdbf109SJoseph Mingrone struct pcap_stat stat;
47*afdbf109SJoseph Mingrone int aux_socket;
48*afdbf109SJoseph Mingrone struct ifreq ifreq;
49*afdbf109SJoseph Mingrone // The original state of the promiscuous mode at the activation time,
50*afdbf109SJoseph Mingrone // if the capture should be run in promiscuous mode.
51*afdbf109SJoseph Mingrone int orig_promisc;
52*afdbf109SJoseph Mingrone };
53*afdbf109SJoseph Mingrone
54*afdbf109SJoseph Mingrone
55*afdbf109SJoseph Mingrone static int
pcap_read_haiku(pcap_t * handle,int maxPackets _U_,pcap_handler callback,u_char * userdata)56*afdbf109SJoseph Mingrone pcap_read_haiku(pcap_t* handle, int maxPackets _U_, pcap_handler callback,
57*afdbf109SJoseph Mingrone u_char* userdata)
58*afdbf109SJoseph Mingrone {
59*afdbf109SJoseph Mingrone // Receive a single packet
60*afdbf109SJoseph Mingrone
61*afdbf109SJoseph Mingrone u_char* buffer = (u_char*)handle->buffer;
62*afdbf109SJoseph Mingrone ssize_t bytesReceived;
63*afdbf109SJoseph Mingrone do {
64*afdbf109SJoseph Mingrone if (handle->break_loop) {
65*afdbf109SJoseph Mingrone handle->break_loop = 0;
66*afdbf109SJoseph Mingrone return PCAP_ERROR_BREAK;
67*afdbf109SJoseph Mingrone }
68*afdbf109SJoseph Mingrone bytesReceived = recvfrom(handle->fd, buffer, handle->bufsize, MSG_TRUNC,
69*afdbf109SJoseph Mingrone NULL, NULL);
70*afdbf109SJoseph Mingrone } while (bytesReceived < 0 && errno == B_INTERRUPTED);
71*afdbf109SJoseph Mingrone
72*afdbf109SJoseph Mingrone // The kernel does not implement timestamping of network packets, so
73*afdbf109SJoseph Mingrone // doing it ASAP in userland is the best that can be done.
74*afdbf109SJoseph Mingrone bigtime_t ts = real_time_clock_usecs();
75*afdbf109SJoseph Mingrone
76*afdbf109SJoseph Mingrone if (bytesReceived < 0) {
77*afdbf109SJoseph Mingrone if (errno == B_WOULD_BLOCK) {
78*afdbf109SJoseph Mingrone // there is no packet for us
79*afdbf109SJoseph Mingrone return 0;
80*afdbf109SJoseph Mingrone }
81*afdbf109SJoseph Mingrone
82*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
83*afdbf109SJoseph Mingrone errno, "recvfrom");
84*afdbf109SJoseph Mingrone return PCAP_ERROR;
85*afdbf109SJoseph Mingrone }
86*afdbf109SJoseph Mingrone
87*afdbf109SJoseph Mingrone struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv;
88*afdbf109SJoseph Mingrone // BPF is 32-bit, which is more than sufficient for any realistic
89*afdbf109SJoseph Mingrone // packet size.
90*afdbf109SJoseph Mingrone if (bytesReceived > UINT32_MAX)
91*afdbf109SJoseph Mingrone goto drop;
92*afdbf109SJoseph Mingrone // At this point, if the recvfrom() call populated its struct sockaddr
93*afdbf109SJoseph Mingrone // and socklen_t arguments, it would be the right time to drop packets
94*afdbf109SJoseph Mingrone // that have .sa_family not valid for the current DLT. But in the
95*afdbf109SJoseph Mingrone // current master branch (hrev57588) this would erroneously drop some
96*afdbf109SJoseph Mingrone // valid packets: recvfrom(), at least for tap mode tunnels, sets the
97*afdbf109SJoseph Mingrone // address length to 0 for all incoming packets and sets .sa_len and
98*afdbf109SJoseph Mingrone // .sa_family to 0 for packets that are broadcast or multicast. So it
99*afdbf109SJoseph Mingrone // cannot be done yet, if there is a good reason to do it in the first
100*afdbf109SJoseph Mingrone // place.
101*afdbf109SJoseph Mingrone handlep->stat.ps_recv++;
102*afdbf109SJoseph Mingrone
103*afdbf109SJoseph Mingrone bpf_u_int32 wireLength = (bpf_u_int32)bytesReceived;
104*afdbf109SJoseph Mingrone // As long as the buffer is large enough, the captured length is equal
105*afdbf109SJoseph Mingrone // to the wire length, but let's get the lengths right anyway in case
106*afdbf109SJoseph Mingrone // packets grow bigger or the buffer grows smaller in future and the
107*afdbf109SJoseph Mingrone // MSG_TRUNC effect kicks in.
108*afdbf109SJoseph Mingrone bpf_u_int32 captureLength =
109*afdbf109SJoseph Mingrone wireLength <= handle->bufsize ? wireLength : handle->bufsize;
110*afdbf109SJoseph Mingrone
111*afdbf109SJoseph Mingrone // run the packet filter
112*afdbf109SJoseph Mingrone if (handle->fcode.bf_insns) {
113*afdbf109SJoseph Mingrone // NB: pcapint_filter() takes the wire length and the captured
114*afdbf109SJoseph Mingrone // length, not the snapshot length of the pcap_t handle.
115*afdbf109SJoseph Mingrone if (pcapint_filter(handle->fcode.bf_insns, buffer, wireLength,
116*afdbf109SJoseph Mingrone captureLength) == 0)
117*afdbf109SJoseph Mingrone goto drop;
118*afdbf109SJoseph Mingrone }
119*afdbf109SJoseph Mingrone
120*afdbf109SJoseph Mingrone // fill in pcap_header
121*afdbf109SJoseph Mingrone struct pcap_pkthdr header;
122*afdbf109SJoseph Mingrone header.caplen = captureLength <= (bpf_u_int32)handle->snapshot ?
123*afdbf109SJoseph Mingrone captureLength :
124*afdbf109SJoseph Mingrone (bpf_u_int32)handle->snapshot;
125*afdbf109SJoseph Mingrone header.len = wireLength;
126*afdbf109SJoseph Mingrone header.ts.tv_usec = ts % 1000000;
127*afdbf109SJoseph Mingrone header.ts.tv_sec = ts / 1000000;
128*afdbf109SJoseph Mingrone
129*afdbf109SJoseph Mingrone /* Call the user supplied callback function */
130*afdbf109SJoseph Mingrone callback(userdata, &header, buffer);
131*afdbf109SJoseph Mingrone return 1;
132*afdbf109SJoseph Mingrone drop:
133*afdbf109SJoseph Mingrone handlep->stat.ps_drop++;
134*afdbf109SJoseph Mingrone return 0;
135*afdbf109SJoseph Mingrone }
136*afdbf109SJoseph Mingrone
137*afdbf109SJoseph Mingrone
138*afdbf109SJoseph Mingrone static int
dgram_socket(const int af,char * errbuf)139*afdbf109SJoseph Mingrone dgram_socket(const int af, char *errbuf)
140*afdbf109SJoseph Mingrone {
141*afdbf109SJoseph Mingrone int ret = socket(af, SOCK_DGRAM, 0);
142*afdbf109SJoseph Mingrone if (ret < 0) {
143*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
144*afdbf109SJoseph Mingrone "socket");
145*afdbf109SJoseph Mingrone return PCAP_ERROR;
146*afdbf109SJoseph Mingrone }
147*afdbf109SJoseph Mingrone return ret;
148*afdbf109SJoseph Mingrone }
149*afdbf109SJoseph Mingrone
150*afdbf109SJoseph Mingrone
151*afdbf109SJoseph Mingrone static int
ioctl_ifreq(const int fd,const unsigned long op,const char * name,struct ifreq * ifreq,char * errbuf)152*afdbf109SJoseph Mingrone ioctl_ifreq(const int fd, const unsigned long op, const char *name,
153*afdbf109SJoseph Mingrone struct ifreq *ifreq, char *errbuf)
154*afdbf109SJoseph Mingrone {
155*afdbf109SJoseph Mingrone if (ioctl(fd, op, ifreq, sizeof(struct ifreq)) < 0) {
156*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
157*afdbf109SJoseph Mingrone "%s", name);
158*afdbf109SJoseph Mingrone return PCAP_ERROR;
159*afdbf109SJoseph Mingrone }
160*afdbf109SJoseph Mingrone return 0;
161*afdbf109SJoseph Mingrone }
162*afdbf109SJoseph Mingrone
163*afdbf109SJoseph Mingrone
164*afdbf109SJoseph Mingrone static int
get_promisc(pcap_t * handle)165*afdbf109SJoseph Mingrone get_promisc(pcap_t *handle)
166*afdbf109SJoseph Mingrone {
167*afdbf109SJoseph Mingrone struct pcap_haiku *handlep = (struct pcap_haiku *)handle->priv;
168*afdbf109SJoseph Mingrone // SIOCGIFFLAGS would work fine for AF_LINK too.
169*afdbf109SJoseph Mingrone if (ioctl_ifreq(handlep->aux_socket, SIOCGIFFLAGS, "SIOCGIFFLAGS",
170*afdbf109SJoseph Mingrone &handlep->ifreq, handle->errbuf) < 0)
171*afdbf109SJoseph Mingrone return PCAP_ERROR;
172*afdbf109SJoseph Mingrone return (handlep->ifreq.ifr_flags & IFF_PROMISC) != 0;
173*afdbf109SJoseph Mingrone }
174*afdbf109SJoseph Mingrone
175*afdbf109SJoseph Mingrone
176*afdbf109SJoseph Mingrone static int
set_promisc(pcap_t * handle,const int enable)177*afdbf109SJoseph Mingrone set_promisc(pcap_t *handle, const int enable)
178*afdbf109SJoseph Mingrone {
179*afdbf109SJoseph Mingrone struct pcap_haiku *handlep = (struct pcap_haiku *)handle->priv;
180*afdbf109SJoseph Mingrone if (enable)
181*afdbf109SJoseph Mingrone handlep->ifreq.ifr_flags |= IFF_PROMISC;
182*afdbf109SJoseph Mingrone else
183*afdbf109SJoseph Mingrone handlep->ifreq.ifr_flags &= ~IFF_PROMISC;
184*afdbf109SJoseph Mingrone // SIOCSIFFLAGS works for AF_INET, but not for AF_LINK.
185*afdbf109SJoseph Mingrone return ioctl_ifreq(handlep->aux_socket, SIOCSIFFLAGS, "SIOCSIFFLAGS",
186*afdbf109SJoseph Mingrone &handlep->ifreq, handle->errbuf);
187*afdbf109SJoseph Mingrone }
188*afdbf109SJoseph Mingrone
189*afdbf109SJoseph Mingrone
190*afdbf109SJoseph Mingrone static void
pcap_cleanup_haiku(pcap_t * handle)191*afdbf109SJoseph Mingrone pcap_cleanup_haiku(pcap_t *handle)
192*afdbf109SJoseph Mingrone {
193*afdbf109SJoseph Mingrone struct pcap_haiku *handlep = (struct pcap_haiku *)handle->priv;
194*afdbf109SJoseph Mingrone if (handlep->aux_socket >= 0) {
195*afdbf109SJoseph Mingrone // Closing the sockets has no effect on IFF_PROMISC, hence the
196*afdbf109SJoseph Mingrone // need to restore the original state on one hand and the
197*afdbf109SJoseph Mingrone // possibility of clash with other processes managing the same
198*afdbf109SJoseph Mingrone // interface flag. Unset promiscuous mode iff the activation
199*afdbf109SJoseph Mingrone // function had set it and it is still set now.
200*afdbf109SJoseph Mingrone if (handle->opt.promisc && ! handlep->orig_promisc &&
201*afdbf109SJoseph Mingrone get_promisc(handle))
202*afdbf109SJoseph Mingrone (void)set_promisc(handle, 0);
203*afdbf109SJoseph Mingrone close(handlep->aux_socket);
204*afdbf109SJoseph Mingrone handlep->aux_socket = -1;
205*afdbf109SJoseph Mingrone }
206*afdbf109SJoseph Mingrone pcapint_cleanup_live_common(handle);
207*afdbf109SJoseph Mingrone }
208*afdbf109SJoseph Mingrone
209*afdbf109SJoseph Mingrone
210*afdbf109SJoseph Mingrone static int
pcap_inject_haiku(pcap_t * handle,const void * buffer _U_,int size _U_)211*afdbf109SJoseph Mingrone pcap_inject_haiku(pcap_t *handle, const void *buffer _U_, int size _U_)
212*afdbf109SJoseph Mingrone {
213*afdbf109SJoseph Mingrone // Haiku currently (hrev57588) does not support sending raw packets.
214*afdbf109SJoseph Mingrone // https://dev.haiku-os.org/ticket/18810
215*afdbf109SJoseph Mingrone strlcpy(handle->errbuf, "Sending packets isn't supported yet",
216*afdbf109SJoseph Mingrone PCAP_ERRBUF_SIZE);
217*afdbf109SJoseph Mingrone return PCAP_ERROR;
218*afdbf109SJoseph Mingrone }
219*afdbf109SJoseph Mingrone
220*afdbf109SJoseph Mingrone
221*afdbf109SJoseph Mingrone static int
pcap_stats_haiku(pcap_t * handle,struct pcap_stat * stats)222*afdbf109SJoseph Mingrone pcap_stats_haiku(pcap_t *handle, struct pcap_stat *stats)
223*afdbf109SJoseph Mingrone {
224*afdbf109SJoseph Mingrone struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv;
225*afdbf109SJoseph Mingrone *stats = handlep->stat;
226*afdbf109SJoseph Mingrone // Now ps_recv and ps_drop are accurate, but ps_ifdrop still equals to
227*afdbf109SJoseph Mingrone // the snapshot value from the activation time.
228*afdbf109SJoseph Mingrone if (ioctl_ifreq(handlep->aux_socket, SIOCGIFSTATS, "SIOCGIFSTATS",
229*afdbf109SJoseph Mingrone &handlep->ifreq, handle->errbuf) < 0)
230*afdbf109SJoseph Mingrone return PCAP_ERROR;
231*afdbf109SJoseph Mingrone // The result is subject to wrapping around the 32-bit integer space,
232*afdbf109SJoseph Mingrone // but that cannot be significantly improved as long as it has to fit
233*afdbf109SJoseph Mingrone // into a 32-bit member of pcap_stats.
234*afdbf109SJoseph Mingrone stats->ps_ifdrop = handlep->ifreq.ifr_stats.receive.dropped - stats->ps_ifdrop;
235*afdbf109SJoseph Mingrone return 0;
236*afdbf109SJoseph Mingrone }
237*afdbf109SJoseph Mingrone
238*afdbf109SJoseph Mingrone
239*afdbf109SJoseph Mingrone static int
pcap_activate_haiku(pcap_t * handle)240*afdbf109SJoseph Mingrone pcap_activate_haiku(pcap_t *handle)
241*afdbf109SJoseph Mingrone {
242*afdbf109SJoseph Mingrone struct pcap_haiku *handlep = (struct pcap_haiku *)handle->priv;
243*afdbf109SJoseph Mingrone int ret = PCAP_ERROR;
244*afdbf109SJoseph Mingrone
245*afdbf109SJoseph Mingrone // we need a socket to talk to the networking stack
246*afdbf109SJoseph Mingrone if ((handlep->aux_socket = dgram_socket(AF_INET, handle->errbuf)) < 0)
247*afdbf109SJoseph Mingrone goto error;
248*afdbf109SJoseph Mingrone
249*afdbf109SJoseph Mingrone // pcap_stats_haiku() will need a baseline for ps_ifdrop.
250*afdbf109SJoseph Mingrone // At the time of this writing SIOCGIFSTATS returns EINVAL for AF_LINK
251*afdbf109SJoseph Mingrone // sockets.
252*afdbf109SJoseph Mingrone if (ioctl_ifreq(handlep->aux_socket, SIOCGIFSTATS, "SIOCGIFSTATS",
253*afdbf109SJoseph Mingrone &handlep->ifreq, handle->errbuf) < 0) {
254*afdbf109SJoseph Mingrone // Detect a non-existent network interface at least at the
255*afdbf109SJoseph Mingrone // first ioctl() use.
256*afdbf109SJoseph Mingrone if (errno == EINVAL)
257*afdbf109SJoseph Mingrone ret = PCAP_ERROR_NO_SUCH_DEVICE;
258*afdbf109SJoseph Mingrone goto error;
259*afdbf109SJoseph Mingrone }
260*afdbf109SJoseph Mingrone handlep->stat.ps_ifdrop = handlep->ifreq.ifr_stats.receive.dropped;
261*afdbf109SJoseph Mingrone
262*afdbf109SJoseph Mingrone // get link level interface for this interface
263*afdbf109SJoseph Mingrone if ((handle->fd = dgram_socket(AF_LINK, handle->errbuf)) < 0)
264*afdbf109SJoseph Mingrone goto error;
265*afdbf109SJoseph Mingrone
266*afdbf109SJoseph Mingrone // Derive a DLT from the interface type.
267*afdbf109SJoseph Mingrone // At the time of this writing SIOCGIFTYPE cannot be used for this
268*afdbf109SJoseph Mingrone // purpose: it returns EINVAL for AF_LINK sockets and sets ifr_type to
269*afdbf109SJoseph Mingrone // 0 for AF_INET sockets. Use the same method as Haiku ifconfig does
270*afdbf109SJoseph Mingrone // (SIOCGIFADDR and AF_LINK).
271*afdbf109SJoseph Mingrone if (ioctl_ifreq(handle->fd, SIOCGIFADDR, "SIOCGIFADDR",
272*afdbf109SJoseph Mingrone &handlep->ifreq, handle->errbuf) < 0)
273*afdbf109SJoseph Mingrone goto error;
274*afdbf109SJoseph Mingrone struct sockaddr_dl *sdl = (struct sockaddr_dl *)&handlep->ifreq.ifr_addr;
275*afdbf109SJoseph Mingrone if (sdl->sdl_family != AF_LINK) {
276*afdbf109SJoseph Mingrone snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
277*afdbf109SJoseph Mingrone "Got AF %d instead of AF_LINK for interface \"%s\".",
278*afdbf109SJoseph Mingrone sdl->sdl_family, handle->opt.device);
279*afdbf109SJoseph Mingrone goto error;
280*afdbf109SJoseph Mingrone }
281*afdbf109SJoseph Mingrone switch (sdl->sdl_type) {
282*afdbf109SJoseph Mingrone case IFT_ETHER:
283*afdbf109SJoseph Mingrone // Ethernet on all versions, also tap (L2) mode tunnels on
284*afdbf109SJoseph Mingrone // versions after R1/beta4.
285*afdbf109SJoseph Mingrone handle->linktype = DLT_EN10MB;
286*afdbf109SJoseph Mingrone break;
287*afdbf109SJoseph Mingrone case IFT_TUNNEL:
288*afdbf109SJoseph Mingrone // Unused on R1/beta4 and earlier versions, tun (L3) mode
289*afdbf109SJoseph Mingrone // tunnels on later versions.
290*afdbf109SJoseph Mingrone case IFT_LOOP:
291*afdbf109SJoseph Mingrone // The loopback interface on all versions.
292*afdbf109SJoseph Mingrone // Both IFT_TUNNEL and IFT_LOOP prepended a dummy Ethernet
293*afdbf109SJoseph Mingrone // header until hrev57585: https://dev.haiku-os.org/ticket/18801
294*afdbf109SJoseph Mingrone handle->linktype = DLT_RAW;
295*afdbf109SJoseph Mingrone break;
296*afdbf109SJoseph Mingrone default:
297*afdbf109SJoseph Mingrone snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
298*afdbf109SJoseph Mingrone "Unknown interface type 0x%0x for interface \"%s\".",
299*afdbf109SJoseph Mingrone sdl->sdl_type, handle->opt.device);
300*afdbf109SJoseph Mingrone goto error;
301*afdbf109SJoseph Mingrone }
302*afdbf109SJoseph Mingrone
303*afdbf109SJoseph Mingrone // start monitoring
304*afdbf109SJoseph Mingrone if (ioctl_ifreq(handle->fd, SIOCSPACKETCAP, "SIOCSPACKETCAP",
305*afdbf109SJoseph Mingrone &handlep->ifreq, handle->errbuf) < 0)
306*afdbf109SJoseph Mingrone goto error;
307*afdbf109SJoseph Mingrone
308*afdbf109SJoseph Mingrone handle->selectable_fd = handle->fd;
309*afdbf109SJoseph Mingrone handle->read_op = pcap_read_haiku;
310*afdbf109SJoseph Mingrone handle->setfilter_op = pcapint_install_bpf_program; /* no kernel filtering */
311*afdbf109SJoseph Mingrone handle->inject_op = pcap_inject_haiku;
312*afdbf109SJoseph Mingrone handle->stats_op = pcap_stats_haiku;
313*afdbf109SJoseph Mingrone handle->cleanup_op = pcap_cleanup_haiku;
314*afdbf109SJoseph Mingrone
315*afdbf109SJoseph Mingrone // use default hooks where possible
316*afdbf109SJoseph Mingrone handle->getnonblock_op = pcapint_getnonblock_fd;
317*afdbf109SJoseph Mingrone handle->setnonblock_op = pcapint_setnonblock_fd;
318*afdbf109SJoseph Mingrone
319*afdbf109SJoseph Mingrone /*
320*afdbf109SJoseph Mingrone * Turn a negative snapshot value (invalid), a snapshot value of
321*afdbf109SJoseph Mingrone * 0 (unspecified), or a value bigger than the normal maximum
322*afdbf109SJoseph Mingrone * value, into the maximum allowed value.
323*afdbf109SJoseph Mingrone *
324*afdbf109SJoseph Mingrone * If some application really *needs* a bigger snapshot
325*afdbf109SJoseph Mingrone * length, we should just increase MAXIMUM_SNAPLEN.
326*afdbf109SJoseph Mingrone */
327*afdbf109SJoseph Mingrone if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
328*afdbf109SJoseph Mingrone handle->snapshot = MAXIMUM_SNAPLEN;
329*afdbf109SJoseph Mingrone
330*afdbf109SJoseph Mingrone // Although it would be trivial to size the buffer at the kernel end of
331*afdbf109SJoseph Mingrone // the capture socket using setsockopt() and SO_RCVBUF, there seems to
332*afdbf109SJoseph Mingrone // be no point in doing so: setting the size low silently drops some
333*afdbf109SJoseph Mingrone // packets in the kernel, setting it high does not result in a visible
334*afdbf109SJoseph Mingrone // improvement. Let's leave this buffer as it is until it is clear why
335*afdbf109SJoseph Mingrone // it would need resizing. Meanwhile pcap_set_buffer_size() will have
336*afdbf109SJoseph Mingrone // no effect on Haiku.
337*afdbf109SJoseph Mingrone
338*afdbf109SJoseph Mingrone // It would be wrong to size the buffer at the libpcap end of the
339*afdbf109SJoseph Mingrone // capture socket to the interface MTU, which limits only outgoing
340*afdbf109SJoseph Mingrone // packets and only at layer 3. For example, an Ethernet interface
341*afdbf109SJoseph Mingrone // with ifconfig/ioctl() MTU set to 1500 ordinarily sends layer 2
342*afdbf109SJoseph Mingrone // packets as large as 1514 bytes and receives layer 2 packets as large
343*afdbf109SJoseph Mingrone // as the NIC and the driver happen to accept (e.g. 9018 bytes for
344*afdbf109SJoseph Mingrone // ipro1000). This way, valid packets larger than the MTU can occur in
345*afdbf109SJoseph Mingrone // a capture and will arrive truncated to pcap_read_haiku() if the
346*afdbf109SJoseph Mingrone // buffer is not large enough. So let's keep it large enough for most
347*afdbf109SJoseph Mingrone // if not all practical use cases, then pcap_read_haiku() can handle
348*afdbf109SJoseph Mingrone // the unlikely truncation as and if necessary.
349*afdbf109SJoseph Mingrone handle->bufsize = 65536;
350*afdbf109SJoseph Mingrone
351*afdbf109SJoseph Mingrone // allocate buffer for monitoring the device
352*afdbf109SJoseph Mingrone handle->buffer = (u_char*)malloc(handle->bufsize);
353*afdbf109SJoseph Mingrone if (handle->buffer == NULL) {
354*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
355*afdbf109SJoseph Mingrone errno, "buffer malloc");
356*afdbf109SJoseph Mingrone goto error;
357*afdbf109SJoseph Mingrone }
358*afdbf109SJoseph Mingrone
359*afdbf109SJoseph Mingrone if (handle->opt.promisc) {
360*afdbf109SJoseph Mingrone // Set promiscuous mode iff required, in any case remember the
361*afdbf109SJoseph Mingrone // original state.
362*afdbf109SJoseph Mingrone if ((handlep->orig_promisc = get_promisc(handle)) < 0)
363*afdbf109SJoseph Mingrone goto error;
364*afdbf109SJoseph Mingrone if (! handlep->orig_promisc && set_promisc(handle, 1) < 0)
365*afdbf109SJoseph Mingrone return PCAP_WARNING_PROMISC_NOTSUP;
366*afdbf109SJoseph Mingrone }
367*afdbf109SJoseph Mingrone return 0;
368*afdbf109SJoseph Mingrone error:
369*afdbf109SJoseph Mingrone pcap_cleanup_haiku(handle);
370*afdbf109SJoseph Mingrone return ret;
371*afdbf109SJoseph Mingrone }
372*afdbf109SJoseph Mingrone
373*afdbf109SJoseph Mingrone
374*afdbf109SJoseph Mingrone static int
validate_ifname(const char * device,char * errbuf)375*afdbf109SJoseph Mingrone validate_ifname(const char *device, char *errbuf)
376*afdbf109SJoseph Mingrone {
377*afdbf109SJoseph Mingrone if (strlen(device) >= IF_NAMESIZE) {
378*afdbf109SJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE,
379*afdbf109SJoseph Mingrone "Interface name \"%s\" is too long.", device);
380*afdbf109SJoseph Mingrone return PCAP_ERROR;
381*afdbf109SJoseph Mingrone }
382*afdbf109SJoseph Mingrone return 0;
383*afdbf109SJoseph Mingrone }
384*afdbf109SJoseph Mingrone
385*afdbf109SJoseph Mingrone
386*afdbf109SJoseph Mingrone // #pragma mark - pcap API
387*afdbf109SJoseph Mingrone
388*afdbf109SJoseph Mingrone
389*afdbf109SJoseph Mingrone static int
can_be_bound(const char * name)390*afdbf109SJoseph Mingrone can_be_bound(const char *name)
391*afdbf109SJoseph Mingrone {
392*afdbf109SJoseph Mingrone if (strcmp(name, "loop") != 0)
393*afdbf109SJoseph Mingrone return 1;
394*afdbf109SJoseph Mingrone
395*afdbf109SJoseph Mingrone // In Haiku versions before hrev57010 the loopback interface allows to
396*afdbf109SJoseph Mingrone // start a capture, but the capture never receives any packets.
397*afdbf109SJoseph Mingrone //
398*afdbf109SJoseph Mingrone // Since compiling libpcap on one Haiku version and using the binary on
399*afdbf109SJoseph Mingrone // another seems to be commonplace, comparing B_HAIKU_VERSION at the
400*afdbf109SJoseph Mingrone // compile time would not always work as intended. Let's at least
401*afdbf109SJoseph Mingrone // remove unsuitable well-known 64-bit versions (with or without
402*afdbf109SJoseph Mingrone // updates) from the problem space at run time.
403*afdbf109SJoseph Mingrone const char *badversions[] = {
404*afdbf109SJoseph Mingrone "hrev56578", // R1/beta4
405*afdbf109SJoseph Mingrone "hrev55182", // R1/beta3
406*afdbf109SJoseph Mingrone "hrev54154", // R1/beta2
407*afdbf109SJoseph Mingrone "hrev52295", // R1/beta1
408*afdbf109SJoseph Mingrone "hrev44702", // R1/alpha4
409*afdbf109SJoseph Mingrone NULL
410*afdbf109SJoseph Mingrone };
411*afdbf109SJoseph Mingrone struct utsname uts;
412*afdbf109SJoseph Mingrone (void)uname(&uts);
413*afdbf109SJoseph Mingrone for (const char **s = badversions; *s; s++)
414*afdbf109SJoseph Mingrone if (! strncmp(uts.version, *s, strlen(*s)))
415*afdbf109SJoseph Mingrone return 0;
416*afdbf109SJoseph Mingrone return 1;
417*afdbf109SJoseph Mingrone }
418*afdbf109SJoseph Mingrone
419*afdbf109SJoseph Mingrone
420*afdbf109SJoseph Mingrone pcap_t *
pcapint_create_interface(const char * device,char * errorBuffer)421*afdbf109SJoseph Mingrone pcapint_create_interface(const char *device, char *errorBuffer)
422*afdbf109SJoseph Mingrone {
423*afdbf109SJoseph Mingrone if (validate_ifname(device, errorBuffer) < 0)
424*afdbf109SJoseph Mingrone return NULL;
425*afdbf109SJoseph Mingrone if (! can_be_bound(device)) {
426*afdbf109SJoseph Mingrone snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
427*afdbf109SJoseph Mingrone "Interface \"%s\" does not support capturing traffic.", device);
428*afdbf109SJoseph Mingrone return NULL;
429*afdbf109SJoseph Mingrone }
430*afdbf109SJoseph Mingrone
431*afdbf109SJoseph Mingrone pcap_t* handle = PCAP_CREATE_COMMON(errorBuffer, struct pcap_haiku);
432*afdbf109SJoseph Mingrone if (handle == NULL)
433*afdbf109SJoseph Mingrone return NULL;
434*afdbf109SJoseph Mingrone handle->activate_op = pcap_activate_haiku;
435*afdbf109SJoseph Mingrone
436*afdbf109SJoseph Mingrone struct pcap_haiku *handlep = (struct pcap_haiku *)handle->priv;
437*afdbf109SJoseph Mingrone handlep->aux_socket = -1;
438*afdbf109SJoseph Mingrone strcpy(handlep->ifreq.ifr_name, device);
439*afdbf109SJoseph Mingrone
440*afdbf109SJoseph Mingrone return handle;
441*afdbf109SJoseph Mingrone }
442*afdbf109SJoseph Mingrone
443*afdbf109SJoseph Mingrone
444*afdbf109SJoseph Mingrone static int
get_if_flags(const char * name,bpf_u_int32 * flags,char * errbuf)445*afdbf109SJoseph Mingrone get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
446*afdbf109SJoseph Mingrone {
447*afdbf109SJoseph Mingrone if (validate_ifname(name, errbuf) < 0)
448*afdbf109SJoseph Mingrone return PCAP_ERROR;
449*afdbf109SJoseph Mingrone
450*afdbf109SJoseph Mingrone if (*flags & PCAP_IF_LOOPBACK ||
451*afdbf109SJoseph Mingrone ! strncmp(name, "tun", strlen("tun")) ||
452*afdbf109SJoseph Mingrone ! strncmp(name, "tap", strlen("tap"))) {
453*afdbf109SJoseph Mingrone /*
454*afdbf109SJoseph Mingrone * Loopback devices aren't wireless, and "connected"/
455*afdbf109SJoseph Mingrone * "disconnected" doesn't apply to them.
456*afdbf109SJoseph Mingrone *
457*afdbf109SJoseph Mingrone * Neither does it to tunnel interfaces. A tun mode tunnel
458*afdbf109SJoseph Mingrone * can be identified by the IFT_TUNNEL value, but tap mode
459*afdbf109SJoseph Mingrone * tunnels and Ethernet interfaces both use IFT_ETHER, so let's
460*afdbf109SJoseph Mingrone * use the interface name prefix until there is a better
461*afdbf109SJoseph Mingrone * solution.
462*afdbf109SJoseph Mingrone */
463*afdbf109SJoseph Mingrone *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
464*afdbf109SJoseph Mingrone return (0);
465*afdbf109SJoseph Mingrone }
466*afdbf109SJoseph Mingrone
467*afdbf109SJoseph Mingrone int fd = dgram_socket(AF_LINK, errbuf);
468*afdbf109SJoseph Mingrone if (fd < 0)
469*afdbf109SJoseph Mingrone return PCAP_ERROR;
470*afdbf109SJoseph Mingrone struct ifreq ifreq;
471*afdbf109SJoseph Mingrone strcpy(ifreq.ifr_name, name);
472*afdbf109SJoseph Mingrone if (ioctl_ifreq(fd, SIOCGIFFLAGS, "SIOCGIFFLAGS", &ifreq, errbuf) < 0) {
473*afdbf109SJoseph Mingrone close(fd);
474*afdbf109SJoseph Mingrone return PCAP_ERROR;
475*afdbf109SJoseph Mingrone }
476*afdbf109SJoseph Mingrone *flags |= (ifreq.ifr_flags & IFF_LINK) ?
477*afdbf109SJoseph Mingrone PCAP_IF_CONNECTION_STATUS_CONNECTED :
478*afdbf109SJoseph Mingrone PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
479*afdbf109SJoseph Mingrone if (ioctl_ifreq(fd, SIOCGIFMEDIA, "SIOCGIFMEDIA", &ifreq, errbuf) < 0) {
480*afdbf109SJoseph Mingrone close(fd);
481*afdbf109SJoseph Mingrone return PCAP_ERROR;
482*afdbf109SJoseph Mingrone }
483*afdbf109SJoseph Mingrone if (IFM_TYPE(ifreq.ifr_media) == IFM_IEEE80211)
484*afdbf109SJoseph Mingrone *flags |= PCAP_IF_WIRELESS;
485*afdbf109SJoseph Mingrone close(fd);
486*afdbf109SJoseph Mingrone
487*afdbf109SJoseph Mingrone return (0);
488*afdbf109SJoseph Mingrone }
489*afdbf109SJoseph Mingrone
490*afdbf109SJoseph Mingrone int
pcapint_platform_finddevs(pcap_if_list_t * _allDevices,char * errorBuffer)491*afdbf109SJoseph Mingrone pcapint_platform_finddevs(pcap_if_list_t* _allDevices, char* errorBuffer)
492*afdbf109SJoseph Mingrone {
493*afdbf109SJoseph Mingrone return pcapint_findalldevs_interfaces(_allDevices, errorBuffer, can_be_bound,
494*afdbf109SJoseph Mingrone get_if_flags);
495*afdbf109SJoseph Mingrone }
496*afdbf109SJoseph Mingrone
497*afdbf109SJoseph Mingrone /*
498*afdbf109SJoseph Mingrone * Libpcap version string.
499*afdbf109SJoseph Mingrone */
500*afdbf109SJoseph Mingrone const char *
pcap_lib_version(void)501*afdbf109SJoseph Mingrone pcap_lib_version(void)
502*afdbf109SJoseph Mingrone {
503*afdbf109SJoseph Mingrone return (PCAP_VERSION_STRING);
504*afdbf109SJoseph Mingrone }
505