diff options
Diffstat (limited to 'pcap-haiku.cpp')
-rw-r--r-- | pcap-haiku.cpp | 305 |
1 files changed, 0 insertions, 305 deletions
diff --git a/pcap-haiku.cpp b/pcap-haiku.cpp deleted file mode 100644 index 8ae9119c2ccf..000000000000 --- a/pcap-haiku.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Axel Dörfler, axeld@pinc-software.de - * James Woodcock - */ - - -#include "config.h" -#include "pcap-int.h" - -#include <OS.h> - -#include <sys/socket.h> -#include <sys/sockio.h> - -#include <net/if.h> -#include <net/if_dl.h> -#include <net/if_types.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - - -/* - * Private data for capturing on Haiku sockets. - */ -struct pcap_haiku { - struct pcap_stat stat; - char *device; /* device name */ -}; - - -bool -prepare_request(struct ifreq& request, const char* name) -{ - if (strlen(name) >= IF_NAMESIZE) - return false; - - strcpy(request.ifr_name, name); - return true; -} - - -static int -pcap_read_haiku(pcap_t* handle, int maxPackets _U_, pcap_handler callback, - u_char* userdata) -{ - // Receive a single packet - - u_char* buffer = (u_char*)handle->buffer + handle->offset; - struct sockaddr_dl from; - ssize_t bytesReceived; - do { - if (handle->break_loop) { - // Clear the break loop flag, and return -2 to indicate our - // reasoning - handle->break_loop = 0; - return -2; - } - - socklen_t fromLength = sizeof(from); - bytesReceived = recvfrom(handle->fd, buffer, handle->bufsize, MSG_TRUNC, - (struct sockaddr*)&from, &fromLength); - } while (bytesReceived < 0 && errno == B_INTERRUPTED); - - if (bytesReceived < 0) { - if (errno == B_WOULD_BLOCK) { - // there is no packet for us - return 0; - } - - snprintf(handle->errbuf, sizeof(handle->errbuf), - "recvfrom: %s", strerror(errno)); - return -1; - } - - int32 captureLength = bytesReceived; - if (captureLength > handle->snapshot) - captureLength = handle->snapshot; - - // run the packet filter - if (handle->fcode.bf_insns) { - if (pcap_filter(handle->fcode.bf_insns, buffer, bytesReceived, - captureLength) == 0) { - // packet got rejected - return 0; - } - } - - // fill in pcap_header - pcap_pkthdr header; - header.caplen = captureLength; - header.len = bytesReceived; - header.ts.tv_usec = system_time() % 1000000; - header.ts.tv_sec = system_time() / 1000000; - // TODO: get timing from packet!!! - - /* Call the user supplied callback function */ - callback(userdata, &header, buffer); - return 1; -} - - -static int -pcap_inject_haiku(pcap_t *handle, const void *buffer, int size) -{ - // we don't support injecting packets yet - // TODO: use the AF_LINK protocol (we need another socket for this) to - // inject the packets - strlcpy(handle->errbuf, "Sending packets isn't supported yet", - PCAP_ERRBUF_SIZE); - return -1; -} - - -static int -pcap_stats_haiku(pcap_t *handle, struct pcap_stat *stats) -{ - struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv; - ifreq request; - int socket = ::socket(AF_INET, SOCK_DGRAM, 0); - if (socket < 0) { - return -1; - } - prepare_request(request, handlep->device); - if (ioctl(socket, SIOCGIFSTATS, &request, sizeof(struct ifreq)) < 0) { - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_stats: %s", - strerror(errno)); - close(socket); - return -1; - } - - close(socket); - handlep->stat.ps_recv += request.ifr_stats.receive.packets; - handlep->stat.ps_drop += request.ifr_stats.receive.dropped; - *stats = handlep->stat; - return 0; -} - - -static int -pcap_activate_haiku(pcap_t *handle) -{ - struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv; - - const char* device = handle->opt.device; - - handle->read_op = pcap_read_haiku; - handle->setfilter_op = install_bpf_program; /* no kernel filtering */ - handle->inject_op = pcap_inject_haiku; - handle->stats_op = pcap_stats_haiku; - - // use default hooks where possible - handle->getnonblock_op = pcap_getnonblock_fd; - handle->setnonblock_op = pcap_setnonblock_fd; - - /* - * Turn a negative snapshot value (invalid), a snapshot value of - * 0 (unspecified), or a value bigger than the normal maximum - * value, into the maximum allowed value. - * - * If some application really *needs* a bigger snapshot - * length, we should just increase MAXIMUM_SNAPLEN. - */ - if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN) - handle->snapshot = MAXIMUM_SNAPLEN; - - handlep->device = strdup(device); - if (handlep->device == NULL) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, - errno, "strdup"); - return PCAP_ERROR; - } - - handle->bufsize = 65536; - // TODO: should be determined by interface MTU - - // allocate buffer for monitoring the device - handle->buffer = (u_char*)malloc(handle->bufsize); - if (handle->buffer == NULL) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, - errno, "buffer malloc"); - return PCAP_ERROR; - } - - handle->offset = 0; - handle->linktype = DLT_EN10MB; - // TODO: check interface type! - - return 0; -} - - -// #pragma mark - pcap API - - -extern "C" pcap_t * -pcap_create_interface(const char *device, char *errorBuffer) -{ - // TODO: handle promiscuous mode! - - // we need a socket to talk to the networking stack - int socket = ::socket(AF_INET, SOCK_DGRAM, 0); - if (socket < 0) { - snprintf(errorBuffer, PCAP_ERRBUF_SIZE, - "The networking stack doesn't seem to be available.\n"); - return NULL; - } - - struct ifreq request; - if (!prepare_request(request, device)) { - snprintf(errorBuffer, PCAP_ERRBUF_SIZE, - "Interface name \"%s\" is too long.", device); - close(socket); - return NULL; - } - - // check if the interface exist - if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) < 0) { - snprintf(errorBuffer, PCAP_ERRBUF_SIZE, - "Interface \"%s\" does not exist.\n", device); - close(socket); - return NULL; - } - - close(socket); - // no longer needed after this point - - // get link level interface for this interface - - socket = ::socket(AF_LINK, SOCK_DGRAM, 0); - if (socket < 0) { - snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "No link level: %s\n", - strerror(errno)); - return NULL; - } - - // start monitoring - if (ioctl(socket, SIOCSPACKETCAP, &request, sizeof(struct ifreq)) < 0) { - snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot start monitoring: %s\n", - strerror(errno)); - close(socket); - return NULL; - } - - struct wrapper_struct { pcap_t __common; struct pcap_haiku __private; }; - pcap_t* handle = pcap_create_common(errorBuffer, - sizeof (struct wrapper_struct), - offsetof (struct wrapper_struct, __private)); - - if (handle == NULL) { - snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "malloc: %s", strerror(errno)); - close(socket); - return NULL; - } - - handle->selectable_fd = socket; - handle->fd = socket; - - handle->activate_op = pcap_activate_haiku; - - return handle; -} - -static int -can_be_bound(const char *name _U_) -{ - return 1; -} - -static int -get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf) -{ - /* TODO */ - if (*flags & PCAP_IF_LOOPBACK) { - /* - * Loopback devices aren't wireless, and "connected"/ - * "disconnected" doesn't apply to them. - */ - *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE; - return (0); - } - return (0); -} - -extern "C" int -pcap_platform_finddevs(pcap_if_list_t* _allDevices, char* errorBuffer) -{ - return pcap_findalldevs_interfaces(_allDevices, errorBuffer, can_be_bound, - get_if_flags); -} - -/* - * Libpcap version string. - */ -extern "C" const char * -pcap_lib_version(void) -{ - return (PCAP_VERSION_STRING); -} |