Skip to content

Commit

Permalink
Add initial implementation for pcap-openvizsla module
Browse files Browse the repository at this point in the history
The module requires libopenvizsla library to communicate with the device.
  • Loading branch information
matwey committed Mar 26, 2023
1 parent 15d0114 commit 41a4cb6
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 0 deletions.
12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2345,6 +2345,18 @@ if(NOT DISABLE_TC)
endif()
endif()

#
# OpenVizsla
#
pkg_check_modules(OPENVIZSLA openvizsla)
if(OPENVIZSLA_FOUND)
set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-openvizsla.c)
include_directories(AFTER ${OPENVIZSLA_INCLUDE_DIRS})
link_directories(AFTER ${OPENVIZSLA_LIBRARY_DIRS})
set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${OPENVIZSLA_LIBRARIES})
set(PCAP_SUPPORT_OPENVIZSLA TRUE)
endif(OPENVIZSLA_FOUND)

#
# Remote capture support.
#
Expand Down
3 changes: 3 additions & 0 deletions cmakeconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@
/* target host supports RDMA sniffing */
#cmakedefine PCAP_SUPPORT_RDMASNIFF 1

/* target host supports OpenVizsla */
#cmakedefine PCAP_SUPPORT_OPENVIZSLA 1

/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1

Expand Down
33 changes: 33 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -3094,6 +3094,39 @@ if test "x$enable_rdma" != "xno"; then
AC_SUBST(PCAP_SUPPORT_RDMASNIFF)
fi

AC_ARG_ENABLE([openvizsla],
[AC_HELP_STRING([--enable-openvizsla],[enable OpenVizsla support @<:@default=yes, if support available@:>@])],
[],
[enable_openvizsla=ifavailable])

if test "xxx_only" = yes; then
# User requested something-else-only pcap, so they don't
# want OpenVizsla support.
enable_openvizsla=no
fi

if test "x$enable_openvizsla" != "xno"; then
if test "x$PKGCONFIG" != "xno"; then
AC_MSG_CHECKING([for libopenvizsla])
if "$PKGCONFIG" openvizsla; then
AC_MSG_RESULT([yes])
OPENVIZSLA_CFLAGS=`"$PKGCONFIG" --cflags openvizsla`
OPENVIZSLA_LIBS=`"$PKGCONFIG" --libs openvizsla`
CFLAGS="$CFLAGS $OPENVIZSLA_CFLAGS"
LIBS="$LIBS $OPENVIZSLA_LIBS"
MODULE_C_SRC="$MODULE_C_SRC pcap-openvizsla.c"

AC_DEFINE(PCAP_SUPPORT_OPENVIZSLA, 1, [support OpenVizsla])
else
AC_MSG_RESULT([no])
if test "x$enable_openvizsla" = "xyes"; then
AC_MSG_ERROR([--enable-openvizsla was given, but the openvizsla package is not installed])
fi
fi
fi
AC_SUBST(PCAP_SUPPORT_OPENVIZSLA)
fi

#
# If this is a platform where we need to have the .pc file and
# pcap-config script supply an rpath option to specify the directory
Expand Down
208 changes: 208 additions & 0 deletions pcap-openvizsla.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include "pcap-int.h"
#include "pcap-openvizsla.h"

#include <openvizsla.h>

#define OPENVIZSLA_IFACE "openvizsla"

struct pcap_openvizsla {
enum ov_usb_speed usb_speed;
struct ov_device* ov;
};

struct pcap_openvizsla_read {
pcap_handler callback;
u_char *user;
};

static void openvizsla_read_cb(struct ov_packet* packet, void* data) {
struct pcap_openvizsla_read* r = (struct pcap_openvizsla_read*)data;

struct pcap_pkthdr pkth;
pkth.caplen = ov_to_host_16(packet->size) + sizeof(struct ov_packet);
pkth.len = pkth.caplen;
pkth.ts.tv_sec = 0;
pkth.ts.tv_usec = 0;

r->callback(r->user, &pkth, (const u_char*)packet);
}

static int openvizsla_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
struct pcap_openvizsla* handlep = handle->priv;
struct pcap_openvizsla_read r;

r.callback = callback;
r.user = user;

int ret = 0;

if ((ret = ov_capture_start(handlep->ov, handle->buffer, handle->bufsize, openvizsla_read_cb, &r)) < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't start capture: %s", ov_get_error_string(handlep->ov));
return PCAP_ERROR;
}

if ((ret = ov_capture_dispatch(handlep->ov, max_packets)) < 0) {
if (handle->break_loop) {
handle->break_loop = 0;

ov_capture_stop(handlep->ov);

return PCAP_ERROR_BREAK;
}

snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"An error occured during capturing: %s", ov_get_error_string(handlep->ov));
return PCAP_ERROR;
}

