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