2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
16 #include <sys/socket.h>
17 #include <sys/sockio.h>
18 #include <sys/utsname.h>
21 #include <net/if_dl.h>
22 #include <net/if_types.h>
23 #include <net/if_media.h>
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.
39 #define IFT_TUNNEL IFT_TUN
43 * Private data for capturing on Haiku sockets.
46 struct pcap_stat stat
;
49 // The original state of the promiscuous mode at the activation time,
50 // if the capture should be run in promiscuous mode.
56 pcap_read_haiku(pcap_t
* handle
, int maxPackets _U_
, pcap_handler callback
,
59 // Receive a single packet
61 u_char
* buffer
= handle
->buffer
;
62 ssize_t bytesReceived
;
64 if (handle
->break_loop
) {
65 handle
->break_loop
= 0;
66 return PCAP_ERROR_BREAK
;
68 bytesReceived
= recvfrom(handle
->fd
, buffer
, handle
->bufsize
, MSG_TRUNC
,
70 } while (bytesReceived
< 0 && errno
== B_INTERRUPTED
);
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();
76 if (bytesReceived
< 0) {
77 if (errno
== B_WOULD_BLOCK
) {
78 // there is no packet for us
82 pcapint_fmt_errmsg_for_errno(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
87 struct pcap_haiku
* handlep
= (struct pcap_haiku
*)handle
->priv
;
88 // BPF is 32-bit, which is more than sufficient for any realistic
90 if (bytesReceived
> UINT32_MAX
)
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
101 handlep
->stat
.ps_recv
++;
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
;
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
,
120 // fill in pcap_header
121 struct pcap_pkthdr header
;
122 header
.caplen
= captureLength
<= (bpf_u_int32
)handle
->snapshot
?
124 (bpf_u_int32
)handle
->snapshot
;
125 header
.len
= wireLength
;
126 header
.ts
.tv_usec
= ts
% 1000000;
127 header
.ts
.tv_sec
= ts
/ 1000000;
129 /* Call the user supplied callback function */
130 callback(userdata
, &header
, buffer
);
133 handlep
->stat
.ps_drop
++;
139 PCAP_WARN_UNUSED_RESULT
140 dgram_socket(const int af
, char *errbuf
)
142 int ret
= socket(af
, SOCK_DGRAM
, 0);
144 pcapint_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
, errno
,
153 PCAP_WARN_UNUSED_RESULT
154 ioctl_ifreq(const int fd
, const unsigned long op
, const char *name
,
155 struct ifreq
*ifreq
, char *errbuf
)
157 if (ioctl(fd
, op
, ifreq
, sizeof(struct ifreq
)) < 0) {
158 pcapint_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
, errno
,
167 PCAP_WARN_UNUSED_RESULT
168 get_promisc(pcap_t
*handle
)
170 struct pcap_haiku
*handlep
= (struct pcap_haiku
*)handle
->priv
;
171 // SIOCGIFFLAGS would work fine for AF_LINK too.
172 if (ioctl_ifreq(handlep
->aux_socket
, SIOCGIFFLAGS
, "SIOCGIFFLAGS",
173 &handlep
->ifreq
, handle
->errbuf
) < 0)
175 return (handlep
->ifreq
.ifr_flags
& IFF_PROMISC
) != 0;
180 set_promisc(pcap_t
*handle
, const int enable
)
182 struct pcap_haiku
*handlep
= (struct pcap_haiku
*)handle
->priv
;
184 handlep
->ifreq
.ifr_flags
|= IFF_PROMISC
;
186 handlep
->ifreq
.ifr_flags
&= ~IFF_PROMISC
;
187 // SIOCSIFFLAGS works for AF_INET, but not for AF_LINK.
188 return ioctl_ifreq(handlep
->aux_socket
, SIOCSIFFLAGS
, "SIOCSIFFLAGS",
189 &handlep
->ifreq
, handle
->errbuf
);
194 pcap_cleanup_haiku(pcap_t
*handle
)
196 struct pcap_haiku
*handlep
= (struct pcap_haiku
*)handle
->priv
;
197 if (handlep
->aux_socket
>= 0) {
198 // Closing the sockets has no effect on IFF_PROMISC, hence the
199 // need to restore the original state on one hand and the
200 // possibility of clash with other processes managing the same
201 // interface flag. Unset promiscuous mode iff the activation
202 // function had set it and it is still set now.
203 if (handle
->opt
.promisc
&& ! handlep
->orig_promisc
&&
205 (void)set_promisc(handle
, 0);
206 close(handlep
->aux_socket
);
207 handlep
->aux_socket
= -1;
209 pcapint_cleanup_live_common(handle
);
214 pcap_inject_haiku(pcap_t
*handle
, const void *buffer _U_
, int size _U_
)
216 // Haiku currently (hrev57588) does not support sending raw packets.
217 // https://dev.haiku-os.org/ticket/18810
218 pcapint_strlcpy(handle
->errbuf
, "Sending packets isn't supported yet",
225 pcap_stats_haiku(pcap_t
*handle
, struct pcap_stat
*stats
)
227 struct pcap_haiku
* handlep
= (struct pcap_haiku
*)handle
->priv
;
228 *stats
= handlep
->stat
;
229 // Now ps_recv and ps_drop are accurate, but ps_ifdrop still equals to
230 // the snapshot value from the activation time.
231 if (ioctl_ifreq(handlep
->aux_socket
, SIOCGIFSTATS
, "SIOCGIFSTATS",
232 &handlep
->ifreq
, handle
->errbuf
) < 0)
234 // The result is subject to wrapping around the 32-bit integer space,
235 // but that cannot be significantly improved as long as it has to fit
236 // into a 32-bit member of pcap_stats.
237 stats
->ps_ifdrop
= handlep
->ifreq
.ifr_stats
.receive
.dropped
- stats
->ps_ifdrop
;
243 pcap_activate_haiku(pcap_t
*handle
)
245 struct pcap_haiku
*handlep
= (struct pcap_haiku
*)handle
->priv
;
246 int ret
= PCAP_ERROR
;
248 // we need a socket to talk to the networking stack
249 if ((handlep
->aux_socket
= dgram_socket(AF_INET
, handle
->errbuf
)) < 0)
252 // pcap_stats_haiku() will need a baseline for ps_ifdrop.
253 // At the time of this writing SIOCGIFSTATS returns EINVAL for AF_LINK
255 if (ioctl_ifreq(handlep
->aux_socket
, SIOCGIFSTATS
, "SIOCGIFSTATS",
256 &handlep
->ifreq
, handle
->errbuf
) < 0) {
257 // Detect a non-existent network interface at least at the
258 // first ioctl() use.
260 ret
= PCAP_ERROR_NO_SUCH_DEVICE
;
263 handlep
->stat
.ps_ifdrop
= handlep
->ifreq
.ifr_stats
.receive
.dropped
;
265 // get link level interface for this interface
266 if ((handle
->fd
= dgram_socket(AF_LINK
, handle
->errbuf
)) < 0)
269 // Derive a DLT from the interface type.
270 // At the time of this writing SIOCGIFTYPE cannot be used for this
271 // purpose: it returns EINVAL for AF_LINK sockets and sets ifr_type to
272 // 0 for AF_INET sockets. Use the same method as Haiku ifconfig does
273 // (SIOCGIFADDR and AF_LINK).
274 if (ioctl_ifreq(handle
->fd
, SIOCGIFADDR
, "SIOCGIFADDR",
275 &handlep
->ifreq
, handle
->errbuf
) < 0)
277 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)&handlep
->ifreq
.ifr_addr
;
278 if (sdl
->sdl_family
!= AF_LINK
) {
279 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
280 "Got AF %d instead of AF_LINK for interface \"%s\".",
281 sdl
->sdl_family
, handle
->opt
.device
);
284 switch (sdl
->sdl_type
) {
286 // Ethernet on all versions, also tap (L2) mode tunnels on
287 // versions after R1/beta4.
288 handle
->linktype
= DLT_EN10MB
;
291 // Unused on R1/beta4 and earlier versions, tun (L3) mode
292 // tunnels on later versions.
294 // The loopback interface on all versions.
295 // Both IFT_TUNNEL and IFT_LOOP prepended a dummy Ethernet
296 // header until hrev57585: https://dev.haiku-os.org/ticket/18801
297 handle
->linktype
= DLT_RAW
;
300 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
301 "Unknown interface type 0x%0x for interface \"%s\".",
302 sdl
->sdl_type
, handle
->opt
.device
);
307 if (ioctl_ifreq(handle
->fd
, SIOCSPACKETCAP
, "SIOCSPACKETCAP",
308 &handlep
->ifreq
, handle
->errbuf
) < 0)
311 handle
->selectable_fd
= handle
->fd
;
312 handle
->read_op
= pcap_read_haiku
;
313 handle
->setfilter_op
= pcapint_install_bpf_program
; /* no kernel filtering */
314 handle
->inject_op
= pcap_inject_haiku
;
315 handle
->stats_op
= pcap_stats_haiku
;
316 handle
->cleanup_op
= pcap_cleanup_haiku
;
318 // use default hooks where possible
319 handle
->getnonblock_op
= pcapint_getnonblock_fd
;
320 handle
->setnonblock_op
= pcapint_setnonblock_fd
;
323 * Turn a negative snapshot value (invalid), a snapshot value of
324 * 0 (unspecified), or a value bigger than the normal maximum
325 * value, into the maximum allowed value.
327 * If some application really *needs* a bigger snapshot
328 * length, we should just increase MAXIMUM_SNAPLEN.
330 if (handle
->snapshot
<= 0 || handle
->snapshot
> MAXIMUM_SNAPLEN
)
331 handle
->snapshot
= MAXIMUM_SNAPLEN
;
333 // Although it would be trivial to size the buffer at the kernel end of
334 // the capture socket using setsockopt() and SO_RCVBUF, there seems to
335 // be no point in doing so: setting the size low silently drops some
336 // packets in the kernel, setting it high does not result in a visible
337 // improvement. Let's leave this buffer as it is until it is clear why
338 // it would need resizing. Meanwhile pcap_set_buffer_size() will have
339 // no effect on Haiku.
341 // It would be wrong to size the buffer at the libpcap end of the
342 // capture socket to the interface MTU, which limits only outgoing
343 // packets and only at layer 3. For example, an Ethernet interface
344 // with ifconfig/ioctl() MTU set to 1500 ordinarily sends layer 2
345 // packets as large as 1514 bytes and receives layer 2 packets as large
346 // as the NIC and the driver happen to accept (e.g. 9018 bytes for
347 // ipro1000). This way, valid packets larger than the MTU can occur in
348 // a capture and will arrive truncated to pcap_read_haiku() if the
349 // buffer is not large enough. So let's keep it large enough for most
350 // if not all practical use cases, then pcap_read_haiku() can handle
351 // the unlikely truncation as and if necessary.
352 handle
->bufsize
= 65536;
354 // allocate buffer for monitoring the device
355 handle
->buffer
= (u_char
*)malloc(handle
->bufsize
);
356 if (handle
->buffer
== NULL
) {
357 pcapint_fmt_errmsg_for_errno(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
358 errno
, "buffer malloc");
362 if (handle
->opt
.promisc
) {
363 // Set promiscuous mode iff required, in any case remember the
365 if ((handlep
->orig_promisc
= get_promisc(handle
)) < 0)
367 if (! handlep
->orig_promisc
&& set_promisc(handle
, 1) < 0)
368 return PCAP_WARNING_PROMISC_NOTSUP
;
372 pcap_cleanup_haiku(handle
);
378 PCAP_WARN_UNUSED_RESULT
379 validate_ifname(const char *device
, char *errbuf
)
381 if (strlen(device
) >= IF_NAMESIZE
) {
382 snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
383 "Interface name \"%s\" is too long.", device
);
390 // #pragma mark - pcap API
394 can_be_bound(const char *name
)
396 if (strcmp(name
, "loop") != 0)
399 // In Haiku versions before hrev57010 the loopback interface allows to
400 // start a capture, but the capture never receives any packets.
402 // Since compiling libpcap on one Haiku version and using the binary on
403 // another seems to be commonplace, comparing B_HAIKU_VERSION at the
404 // compile time would not always work as intended. Let's at least
405 // remove unsuitable well-known 64-bit versions (with or without
406 // updates) from the problem space at run time.
407 const char *badversions
[] = {
408 "hrev56578", // R1/beta4
409 "hrev55182", // R1/beta3
410 "hrev54154", // R1/beta2
411 "hrev52295", // R1/beta1
412 "hrev44702", // R1/alpha4
417 for (const char **s
= badversions
; *s
; s
++)
418 if (! strncmp(uts
.version
, *s
, strlen(*s
)))
425 pcapint_create_interface(const char *device
, char *errorBuffer
)
427 if (validate_ifname(device
, errorBuffer
) < 0)
429 if (! can_be_bound(device
)) {
430 snprintf(errorBuffer
, PCAP_ERRBUF_SIZE
,
431 "Interface \"%s\" does not support capturing traffic.", device
);
435 pcap_t
* handle
= PCAP_CREATE_COMMON(errorBuffer
, struct pcap_haiku
);
438 handle
->activate_op
= pcap_activate_haiku
;
440 struct pcap_haiku
*handlep
= (struct pcap_haiku
*)handle
->priv
;
441 handlep
->aux_socket
= -1;
442 // validate_ifname() has already checked "device" length.
443 (void)pcapint_strlcpy(handlep
->ifreq
.ifr_name
, device
, IF_NAMESIZE
);
450 get_if_flags(const char *name
, bpf_u_int32
*flags
, char *errbuf
)
452 if (validate_ifname(name
, errbuf
) < 0)
455 if (*flags
& PCAP_IF_LOOPBACK
||
456 ! strncmp(name
, "tun", strlen("tun")) ||
457 ! strncmp(name
, "tap", strlen("tap"))) {
459 * Loopback devices aren't wireless, and "connected"/
460 * "disconnected" doesn't apply to them.
462 * Neither does it to tunnel interfaces. A tun mode tunnel
463 * can be identified by the IFT_TUNNEL value, but tap mode
464 * tunnels and Ethernet interfaces both use IFT_ETHER, so let's
465 * use the interface name prefix until there is a better
468 *flags
|= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE
;
472 int fd
= dgram_socket(AF_LINK
, errbuf
);
476 // validate_ifname() has already checked "name" length.
477 (void)pcapint_strlcpy(ifreq
.ifr_name
, name
, IF_NAMESIZE
);
478 if (ioctl_ifreq(fd
, SIOCGIFFLAGS
, "SIOCGIFFLAGS", &ifreq
, errbuf
) < 0) {
482 *flags
|= (ifreq
.ifr_flags
& IFF_LINK
) ?
483 PCAP_IF_CONNECTION_STATUS_CONNECTED
:
484 PCAP_IF_CONNECTION_STATUS_DISCONNECTED
;
485 if (ioctl_ifreq(fd
, SIOCGIFMEDIA
, "SIOCGIFMEDIA", &ifreq
, errbuf
) < 0) {
489 if (IFM_TYPE(ifreq
.ifr_media
) == IFM_IEEE80211
)
490 *flags
|= PCAP_IF_WIRELESS
;
497 pcapint_platform_finddevs(pcap_if_list_t
* _allDevices
, char* errorBuffer
)
499 return pcapint_findalldevs_interfaces(_allDevices
, errorBuffer
, can_be_bound
,
504 * Libpcap version string.
507 pcap_lib_version(void)
509 return (PCAP_VERSION_STRING
);