ov_capture_stop(handlep->ov);

return ret;
}

static void openvizsla_cleanup(pcap_t* handle)
{
struct pcap_openvizsla* handlep = handle->priv;

ov_free(handlep->ov);
pcap_cleanup_live_common(handle);
}

static void openvizsla_breakloop(pcap_t* handle)
{
struct pcap_openvizsla* handlep = handle->priv;

ov_capture_breakloop(handlep->ov);
pcap_breakloop_common(handle);
}

static int openvizsla_activate(pcap_t* handle)
{
struct pcap_openvizsla* handlep = handle->priv;
int ret = 0;

if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
handle->snapshot = MAXIMUM_SNAPLEN;

handle->bufsize = handle->snapshot;
handle->offset = 0;
handle->linktype = DLT_OPENVIZSLA;
handle->buffer = malloc(handle->bufsize);
if (!handle->buffer) {
pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "malloc");
goto fail_buffer_malloc;
}

handle->cleanup_op = openvizsla_cleanup;
handle->read_op = openvizsla_read;
handle->setfilter_op = install_bpf_program; /* no kernel filtering */
handle->breakloop_op = openvizsla_breakloop;

handlep->ov = ov_new(NULL);
if (!handlep->ov) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't create OpenVizsla device handler");
goto fail_ov_init;
}

ret = ov_open(handlep->ov);
if (ret < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't open device: %s", ov_get_error_string(handlep->ov));
goto fail_ov_open;
}

ret = ov_set_usb_speed(handlep->ov, handlep->usb_speed);
if (ret < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't set USB speed: %s", ov_get_error_string(handlep->ov));
goto fail_ov_set_usb_speed;
}

return 0;

fail_ov_set_usb_speed:
fail_ov_open:
ov_free(handlep->ov);
fail_ov_init:
free(handle->buffer);
handle->buffer = NULL;
fail_buffer_malloc:
return PCAP_ERROR;
}

int openvizsla_findalldevs(pcap_if_list_t *devlistp, char *err_str)
{
/* Always find one device */
return 0;
}

pcap_t *openvizsla_create(const char *device, char *ebuf, int *is_ours)
{
const char *cp;
char *cpend;
long devnum;
pcap_t *p;
struct pcap_openvizsla* handlep;
enum ov_usb_speed usb_speed;

cp = strrchr(device, '/');
if (cp == NULL)
cp = device;

if (strncmp(cp, OPENVIZSLA_IFACE, sizeof (OPENVIZSLA_IFACE - 1)) != 0) {
*is_ours = 0;
return NULL;
}

cp += sizeof OPENVIZSLA_IFACE - 1;
devnum = strtol(cp, &cpend, 10);
if (cpend == cp) {
*is_ours = 0;
return NULL;
}
if (devnum < 0) {
*is_ours = 0;
return NULL;
}

switch (*cpend) {
case '\0': /* Fallback to 'l' */
case 'l': {
usb_speed = OV_LOW_SPEED;
} break;
case 'f': {
usb_speed = OV_FULL_SPEED;
} break;
case 'h': {
usb_speed = OV_HIGH_SPEED;
} break;
default: {
*is_ours = 0;
return NULL;
}
}

*is_ours = 1;

p = PCAP_CREATE_COMMON(ebuf, struct pcap_openvizsla);
if (p == NULL)
return NULL;

p->activate_op = openvizsla_activate;

handlep = p->priv;
handlep->usb_speed = usb_speed;

return p;
}
5 changes: 5 additions & 0 deletions pcap-openvizsla.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
* Prototypes for OpenVizsla-related functions
*/
int openvizsla_findalldevs(pcap_if_list_t *devlistp, char *err_str);
pcap_t *openvizsla_create(const char *device, char *ebuf, int *is_ours);
7 changes: 7 additions & 0 deletions pcap.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ struct rtentry; /* declarations in <net/if.h> */
#include "pcap-airpcap.h"
#endif

#ifdef PCAP_SUPPORT_OPENVIZSLA
#include "pcap-openvizsla.h"
#endif

#ifdef _WIN32
/*
* To quote the WSAStartup() documentation:
Expand Down Expand Up @@ -697,6 +701,9 @@ static struct capture_source_type {
#endif
#ifdef HAVE_AIRPCAP_API
{ airpcap_findalldevs, airpcap_create },
#endif
#ifdef PCAP_SUPPORT_OPENVIZSLA
{ openvizsla_findalldevs, openvizsla_create },
#endif
{ NULL, NULL }
};
Expand Down

0 comments on commit 41a4cb6

Please sign in to comment.