diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bb58b9184..4bf93d7e1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1833,6 +1833,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. # @@ -2085,6 +2097,7 @@ set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/grammar.c PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/scanner.h ) + # # Add grammar.c to the list of sources. # diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in index ea87e70ff0..cdaa41f233 100644 --- a/cmakeconfig.h.in +++ b/cmakeconfig.h.in @@ -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 diff --git a/configure b/configure index f0d0aeae19..4ff2838af6 100755 --- a/configure +++ b/configure @@ -623,6 +623,7 @@ ac_subst_vars='LTLIBOBJS INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM +PCAP_SUPPORT_OPENVIZSLA PCAP_SUPPORT_RDMASNIFF PCAP_SUPPORT_DBUS PCAP_SUPPORT_BT @@ -765,6 +766,7 @@ with_dpdk enable_bluetooth enable_dbus enable_rdma +enable_openvizsla ' ac_precious_vars='build_alias host_alias @@ -1414,6 +1416,8 @@ Optional Features: support available] --enable-rdma enable RDMA capture support [default=yes, if support available] + --enable-openvizsla enable OpenVizsla support [default=yes, if support + available] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -11744,6 +11748,43 @@ fi fi +fi + +# Check whether --enable-openvizsla was given. +if test "${enable_openvizsla+set}" = set; then : + enableval=$enable_openvizsla; +else + enable_openvizsla=ifavailable +fi + + +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 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libopenvizsla" >&5 +$as_echo_n "checking for libopenvizsla... " >&6; } + if "$PKGCONFIG" openvizsla; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + 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" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "x$enable_openvizsla" = "xyes"; then + as_fn_error $? "--enable-openvizsla was given, but the openvizsla package is not installed" "$LINENO" 5 + fi + fi + fi + fi # Find a good install program. We prefer a C program (faster), diff --git a/configure.ac b/configure.ac index ac3cc7b78c..9cc2f4c0e4 100644 --- a/configure.ac +++ b/configure.ac @@ -2788,6 +2788,37 @@ 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" + 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 + AC_PROG_INSTALL AC_CONFIG_HEADER(config.h) diff --git a/pcap-openvizsla.c b/pcap-openvizsla.c new file mode 100644 index 0000000000..6de9294e44 --- /dev/null +++ b/pcap-openvizsla.c @@ -0,0 +1,199 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "pcap-int.h" +#include "pcap-openvizsla.h" + +#include + +#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 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 */ + + 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; +} diff --git a/pcap-openvizsla.h b/pcap-openvizsla.h new file mode 100644 index 0000000000..b60c522db6 --- /dev/null +++ b/pcap-openvizsla.h @@ -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); diff --git a/pcap.c b/pcap.c index 58ef71d279..ca305dbc65 100644 --- a/pcap.c +++ b/pcap.c @@ -129,6 +129,10 @@ struct rtentry; /* declarations in */ #include "pcap-airpcap.h" #endif +#ifdef PCAP_SUPPORT_OPENVIZSLA +#include "pcap-openvizsla.h" +#endif + #ifdef _WIN32 /* * DllMain(), required when built as a Windows DLL. @@ -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 } };