Control: tags 962208 + patch Control: tags 962208 + pending Control: tags 965694 + patch Control: tags 965694 + pending
Dear maintainer, I've prepared an NMU for libtrace3 (versioned as 3.0.22-0.1) and uploaded it to DELAYED/15. Please feel free to tell me if I should cancel it. cu Adrian
diff -Nru libtrace3-3.0.21/configure libtrace3-3.0.22/configure --- libtrace3-3.0.21/configure 2014-09-09 00:55:29.000000000 +0300 +++ libtrace3-3.0.22/configure 2015-02-10 06:56:58.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libtrace 3.0.21. +# Generated by GNU Autoconf 2.69 for libtrace 3.0.22. # # Report bugs to <cont...@wand.net.nz>. # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='libtrace' PACKAGE_TARNAME='libtrace' -PACKAGE_VERSION='3.0.21' -PACKAGE_STRING='libtrace 3.0.21' +PACKAGE_VERSION='3.0.22' +PACKAGE_STRING='libtrace 3.0.22' PACKAGE_BUGREPORT='cont...@wand.net.nz' PACKAGE_URL='' @@ -1394,7 +1394,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libtrace 3.0.21 to adapt to many kinds of systems. +\`configure' configures libtrace 3.0.22 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1464,7 +1464,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libtrace 3.0.21:";; + short | recursive ) echo "Configuration of libtrace 3.0.22:";; esac cat <<\_ACEOF @@ -1582,7 +1582,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libtrace configure 3.0.21 +libtrace configure 3.0.22 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2503,7 +2503,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libtrace $as_me 3.0.21, which was +It was created by libtrace $as_me 3.0.22, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2854,7 +2854,7 @@ LIBTRACE_MAJOR=3 LIBTRACE_MID=0 -LIBTRACE_MINOR=21 +LIBTRACE_MINOR=22 # OpenSolaris hides libraries like libncurses in /usr/gnu/lib, which is not # searched by default - add it to LDFLAGS so we at least have a chance of @@ -3332,7 +3332,7 @@ # Define the identity of the package. PACKAGE='libtrace' - VERSION='3.0.21' + VERSION='3.0.22' cat >>confdefs.h <<_ACEOF @@ -17942,6 +17942,9 @@ if test "$ac_cv_search_dlopen" != "none required"; then LIBPKTDUMP_LIBS="$LIBPKTDUMP_LIBS $ac_cv_search_dlopen" + if test "$dpdk_found" = 1; then + LIBTRACE_LIBS="$LIBTRACE_LIBS -Wl,$ac_cv_search_dlopen" + fi fi if test "$have_pthread" = 1; then @@ -19255,7 +19258,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libtrace $as_me 3.0.21, which was +This file was extended by libtrace $as_me 3.0.22, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -19321,7 +19324,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libtrace config.status 3.0.21 +libtrace config.status 3.0.22 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru libtrace3-3.0.21/configure.in libtrace3-3.0.22/configure.in --- libtrace3-3.0.21/configure.in 2014-09-09 00:55:18.000000000 +0300 +++ libtrace3-3.0.22/configure.in 2015-02-10 06:56:03.000000000 +0200 @@ -3,11 +3,11 @@ # Now you only need to update the version number in two places - below, # and in the README -AC_INIT([libtrace],[3.0.21],[cont...@wand.net.nz],[libtrace]) +AC_INIT([libtrace],[3.0.22],[cont...@wand.net.nz],[libtrace]) LIBTRACE_MAJOR=3 LIBTRACE_MID=0 -LIBTRACE_MINOR=21 +LIBTRACE_MINOR=22 # OpenSolaris hides libraries like libncurses in /usr/gnu/lib, which is not # searched by default - add it to LDFLAGS so we at least have a chance of @@ -417,6 +417,9 @@ if test "$ac_cv_search_dlopen" != "none required"; then LIBPKTDUMP_LIBS="$LIBPKTDUMP_LIBS $ac_cv_search_dlopen" + if test "$dpdk_found" = 1; then + LIBTRACE_LIBS="$LIBTRACE_LIBS -Wl,$ac_cv_search_dlopen" + fi fi if test "$have_pthread" = 1; then diff -Nru libtrace3-3.0.21/debian/changelog libtrace3-3.0.22/debian/changelog --- libtrace3-3.0.21/debian/changelog 2014-10-24 02:51:45.000000000 +0300 +++ libtrace3-3.0.22/debian/changelog 2022-01-06 18:13:17.000000000 +0200 @@ -1,3 +1,12 @@ +libtrace3 (3.0.22-0.1) unstable; urgency=low + + * Non-maintainer upload. + * New upstream release. + * Backport upstream fix for FTBFS with glibc 2.31. (Closes: #962208) + * debian/compat: 5 -> 7. (Closes: #965694) + + -- Adrian Bunk <b...@debian.org> Thu, 06 Jan 2022 18:13:17 +0200 + libtrace3 (3.0.21-1) unstable; urgency=medium * New upstream release diff -Nru libtrace3-3.0.21/debian/compat libtrace3-3.0.22/debian/compat --- libtrace3-3.0.21/debian/compat 2009-05-27 02:20:57.000000000 +0300 +++ libtrace3-3.0.22/debian/compat 2022-01-06 17:55:38.000000000 +0200 @@ -1 +1 @@ -5 +7 diff -Nru libtrace3-3.0.21/debian/patches/0001-Fix-SIOCGSTAMP-undeclared-error-on-new-linux-kernels.patch libtrace3-3.0.22/debian/patches/0001-Fix-SIOCGSTAMP-undeclared-error-on-new-linux-kernels.patch --- libtrace3-3.0.21/debian/patches/0001-Fix-SIOCGSTAMP-undeclared-error-on-new-linux-kernels.patch 1970-01-01 02:00:00.000000000 +0200 +++ libtrace3-3.0.22/debian/patches/0001-Fix-SIOCGSTAMP-undeclared-error-on-new-linux-kernels.patch 2022-01-06 17:55:38.000000000 +0200 @@ -0,0 +1,20 @@ +From cd7f4c79aa55823d2e3be9b753088c40bc44d183 Mon Sep 17 00:00:00 2001 +From: Shane Alcock <salc...@waikato.ac.nz> +Date: Mon, 19 Aug 2019 11:53:41 +1200 +Subject: Fix SIOCGSTAMP undeclared error on new linux kernels. + +diff --git a/lib/format_linux_common.h b/lib/format_linux_common.h +index 244144b1..b6a66d30 100644 +--- a/lib/format_linux.c ++++ b/lib/format_linux.c +@@ -44,6 +44,7 @@ + #include <netpacket/packet.h> + #include <net/ethernet.h> + #include <net/if_arp.h> ++#include <linux/sockios.h> + + #include <net/if.h> + #include <sys/ioctl.h> +-- +2.20.1 + diff -Nru libtrace3-3.0.21/debian/patches/series libtrace3-3.0.22/debian/patches/series --- libtrace3-3.0.21/debian/patches/series 1970-01-01 02:00:00.000000000 +0200 +++ libtrace3-3.0.22/debian/patches/series 2022-01-06 17:55:38.000000000 +0200 @@ -0,0 +1 @@ +0001-Fix-SIOCGSTAMP-undeclared-error-on-new-linux-kernels.patch diff -Nru libtrace3-3.0.21/lib/format_dag25.c libtrace3-3.0.22/lib/format_dag25.c --- libtrace3-3.0.21/lib/format_dag25.c 2014-09-08 05:34:51.000000000 +0300 +++ libtrace3-3.0.22/lib/format_dag25.c 2015-02-10 06:54:12.000000000 +0200 @@ -103,6 +103,8 @@ /* "Global" data that is stored for each DAG output trace */ struct dag_format_data_out_t { + /* String containing the DAG device name */ + char *device_name; /* The DAG device being used for writing */ struct dag_dev_t *device; /* The DAG stream that is being written on */ @@ -131,7 +133,9 @@ libtrace_t *dummy_duck; } duck; - /* The DAG device that we are reading from */ + /* String containing the DAG device name */ + char *device_name; + /* The DAG device that we are reading from */ struct dag_dev_t *device; /* The DAG stream that we are reading from */ unsigned int dagstream; @@ -145,6 +149,8 @@ uint32_t processed; /* The number of packets that have been dropped */ uint64_t drops; + + uint8_t seeninterface[4]; }; /* To be thread-safe, we're going to need a mutex for operating on the list @@ -205,6 +211,7 @@ // no DUCK on output FORMAT_DATA_OUT->stream_attached = 0; FORMAT_DATA_OUT->device = NULL; + FORMAT_DATA_OUT->device_name = NULL; FORMAT_DATA_OUT->dagstream = 0; FORMAT_DATA_OUT->waiting = 0; @@ -220,11 +227,13 @@ DUCK.dummy_duck = NULL; FORMAT_DATA->stream_attached = 0; FORMAT_DATA->drops = 0; + FORMAT_DATA->device_name = NULL; FORMAT_DATA->device = NULL; FORMAT_DATA->dagstream = 0; FORMAT_DATA->processed = 0; FORMAT_DATA->bottom = NULL; FORMAT_DATA->top = NULL; + memset(FORMAT_DATA->seeninterface, 0, sizeof(FORMAT_DATA->seeninterface)); } /* Determines if there is already an entry for the given DAG device in the @@ -274,7 +283,7 @@ dag_close(dev->fd); if (dev->dev_name) - free(dev->dev_name); + free(dev->dev_name); free(dev); } @@ -388,7 +397,6 @@ /* Creates and initialises a DAG output trace */ static int dag_init_output(libtrace_out_t *libtrace) { - char *dag_dev_name = NULL; char *scan = NULL; struct dag_dev_t *dag_device = NULL; int stream = 1; @@ -411,30 +419,29 @@ * * If no stream is specified, we will write using stream 1 */ if ((scan = strchr(libtrace->uridata,',')) == NULL) { - dag_dev_name = strdup(libtrace->uridata); + FORMAT_DATA_OUT->device_name = strdup(libtrace->uridata); } else { - dag_dev_name = (char *)strndup(libtrace->uridata, + FORMAT_DATA_OUT->device_name = + (char *)strndup(libtrace->uridata, (size_t)(scan - libtrace->uridata)); stream = atoi(++scan); } FORMAT_DATA_OUT->dagstream = stream; /* See if our DAG device is already open */ - dag_device = dag_find_open_device(dag_dev_name); + dag_device = dag_find_open_device(FORMAT_DATA_OUT->device_name); if (dag_device == NULL) { /* Device not yet opened - open it ourselves */ - dag_device = dag_open_output_device(libtrace, dag_dev_name); - } else { - /* Otherwise, just use the existing one */ - free(dag_dev_name); - dag_dev_name = NULL; + dag_device = dag_open_output_device(libtrace, + FORMAT_DATA_OUT->device_name); } /* Make sure we have successfully opened a DAG device */ if (dag_device == NULL) { - if (dag_dev_name) { - free(dag_dev_name); + if (FORMAT_DATA_OUT->device_name) { + free(FORMAT_DATA_OUT->device_name); + FORMAT_DATA_OUT->device_name = NULL; } pthread_mutex_unlock(&open_dag_mutex); return -1; @@ -447,7 +454,6 @@ /* Creates and initialises a DAG input trace */ static int dag_init_input(libtrace_t *libtrace) { - char *dag_dev_name = NULL; char *scan = NULL; int stream = 0; struct dag_dev_t *dag_device = NULL; @@ -463,9 +469,9 @@ * * If no stream is specified, we will read from stream 0 */ if ((scan = strchr(libtrace->uridata,',')) == NULL) { - dag_dev_name = strdup(libtrace->uridata); + FORMAT_DATA->device_name = strdup(libtrace->uridata); } else { - dag_dev_name = (char *)strndup(libtrace->uridata, + FORMAT_DATA->device_name = (char *)strndup(libtrace->uridata, (size_t)(scan - libtrace->uridata)); stream = atoi(++scan); } @@ -473,22 +479,18 @@ FORMAT_DATA->dagstream = stream; /* See if our DAG device is already open */ - dag_device = dag_find_open_device(dag_dev_name); + dag_device = dag_find_open_device(FORMAT_DATA->device_name); if (dag_device == NULL) { /* Device not yet opened - open it ourselves */ - dag_device = dag_open_device(libtrace, dag_dev_name); - } else { - /* Otherwise, just use the existing one */ - free(dag_dev_name); - dag_dev_name = NULL; + dag_device=dag_open_device(libtrace, FORMAT_DATA->device_name); } /* Make sure we have successfully opened a DAG device */ if (dag_device == NULL) { - if (dag_dev_name) - free(dag_dev_name); - dag_dev_name = NULL; + if (FORMAT_DATA->device_name) + free(FORMAT_DATA->device_name); + FORMAT_DATA->device_name = NULL; pthread_mutex_unlock(&open_dag_mutex); return -1; } @@ -520,7 +522,7 @@ case TRACE_OPTION_META_FREQ: /* This option is used to specify the frequency of DUCK * updates */ - DUCK.duck_freq = *(int *)data; + DUCK.duck_freq = *(int *)data; return 0; case TRACE_OPTION_SNAPLEN: /* Tell the card our new snap length */ @@ -556,7 +558,7 @@ /* Attach and start the DAG stream */ if (dag_attach_stream(FORMAT_DATA_OUT->device->fd, - FORMAT_DATA_OUT->dagstream, 0, 1048576) < 0) { + FORMAT_DATA_OUT->dagstream, 0, 4 * 1024 * 1024) < 0) { trace_set_err_out(libtrace, errno, "Cannot attach DAG stream"); return -1; } @@ -580,8 +582,7 @@ /* Starts a DAG input trace */ static int dag_start_input(libtrace_t *libtrace) { struct timeval zero, nopoll; - uint8_t *top, *bottom; - uint8_t diff = 0; + uint8_t *top, *bottom, *starttop; top = bottom = NULL; zero.tv_sec = 0; @@ -607,17 +608,20 @@ FORMAT_DATA->dagstream, 0, &zero, &nopoll); + starttop = dag_advance_stream(FORMAT_DATA->device->fd, + FORMAT_DATA->dagstream, + &bottom); + /* Should probably flush the memory hole now */ - do { + top = starttop; + while (starttop - bottom > 0) { + bottom += (starttop - bottom); top = dag_advance_stream(FORMAT_DATA->device->fd, FORMAT_DATA->dagstream, &bottom); - assert(top && bottom); - diff = top - bottom; - bottom -= diff; - } while (diff != 0); - FORMAT_DATA->top = NULL; - FORMAT_DATA->bottom = NULL; + } + FORMAT_DATA->top = top; + FORMAT_DATA->bottom = bottom; FORMAT_DATA->processed = 0; FORMAT_DATA->drops = 0; @@ -675,6 +679,8 @@ dag_close_device(FORMAT_DATA->device); if (DUCK.dummy_duck) trace_destroy_dead(DUCK.dummy_duck); + if (FORMAT_DATA->device_name) + free(FORMAT_DATA->device_name); free(libtrace->format_data); pthread_mutex_unlock(&open_dag_mutex); return 0; /* success */ @@ -708,15 +714,42 @@ /* Close the DAG device if there are no more references to it */ if (FORMAT_DATA_OUT->device->ref_count == 0) dag_close_device(FORMAT_DATA_OUT->device); + if (FORMAT_DATA_OUT->device_name) + free(FORMAT_DATA_OUT->device_name); free(libtrace->format_data); pthread_mutex_unlock(&open_dag_mutex); return 0; /* success */ } +#ifdef DAGIOC_CARD_DUCK +#define LIBTRACE_DUCK_IOCTL DAGIOC_CARD_DUCK +#define LIBTRACE_DUCK_VERSION TRACE_RT_DUCK_5_0 +#else +#ifdef DAGIOCDUCK +#define LIBTRACE_DUCK_IOCTL DAGIOCDUCK +#define LIBTRACE_DUCK_VERSION TRACE_RT_DUCK_2_5 +#else +#warning "DAG appears to be missing DUCK support" +#endif +#endif + /* Extracts DUCK information from the DAG card and produces a DUCK packet */ static int dag_get_duckinfo(libtrace_t *libtrace, libtrace_packet_t *packet) { + if (DUCK.duck_freq == 0) + return 0; + +#ifndef LIBTRACE_DUCK_IOCTL + trace_set_err(libtrace, errno, + "Requested DUCK information but unable to determine the correct ioctl for DUCK"); + DUCK.duck_freq = 0; + return -1; +#endif + + if (DUCK.last_pkt - DUCK.last_duck < DUCK.duck_freq) + return 0; + /* Allocate memory for the DUCK data */ if (packet->buf_control == TRACE_CTRL_EXTERNAL || !packet->buffer) { @@ -735,20 +768,22 @@ /* No need to check if we can get DUCK or not - we're modern * enough so just grab the DUCK info */ - if ((ioctl(FORMAT_DATA->device->fd, DAGIOCDUCK, + if ((ioctl(FORMAT_DATA->device->fd, LIBTRACE_DUCK_IOCTL, (duckinf_t *)packet->payload) < 0)) { - trace_set_err(libtrace, errno, "Error using DAGIOCDUCK"); + trace_set_err(libtrace, errno, "Error using DUCK ioctl"); + DUCK.duck_freq = 0; return -1; } - packet->type = TRACE_RT_DUCK_2_5; + packet->type = LIBTRACE_DUCK_VERSION; - /* Set the packet's tracce to point at a DUCK trace, so that the + /* Set the packet's trace to point at a DUCK trace, so that the * DUCK format functions will be called on the packet rather than the * DAG ones */ if (!DUCK.dummy_duck) - DUCK.dummy_duck = trace_create_dead("rt:localhost:3434"); + DUCK.dummy_duck = trace_create_dead("duck:dummy"); packet->trace = DUCK.dummy_duck; + DUCK.last_duck = DUCK.last_pkt; return sizeof(duckinf_t); } @@ -842,7 +877,11 @@ /* TODO */ } else { /* Use the ERF loss counter */ - DATA(libtrace)->drops += ntohs(erfptr->lctr); + if (FORMAT_DATA->seeninterface[erfptr->flags.iface] == 0) { + FORMAT_DATA->seeninterface[erfptr->flags.iface] = 1; + } else { + FORMAT_DATA->drops += ntohs(erfptr->lctr); + } } return 0; @@ -1043,16 +1082,11 @@ maxwait.tv_usec = 250000; /* Check if we're due for a DUCK report */ - if (DUCK.last_pkt - DUCK.last_duck > DUCK.duck_freq && - DUCK.duck_freq != 0) { - size = dag_get_duckinfo(libtrace, packet); - DUCK.last_duck = DUCK.last_pkt; - if (size != 0) { - return size; - } - /* No DUCK support, so don't waste our time anymore */ - DUCK.duck_freq = 0; - } + size = dag_get_duckinfo(libtrace, packet); + + if (size != 0) + return size; + /* Don't let anyone try to free our DAG memory hole! */ flags |= TRACE_PREP_DO_NOT_OWN_BUFFER; @@ -1110,10 +1144,20 @@ dag_record_t *erfptr = NULL; int numbytes; uint32_t flags = 0; - struct timeval minwait; + struct timeval minwait, tv; minwait.tv_sec = 0; minwait.tv_usec = 10000; + + /* Check if we're meant to provide a DUCK update */ + numbytes = dag_get_duckinfo(libtrace, packet); + if (numbytes < 0) { + event.type = TRACE_EVENT_TERMINATE; + return event; + } else if (numbytes > 0) { + event.type = TRACE_EVENT_PACKET; + return event; + } if (dag_set_stream_poll(FORMAT_DATA->device->fd, FORMAT_DATA->dagstream, 0, &minwait, @@ -1186,6 +1230,10 @@ event.type = TRACE_EVENT_PACKET; } + /* Update the DUCK timer */ + tv = trace_get_timeval(packet); + DUCK.last_pkt = tv.tv_sec; + if (libtrace->snaplen > 0) { trace_set_capture_length(packet, libtrace->snaplen); } diff -Nru libtrace3-3.0.21/lib/format_dpdk.c libtrace3-3.0.22/lib/format_dpdk.c --- libtrace3-3.0.21/lib/format_dpdk.c 2014-09-05 00:22:50.000000000 +0300 +++ libtrace3-3.0.22/lib/format_dpdk.c 2015-02-10 06:56:03.000000000 +0200 @@ -1,3 +1,4 @@ + /* * This file is part of libtrace * @@ -68,7 +69,8 @@ * Below this is a log of version that required changes to the libtrace * code (that we still attempt to support). * - * Currently 1.5 to 1.7 is supported. + * DPDK v1.7.1 is recommended. + * However 1.5 to 1.8 are likely supported. */ #include <rte_eal.h> #include <rte_version.h> @@ -85,7 +87,10 @@ /* 1.6.0r2 : * rte_eal_pci_set_blacklist() is removed - * device_list is renamed ot pci_device_list + * device_list is renamed to pci_device_list + * In the 1.7.0 release rte_eal_pci_probe is called by rte_eal_init + * as such we do apply the whitelist before rte_eal_init. + * This also works correctly with DPDK 1.6.0r2. * * Replaced by: * rte_devargs (we can simply whitelist) @@ -109,6 +114,28 @@ # define DPDK_USE_PMD_INIT 0 #endif +/* 1.7.0-rc3 : + * + * Since 1.7.0-rc3 rte_eal_pci_probe is called as part of rte_eal_init. + * Somewhere between 1.7 and 1.8 calling it twice broke so we should not call + * it twice. + */ +#if RTE_VERSION < RTE_VERSION_NUM(1, 7, 0, 3) +# define DPDK_USE_PCI_PROBE 1 +#else +# define DPDK_USE_PCI_PROBE 0 +#endif + +/* 1.8.0-rc1 : + * LOG LEVEL is a command line option which overrides what + * we previously set it to. + */ +#if RTE_VERSION >= RTE_VERSION_NUM(1, 8, 0, 1) +# define DPDK_USE_LOG_LEVEL 1 +#else +# define DPDK_USE_LOG_LEVEL 0 +#endif + #include <rte_per_lcore.h> #include <rte_debug.h> #include <rte_errno.h> @@ -328,7 +355,7 @@ } #else /* DPDK_USE_BLACKLIST */ #include <rte_devargs.h> -static int blacklist_devices(struct dpdk_format_data_t *format_data UNUSED, struct rte_pci_addr *whitelist) +static int whitelist_device(struct dpdk_format_data_t *format_data UNUSED, struct rte_pci_addr *whitelist) { char pci_str[20] = {0}; snprintf(pci_str, sizeof(pci_str), PCI_PRI_FMT, @@ -352,43 +379,15 @@ * or ./libtrace dpdk:0:1:0.1-2 -> 0:1:0.1 (Using CPU core #2) */ static int parse_pciaddr(char * str, struct rte_pci_addr * addr, long * core) { - char * wrkstr; - char * pch; + int matches; assert(str); - wrkstr = strdup(str); - - pch = strtok(wrkstr,":"); - if (pch == NULL || pch[0] == 0) { - free(wrkstr); return -1; - } - addr->domain = (uint16_t) atoi(pch); - - pch = strtok(NULL,":"); - if (pch == NULL || pch[0] == 0) { - free(wrkstr); return -1; - } - addr->bus = (uint8_t) atoi(pch); - - pch = strtok(NULL,"."); - if (pch == NULL || pch[0] == 0) { - free(wrkstr); return -1; - } - addr->devid = (uint8_t) atoi(pch); - - pch = strtok(NULL,"-"); /* Might not find the '-' it's optional */ - if (pch == NULL || pch[0] == 0) { - free(wrkstr); return -1; - } - addr->function = (uint8_t) atoi(pch); - - pch = strtok(NULL, ""); /* Find end of string */ - - if (pch != NULL && pch[0] != 0) { - *core = (long) atoi(pch); + matches = sscanf(str, "%4"SCNx16":%2"SCNx8":%2"SCNx8".%2"SCNx8"-%ld", + &addr->domain, &addr->bus, &addr->devid, &addr->function, core); + if (matches >= 4) { + return 0; + } else { + return -1; } - - free(wrkstr); - return 0; } #if DEBUG @@ -397,31 +396,30 @@ { struct rte_config * global_config; long nb_cpu = sysconf(_SC_NPROCESSORS_ONLN); - + if (nb_cpu <= 0) { perror("sysconf(_SC_NPROCESSORS_ONLN) failed. Falling back to the first core."); nb_cpu = 1; /* fallback to just 1 core */ } if (nb_cpu > RTE_MAX_LCORE) nb_cpu = RTE_MAX_LCORE; - + global_config = rte_eal_get_configuration(); - + if (global_config != NULL) { int i; fprintf(stderr, "Intel DPDK setup\n" - "---Version : %"PRIu32"\n" - "---Magic : %"PRIu32"\n" + "---Version : %s\n" "---Master LCore : %"PRIu32"\n" "---LCore Count : %"PRIu32"\n", - global_config->version, global_config->magic, + rte_version(), global_config->master_lcore, global_config->lcore_count); - + for (i = 0 ; i < nb_cpu; i++) { - fprintf(stderr, " ---Core %d : %s\n", i, + fprintf(stderr, " ---Core %d : %s\n", i, global_config->lcore_role[i] == ROLE_RTE ? "on" : "off"); } - + const char * proc_type; switch (global_config->process_type) { case RTE_PROC_AUTO: @@ -441,7 +439,7 @@ } fprintf(stderr, "---Process Type : %s\n", proc_type); } - + } #endif @@ -485,7 +483,7 @@ #if DEBUG rte_set_log_level(RTE_LOG_DEBUG); -#else +#else rte_set_log_level(RTE_LOG_WARNING); #endif /* @@ -493,8 +491,20 @@ * the two processes. However be careful we still cannot access a * port that already in use. */ - char* argv[] = {"libtrace", "-c", cpu_number, "-n", "1", "--proc-type", "auto", - "--file-prefix", mem_map, "-m", "256", NULL}; + char* argv[] = {"libtrace", + "-c", cpu_number, + "-n", "1", + "--proc-type", "auto", + "--file-prefix", mem_map, + "-m", "256", +#if DPDK_USE_LOG_LEVEL +# if DEBUG + "--log-level", "8", /* RTE_LOG_DEBUG */ +# else + "--log-level", "5", /* RTE_LOG_WARNING */ +# endif +#endif + NULL}; int argc = sizeof(argv) / sizeof(argv[0]) - 1; /* This initialises the Environment Abstraction Layer (EAL) @@ -542,6 +552,14 @@ /* Make our mask */ snprintf(cpu_number, sizeof(cpu_number), "%x", 0x1 << (my_cpu - 1)); +#if !DPDK_USE_BLACKLIST + /* Black list all ports besides the one that we want to use */ + if ((ret = whitelist_device(format_data, &use_addr)) < 0) { + snprintf(err, errlen, "Intel DPDK - Whitelisting PCI device failed," + " are you sure the address is correct?: %s", strerror(-ret)); + return -1; + } +#endif /* Give the memory map a unique name */ snprintf(mem_map, sizeof(mem_map), "libtrace-%d", (int) getpid()); @@ -571,19 +589,23 @@ } #endif +#if DPDK_USE_BLACKLIST /* Blacklist all ports besides the one that we want to use */ if ((ret = blacklist_devices(format_data, &use_addr)) < 0) { snprintf(err, errlen, "Intel DPDK - Whitelisting PCI device failed," " are you sure the address is correct?: %s", strerror(-ret)); return -1; } +#endif +#if DPDK_USE_PCI_PROBE /* This loads DPDK drivers against all ports that are not blacklisted */ if ((ret = rte_eal_pci_probe()) < 0) { snprintf(err, errlen, "Intel DPDK - rte_eal_pci_probe failed: %s", strerror(-ret)); return -1; } +#endif format_data->nb_ports = rte_eth_dev_count(); @@ -844,7 +866,7 @@ + RTE_PKTMBUF_HEADROOM, 8, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, - 0, MEMPOOL_F_SP_PUT | MEMPOOL_F_SC_GET); + rte_socket_id(), MEMPOOL_F_SP_PUT | MEMPOOL_F_SC_GET); if (format_data->pktmbuf_pool == NULL) { snprintf(err, errlen, "Intel DPDK - Initialisation of mbuf " @@ -875,7 +897,7 @@ * receiving. Otherwise a larger size if writing packets. */ ret = rte_eth_tx_queue_setup(format_data->port, format_data->queue_id, - format_data->nb_tx_buf, SOCKET_ID_ANY, &tx_conf); + format_data->nb_tx_buf, rte_socket_id(), &tx_conf); if (ret < 0) { snprintf(err, errlen, "Intel DPDK - Cannot configure TX queue on port" " %"PRIu8" : %s", format_data->port, @@ -884,7 +906,7 @@ } /* Initialise the RX queue with some packets from memory */ ret = rte_eth_rx_queue_setup(format_data->port, format_data->queue_id, - format_data->nb_rx_buf, SOCKET_ID_ANY, + format_data->nb_rx_buf, rte_socket_id(), &rx_conf, format_data->pktmbuf_pool); if (ret < 0) { snprintf(err, errlen, "Intel DPDK - Cannot configure RX queue on port" @@ -1150,8 +1172,8 @@ #if GET_MAC_CRC_CHECKSUM /* Add back in the CRC sum */ - pkt->pkt.pkt_len += ETHER_CRC_LEN; - pkt->pkt.data_len += ETHER_CRC_LEN; + rte_pktmbuf_pkt_len(pkt) += ETHER_CRC_LEN; + rte_pktmbuf_data_len(pkt) += ETHER_CRC_LEN; hdr->flags |= INCLUDES_CHECKSUM; #endif @@ -1293,10 +1315,13 @@ while (1) { /* Poll for a single packet */ nb_rx = rte_eth_rx_burst(FORMAT(libtrace)->port, - FORMAT(libtrace)->queue_id, pkts_burst, 1); + FORMAT(libtrace)->queue_id, pkts_burst, 1); if (nb_rx > 0) { /* Got a packet - otherwise we keep spining */ return dpdk_ready_pkt(libtrace, packet, pkts_burst[0]); } + if (libtrace_halt) { + return 0; + } } /* We'll never get here - but if we did it would be bad */ diff -Nru libtrace3-3.0.21/lib/format_duck.c libtrace3-3.0.22/lib/format_duck.c --- libtrace3-3.0.21/lib/format_duck.c 2014-08-25 02:00:34.000000000 +0300 +++ libtrace3-3.0.22/lib/format_duck.c 2015-02-10 06:54:12.000000000 +0200 @@ -215,6 +215,9 @@ } else if (DATA(libtrace)->dag_version == TRACE_RT_DUCK_2_5) { duck_size = sizeof(duck2_5_t); packet->type = TRACE_RT_DUCK_2_5; + } else if (DATA(libtrace)->dag_version == TRACE_RT_DUCK_5_0) { + duck_size = sizeof(duck5_0_t); + packet->type = TRACE_RT_DUCK_5_0; } else { trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Unrecognised DUCK version %i", @@ -251,7 +254,8 @@ uint32_t duck_version; if (packet->type != TRACE_RT_DUCK_2_4 - && packet->type != TRACE_RT_DUCK_2_5) { + && packet->type != TRACE_RT_DUCK_2_5 && + packet->type != TRACE_RT_DUCK_5_0) { trace_set_err_out(libtrace, TRACE_ERR_BAD_PACKET, "Only DUCK packets may be written to a DUCK file"); return -1; @@ -286,6 +290,8 @@ return sizeof(duck2_4_t); case TRACE_RT_DUCK_2_5: return sizeof(duck2_5_t); + case TRACE_RT_DUCK_5_0: + return sizeof(duck5_0_t); default: trace_set_err(packet->trace,TRACE_ERR_BAD_PACKET, "Not a duck packet"); diff -Nru libtrace3-3.0.21/lib/format_erf.c libtrace3-3.0.22/lib/format_erf.c --- libtrace3-3.0.21/lib/format_erf.c 2014-08-25 02:00:34.000000000 +0300 +++ libtrace3-3.0.22/lib/format_erf.c 2015-02-10 06:54:12.000000000 +0200 @@ -479,8 +479,7 @@ if ((numbytes=wandio_read(libtrace->io, packet->buffer, (size_t)dag_record_size)) == -1) { - trace_set_err(libtrace,errno,"read(%s)", - libtrace->uridata); + trace_set_err(libtrace,errno,"reading ERF file"); return -1; } /* EOF */ @@ -488,6 +487,11 @@ return 0; } + if (numbytes < (int)dag_record_size) { + trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF header"); + return -1; + } + rlen = ntohs(((dag_record_t *)packet->buffer)->rlen); buffer2 = (char*)packet->buffer + dag_record_size; size = rlen - dag_record_size; @@ -521,6 +525,11 @@ /* Failed to read the full packet? must be EOF */ return -1; } + + if (numbytes < (int)size) { + trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF record"); + return -1; + } if (erf_prepare_packet(libtrace, packet, packet->buffer, TRACE_RT_DATA_ERF, flags)) diff -Nru libtrace3-3.0.21/lib/format_linux.c libtrace3-3.0.22/lib/format_linux.c --- libtrace3-3.0.21/lib/format_linux.c 2014-09-05 07:15:58.000000000 +0300 +++ libtrace3-3.0.22/lib/format_linux.c 2015-02-10 06:54:12.000000000 +0200 @@ -1077,7 +1077,11 @@ header = GET_CURRENT_BUFFER(libtrace); assert((((unsigned long) header) & (pagesize - 1)) == 0); - while (1) { + /* TP_STATUS_USER means that we can read the frame. + * When a slot does not have this flag set, the frame is not + * ready for consumption. + */ + while (!(header->tp_status & TP_STATUS_USER)) { pollset.fd = FORMAT(libtrace->format_data)->fd; pollset.events = POLLIN; pollset.revents = 0; @@ -1088,18 +1092,11 @@ trace_set_err(libtrace,errno,"poll()"); return -1; } else if (ret == 0) { - /* Poll timed out - check if we should exit */ - if (libtrace_halt) - return 0; - continue; - } - - /* TP_STATUS_USER means that we can use the frame. - * When a slot does not have this flag set, the frame is not - * ready for consumption. - */ - if (header->tp_status & TP_STATUS_USER) - break; + /* Poll timed out - check if we should exit */ + if (libtrace_halt) + return 0; + continue; + } } packet->buffer = header; diff -Nru libtrace3-3.0.21/lib/format_pcapfile.c libtrace3-3.0.22/lib/format_pcapfile.c --- libtrace3-3.0.21/lib/format_pcapfile.c 2014-08-25 02:00:34.000000000 +0300 +++ libtrace3-3.0.22/lib/format_pcapfile.c 2015-02-10 06:54:12.000000000 +0200 @@ -209,13 +209,17 @@ assert(sizeof(DATA(libtrace)->header) > 0); if (err<1) { - if (err == 0) { - trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, - "Reading pcap file header\n"); - } + trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, + "Error while reading pcap file header\n"); return -1; } - + + if (err != (int)sizeof(DATA(libtrace)->header)) { + trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, + "Incomplete pcap file header"); + return -1; + } + if (!header_is_magic(&(DATA(libtrace)->header))) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED, "Not a pcap tracefile (magic=%08x)\n",swapl(libtrace,DATA(libtrace)->header.magic_number)); @@ -358,7 +362,6 @@ err=wandio_read(libtrace->io, packet->buffer, sizeof(libtrace_pcapfile_pkt_hdr_t)); - if (err<0) { trace_set_err(libtrace,errno,"reading packet"); return -1; @@ -368,6 +371,11 @@ return 0; } + if (err < (int)sizeof(libtrace_pcapfile_pkt_hdr_t)) { + trace_set_err(libtrace, errno, "Incomplete pcap packet header"); + return -1; + } + bytes_to_read = swapl(libtrace,((libtrace_pcapfile_pkt_hdr_t*)packet->buffer)->caplen); if (bytes_to_read >= LIBTRACE_PACKET_BUFSIZE) { @@ -390,7 +398,6 @@ (size_t)swapl(libtrace,((libtrace_pcapfile_pkt_hdr_t*)packet->buffer)->caplen) ); - if (err<0) { trace_set_err(libtrace,errno,"reading packet"); return -1; @@ -399,6 +406,11 @@ return 0; } + if (err < (int)bytes_to_read) { + trace_set_err(libtrace, errno, "Incomplete pcap packet body"); + return -1; + } + if (pcapfile_prepare_packet(libtrace, packet, packet->buffer, packet->type, flags)) { return -1; diff -Nru libtrace3-3.0.21/lib/format_rt.c libtrace3-3.0.22/lib/format_rt.c --- libtrace3-3.0.21/lib/format_rt.c 2014-08-25 02:00:34.000000000 +0300 +++ libtrace3-3.0.22/lib/format_rt.c 2015-02-10 06:54:12.000000000 +0200 @@ -429,6 +429,7 @@ switch (packet->type) { case TRACE_RT_DUCK_2_4: case TRACE_RT_DUCK_2_5: + case TRACE_RT_DUCK_5_0: if (!RT_INFO->dummy_duck) { RT_INFO->dummy_duck = trace_create_dead("duck:dummy"); } diff -Nru libtrace3-3.0.21/lib/format_tsh.c libtrace3-3.0.22/lib/format_tsh.c --- libtrace3-3.0.21/lib/format_tsh.c 2014-08-25 02:00:34.000000000 +0300 +++ libtrace3-3.0.22/lib/format_tsh.c 2015-02-10 06:54:12.000000000 +0200 @@ -147,6 +147,11 @@ return 0; } + if (numbytes < (int)sizeof(tsh_pkt_header_t)) { + trace_set_err(libtrace, errno, "Incomplete TSH header"); + return -1; + } + buffer2 = (char*)buffer2 + numbytes; /* Read the IP header */ diff -Nru libtrace3-3.0.21/lib/libtrace.h libtrace3-3.0.22/lib/libtrace.h --- libtrace3-3.0.21/lib/libtrace.h 2014-09-09 00:55:39.000000000 +0300 +++ libtrace3-3.0.22/lib/libtrace.h 2015-02-10 06:57:10.000000000 +0200 @@ -106,11 +106,13 @@ /** API version as 2 byte hex digits, eg 0xXXYYZZ */ #define LIBTRACE_API_VERSION \ - ((3<<16)|(0<<8)|(21)) + ((3<<16)|(0<<8)|(22)) -/** Replaced with the current SVN revision number when 'make dist' is invoked - * to create a distributable tarball */ -#define LIBTRACE_SVN_REVISION 0 +/** This used to be replaced with the current SVN revision number when + * 'make dist' was invoked to create a distributable tarball. We don't use + * SVN anymore and there probably isn't any need to know the exact revision + * number either these days. */ +#define LIBTRACE_SVN_REVISION LIBTRACE_API_VERSION /** DAG driver version installed on the current system */ #define DAG_DRIVER_V "" @@ -380,6 +382,7 @@ TRACE_RT_SERVERSTART =16,/**< Reliable server has been restarted */ TRACE_RT_CLIENTDROP =17,/**< Reliable client was lost */ TRACE_RT_METADATA =18,/**< Packet contains server meta-data */ + TRACE_RT_DUCK_5_0 =19,/**< Dag 5.0 Duck */ /** Not actually used - all DATA types begin from this value */ TRACE_RT_DATA_SIMPLE = 1000, @@ -807,6 +810,35 @@ uint16_t length; /**< Total Length of the PPP packet */ } PACKED libtrace_pppoe_t; +/** Libtrace local definition of GRE (Generalised Routing Protocol) header + * RFC2890 + */ +typedef struct libtrace_gre_t +{ + uint16_t flags; /**< Flags and version */ + uint16_t ethertype; /**< Payload ethertype */ + uint16_t checksum; /**< Optional checksum */ + uint16_t reserved1; /**< Optional reserved */ + uint16_t key; /**< Optional key (or Tenant Network ID) */ + uint16_t seq; /**< Optional sequence number */ +} PACKED libtrace_gre_t; + +#define LIBTRACE_GRE_FLAG_CHECKSUM 0x8000 +#define LIBTRACE_GRE_FLAG_KEY 0x2000 +#define LIBTRACE_GRE_FLAG_SEQ 0x1000 +#define LIBTRACE_GRE_FLAG_VERMASK 0x0007 + +/** Libtrace local definition of VXLAN Header + * (draft-mahalingam-dutt-dcops-vxlan) + */ +typedef struct libtrace_vxlan_t +{ + uint8_t flags; /**< Flags */ + uint8_t reserved1[3]; /**< Reserved */ + uint8_t vni[3]; /**< VXLAN Network Identifier (VNI) */ + uint8_t reserved2; +} PACKED libtrace_vxlan_t; + /** 802.11 header */ typedef struct libtrace_80211_t { #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -2070,6 +2102,58 @@ DLLEXPORT void *trace_get_payload_from_icmp6(libtrace_icmp6_t *icmp, uint32_t *remaining); +/** Gets a pointer to the payload following a GRE header + * @param gre A pointer to the beginning of the GRE header. + * @param[in,out] remaining Updated with the number of captured bytes remaining. + * + * @return A pointer to the GRE payload, or NULL if the GRE header is truncated. + * + * When calling this function, remaining must contain the number of captured + * bytes remaining in the packet starting from the GRE header (including the + * GRE header itself). remaining will be updated to contain the number of + * bytes remaining after the GRE header has been skipped. + * + * If the GRE header is complete but there are zero bytes of payload after + * the header, a pointer to where the payload would be is returned and + * remaining will be set to 0. If the GRE header is incomplete, NULL will be + * returned and remaining will be set to 0. Therefore, it is important to check + * the value of remaining after calling this function. + */ +DLLEXPORT void *trace_get_payload_from_gre(libtrace_gre_t *gre, + uint32_t *remaining); + +/** Gets a pointer to the payload following a VXLAN header + * @param udp A pointer to the beginning of the UDP header. + * @param[in,out] remaining Updated with the number of captured bytes remaining. + * + * @return A pointer to the beginning of the VXLAN header, or NULL if the UDP + * header is truncated, or this is not a VXLAN packet. + * + */ +DLLEXPORT libtrace_vxlan_t *trace_get_vxlan_from_udp(libtrace_udp_t *udp, + uint32_t *remaining); + +/** Gets a pointer to the payload following a VXLAN header + * @param vxlan A pointer to the beginning of the VXLAN header. + * @param[in,out] remaining Updated with the number of captured bytes remaining. + * + * @return A pointer to the VXLAN payload, or NULL if the VXLAN header is + * truncated. + * + * When calling this function, remaining must contain the number of captured + * bytes remaining in the packet starting from the VXLAN header (including the + * VXLAN header itself). remaining will be updated to contain the number of + * bytes remaining after the VXLAN header has been skipped. + * + * If the VXLAN header is complete but there are zero bytes of payload after + * the header, a pointer to where the payload would be is returned and + * remaining will be set to 0. If the VXLAN header is incomplete, NULL will be + * returned and remaining will be set to 0. Therefore, it is important to check + * the value of remaining after calling this function. + */ +DLLEXPORT void *trace_get_payload_from_vxlan(libtrace_vxlan_t *vxlan, + uint32_t *remaining); + /** Get a pointer to the TCP header (if present) * @param packet The packet to get the TCP header from * diff -Nru libtrace3-3.0.21/lib/libtrace.h.in libtrace3-3.0.22/lib/libtrace.h.in --- libtrace3-3.0.21/lib/libtrace.h.in 2014-09-09 00:55:41.000000000 +0300 +++ libtrace3-3.0.22/lib/libtrace.h.in 2015-02-10 06:54:12.000000000 +0200 @@ -108,9 +108,11 @@ #define LIBTRACE_API_VERSION \ ((@LIBTRACE_MAJOR@<<16)|(@LIBTRACE_MID@<<8)|(@LIBTRACE_MINOR@)) -/** Replaced with the current SVN revision number when 'make dist' is invoked - * to create a distributable tarball */ -#define LIBTRACE_SVN_REVISION xported +/** This used to be replaced with the current SVN revision number when + * 'make dist' was invoked to create a distributable tarball. We don't use + * SVN anymore and there probably isn't any need to know the exact revision + * number either these days. */ +#define LIBTRACE_SVN_REVISION LIBTRACE_API_VERSION /** DAG driver version installed on the current system */ #define DAG_DRIVER_V "@DAG_VERSION_NUM@" @@ -380,6 +382,7 @@ TRACE_RT_SERVERSTART =16,/**< Reliable server has been restarted */ TRACE_RT_CLIENTDROP =17,/**< Reliable client was lost */ TRACE_RT_METADATA =18,/**< Packet contains server meta-data */ + TRACE_RT_DUCK_5_0 =19,/**< Dag 5.0 Duck */ /** Not actually used - all DATA types begin from this value */ TRACE_RT_DATA_SIMPLE = 1000, @@ -807,6 +810,35 @@ uint16_t length; /**< Total Length of the PPP packet */ } PACKED libtrace_pppoe_t; +/** Libtrace local definition of GRE (Generalised Routing Protocol) header + * RFC2890 + */ +typedef struct libtrace_gre_t +{ + uint16_t flags; /**< Flags and version */ + uint16_t ethertype; /**< Payload ethertype */ + uint16_t checksum; /**< Optional checksum */ + uint16_t reserved1; /**< Optional reserved */ + uint16_t key; /**< Optional key (or Tenant Network ID) */ + uint16_t seq; /**< Optional sequence number */ +} PACKED libtrace_gre_t; + +#define LIBTRACE_GRE_FLAG_CHECKSUM 0x8000 +#define LIBTRACE_GRE_FLAG_KEY 0x2000 +#define LIBTRACE_GRE_FLAG_SEQ 0x1000 +#define LIBTRACE_GRE_FLAG_VERMASK 0x0007 + +/** Libtrace local definition of VXLAN Header + * (draft-mahalingam-dutt-dcops-vxlan) + */ +typedef struct libtrace_vxlan_t +{ + uint8_t flags; /**< Flags */ + uint8_t reserved1[3]; /**< Reserved */ + uint8_t vni[3]; /**< VXLAN Network Identifier (VNI) */ + uint8_t reserved2; +} PACKED libtrace_vxlan_t; + /** 802.11 header */ typedef struct libtrace_80211_t { #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -2070,6 +2102,58 @@ DLLEXPORT void *trace_get_payload_from_icmp6(libtrace_icmp6_t *icmp, uint32_t *remaining); +/** Gets a pointer to the payload following a GRE header + * @param gre A pointer to the beginning of the GRE header. + * @param[in,out] remaining Updated with the number of captured bytes remaining. + * + * @return A pointer to the GRE payload, or NULL if the GRE header is truncated. + * + * When calling this function, remaining must contain the number of captured + * bytes remaining in the packet starting from the GRE header (including the + * GRE header itself). remaining will be updated to contain the number of + * bytes remaining after the GRE header has been skipped. + * + * If the GRE header is complete but there are zero bytes of payload after + * the header, a pointer to where the payload would be is returned and + * remaining will be set to 0. If the GRE header is incomplete, NULL will be + * returned and remaining will be set to 0. Therefore, it is important to check + * the value of remaining after calling this function. + */ +DLLEXPORT void *trace_get_payload_from_gre(libtrace_gre_t *gre, + uint32_t *remaining); + +/** Gets a pointer to the payload following a VXLAN header + * @param udp A pointer to the beginning of the UDP header. + * @param[in,out] remaining Updated with the number of captured bytes remaining. + * + * @return A pointer to the beginning of the VXLAN header, or NULL if the UDP + * header is truncated, or this is not a VXLAN packet. + * + */ +DLLEXPORT libtrace_vxlan_t *trace_get_vxlan_from_udp(libtrace_udp_t *udp, + uint32_t *remaining); + +/** Gets a pointer to the payload following a VXLAN header + * @param vxlan A pointer to the beginning of the VXLAN header. + * @param[in,out] remaining Updated with the number of captured bytes remaining. + * + * @return A pointer to the VXLAN payload, or NULL if the VXLAN header is + * truncated. + * + * When calling this function, remaining must contain the number of captured + * bytes remaining in the packet starting from the VXLAN header (including the + * VXLAN header itself). remaining will be updated to contain the number of + * bytes remaining after the VXLAN header has been skipped. + * + * If the VXLAN header is complete but there are zero bytes of payload after + * the header, a pointer to where the payload would be is returned and + * remaining will be set to 0. If the VXLAN header is incomplete, NULL will be + * returned and remaining will be set to 0. Therefore, it is important to check + * the value of remaining after calling this function. + */ +DLLEXPORT void *trace_get_payload_from_vxlan(libtrace_vxlan_t *vxlan, + uint32_t *remaining); + /** Get a pointer to the TCP header (if present) * @param packet The packet to get the TCP header from * diff -Nru libtrace3-3.0.21/lib/libtrace_int.h libtrace3-3.0.22/lib/libtrace_int.h --- libtrace3-3.0.21/lib/libtrace_int.h 2014-07-07 02:25:20.000000000 +0300 +++ libtrace3-3.0.22/lib/libtrace_int.h 2015-02-10 06:54:12.000000000 +0200 @@ -745,7 +745,7 @@ /** Specifies whether any blocking packet readers should cease reading * immediately */ -extern int libtrace_halt; +extern volatile int libtrace_halt; /** Registers a new capture format module. * diff -Nru libtrace3-3.0.21/lib/Makefile.am libtrace3-3.0.22/lib/Makefile.am --- libtrace3-3.0.21/lib/Makefile.am 2014-09-05 07:53:18.000000000 +0300 +++ libtrace3-3.0.22/lib/Makefile.am 2015-02-10 06:54:12.000000000 +0200 @@ -20,7 +20,7 @@ EXTRA_DIST=format_dag24.c format_dag25.c dpdk_libtrace.mk if HAVE_LLVM -BPFJITSOURCE=bpf-jit/bpf-jit.cc +BPFJITSOURCE=bpf-jit/bpf-jit.cc else BPFJITSOURCE= endif @@ -53,6 +53,7 @@ checksum.c checksum.h \ protocols_pktmeta.c protocols_l2.c protocols_l3.c \ protocols_transport.c protocols.h protocols_ospf.c \ + protocols_application.c \ $(DAGSOURCE) format_erf.h \ $(BPFJITSOURCE) \ libtrace_arphrd.h diff -Nru libtrace3-3.0.21/lib/Makefile.in libtrace3-3.0.22/lib/Makefile.in --- libtrace3-3.0.21/lib/Makefile.in 2014-09-09 00:55:27.000000000 +0300 +++ libtrace3-3.0.22/lib/Makefile.in 2015-02-10 06:56:57.000000000 +0200 @@ -108,8 +108,8 @@ link_wireless.c byteswap.c checksum.c checksum.h \ protocols_pktmeta.c protocols_l2.c protocols_l3.c \ protocols_transport.c protocols.h protocols_ospf.c \ - format_dag25.c format_dag24.c format_erf.h bpf-jit/bpf-jit.cc \ - libtrace_arphrd.h + protocols_application.c format_dag25.c format_dag24.c \ + format_erf.h bpf-jit/bpf-jit.cc libtrace_arphrd.h @HAVE_DPDK_TRUE@am__objects_1 = format_dpdk.lo am__objects_2 = format_linux.lo $(am__objects_1) am__objects_3 = format_bpf.lo @@ -123,8 +123,8 @@ $(am__objects_2) $(am__objects_3) format_atmhdr.lo \ linktypes.lo link_wireless.lo byteswap.lo checksum.lo \ protocols_pktmeta.lo protocols_l2.lo protocols_l3.lo \ - protocols_transport.lo protocols_ospf.lo $(am__objects_4) \ - $(am__objects_5) + protocols_transport.lo protocols_ospf.lo \ + protocols_application.lo $(am__objects_4) $(am__objects_5) @DAG2_4_TRUE@nodist_libtrace_la_OBJECTS = dagopts.lo dagapi.lo libtrace_la_OBJECTS = $(am_libtrace_la_OBJECTS) \ $(nodist_libtrace_la_OBJECTS) @@ -353,7 +353,7 @@ EXTRA_DIST = format_dag24.c format_dag25.c dpdk_libtrace.mk \ $(am__append_2) @HAVE_LLVM_FALSE@BPFJITSOURCE = -@HAVE_LLVM_TRUE@BPFJITSOURCE = bpf-jit/bpf-jit.cc +@HAVE_LLVM_TRUE@BPFJITSOURCE = bpf-jit/bpf-jit.cc libtrace_la_SOURCES = trace.c common.h \ format_erf.c format_pcap.c format_legacy.c \ format_rt.c format_helper.c format_helper.h format_pcapfile.c \ @@ -364,6 +364,7 @@ checksum.c checksum.h \ protocols_pktmeta.c protocols_l2.c protocols_l3.c \ protocols_transport.c protocols.h protocols_ospf.c \ + protocols_application.c \ $(DAGSOURCE) format_erf.h \ $(BPFJITSOURCE) \ libtrace_arphrd.h @@ -485,6 +486,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/format_tsh.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/link_wireless.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linktypes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocols_application.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocols_l2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocols_l3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocols_ospf.Plo@am__quote@ diff -Nru libtrace3-3.0.21/lib/protocols_application.c libtrace3-3.0.22/lib/protocols_application.c --- libtrace3-3.0.21/lib/protocols_application.c 1970-01-01 02:00:00.000000000 +0200 +++ libtrace3-3.0.22/lib/protocols_application.c 2015-02-10 06:54:12.000000000 +0200 @@ -0,0 +1,56 @@ +/* + * This file is part of libtrace + * + * Copyright (c) 2014 The University of Waikato, Hamilton, New Zealand. + * + * Authors: Perry Lorier + * + * All rights reserved. + * + * This code has been developed by the University of Waikato WAND + * research group. For further information please see http://www.wand.net.nz/ + * + * libtrace is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libtrace is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libtrace; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <stdlib.h> +#include "libtrace.h" + +void *trace_get_payload_from_vxlan(libtrace_vxlan_t *vxlan, uint32_t *remaining) +{ + if (remaining) { + if (*remaining < sizeof(*vxlan)) { + *remaining = 0; + return NULL; + } + + *remaining -= sizeof(*vxlan); + } + + return (void*)((char *)vxlan + sizeof(*vxlan)); +} + + +libtrace_vxlan_t *trace_get_vxlan_from_udp(libtrace_udp_t *udp, + uint32_t *remaining) +{ + if (udp->dest != htons(4789)) { /* UDP port number for vxlan */ + return NULL; /* Not a vxlan packet. */ + } + + return trace_get_payload_from_udp(udp, remaining); +} + + + diff -Nru libtrace3-3.0.21/lib/protocols_transport.c libtrace3-3.0.22/lib/protocols_transport.c --- libtrace3-3.0.21/lib/protocols_transport.c 2014-07-07 02:25:20.000000000 +0300 +++ libtrace3-3.0.22/lib/protocols_transport.c 2015-02-10 06:54:12.000000000 +0200 @@ -552,3 +552,34 @@ return csum_ptr; } + +DLLEXPORT void *trace_get_payload_from_gre(libtrace_gre_t *gre, + uint32_t *remaining) +{ + uint32_t size = 4; /* GRE is 4 bytes long by default */ + if (remaining && *remaining < size) { + *remaining = 0; + return NULL; + } + + if ((ntohs(gre->flags) & LIBTRACE_GRE_FLAG_CHECKSUM) != 0) { + size += 4; /* An extra 4 bytes. */ + } + + if ((ntohs(gre->flags) & LIBTRACE_GRE_FLAG_KEY) != 0) { + size += 4; /* An extra 4 bytes. */ + } + + if ((ntohs(gre->flags) & LIBTRACE_GRE_FLAG_SEQ) != 0) { + size += 4; /* An extra 4 bytes. */ + } + + if (remaining) { + if (*remaining < size) { + *remaining = 0; + return NULL; + } + *remaining -= size; + } + return (char*)gre+size; +} diff -Nru libtrace3-3.0.21/lib/rt_protocol.h libtrace3-3.0.22/lib/rt_protocol.h --- libtrace3-3.0.21/lib/rt_protocol.h 2014-07-07 02:22:32.000000000 +0300 +++ libtrace3-3.0.22/lib/rt_protocol.h 2015-02-10 06:54:12.000000000 +0200 @@ -248,6 +248,29 @@ uint64_t Last_TSC; } PACKED duck2_5_t; +typedef struct duck5_0 { + int64_t Phase_Correction; + uint64_t Last_Ticks; + uint64_t Last_TSC; + /* XXX Stat_Start and Stat_End are time_t in dagioctl.h, which means + * they could in theory be 32 or 64 bit depending on the architecture + * when capturing. I'm going to assume 5.0 era DAG captures are taking + * place on a 64 bit arch, rather than have to deal with the varying + * sizes (especially given nobody really uses DUCK these days). + */ + uint64_t Stat_Start, Stat_End; + uint32_t Crystal_Freq; + uint32_t Synth_Freq; + uint32_t Resyncs; + uint32_t Bad_Pulses; + uint32_t Worst_Freq_Err, Worst_Phase_Err; + uint32_t Health_Thresh; + uint32_t Pulses, Single_Pulses_Missing, Longest_Pulse_Missing; + uint32_t Health, Sickness; + int32_t Freq_Err, Phase_Err; + uint32_t Set_Duck_Field; +} PACKED duck5_0_t; + /* typedef struct rt_duck_2_4 { duck2_4_t duck; diff -Nru libtrace3-3.0.21/lib/trace.c libtrace3-3.0.22/lib/trace.c --- libtrace3-3.0.21/lib/trace.c 2014-08-25 02:59:50.000000000 +0300 +++ libtrace3-3.0.22/lib/trace.c 2015-02-10 06:54:12.000000000 +0200 @@ -104,7 +104,7 @@ static struct libtrace_format_t *formats_list = NULL; -int libtrace_halt = 0; +volatile int libtrace_halt = 0; /* strncpy is not assured to copy the final \0, so we * will use our own one that does diff -Nru libtrace3-3.0.21/libwandio/ior-zlib.c libtrace3-3.0.22/libwandio/ior-zlib.c --- libtrace3-3.0.21/libwandio/ior-zlib.c 2014-07-07 02:22:32.000000000 +0300 +++ libtrace3-3.0.22/libwandio/ior-zlib.c 2015-02-10 06:54:12.000000000 +0200 @@ -55,6 +55,7 @@ io_t *parent; int outoffset; enum err_t err; + size_t sincelastend; }; @@ -82,6 +83,7 @@ DATA(io)->strm.zfree = Z_NULL; DATA(io)->strm.opaque = NULL; DATA(io)->err = ERR_OK; + DATA(io)->sincelastend = 1; inflateInit2(&DATA(io)->strm, 15 | 32); @@ -107,9 +109,22 @@ (char*)DATA(io)->inbuff, sizeof(DATA(io)->inbuff)); if (bytes_read == 0) { - /* EOF */ + /* If we get EOF immediately after a + * Z_STREAM_END, then we assume we've reached + * the end of the file. If there was data + * between the Z_STREAM_END and the EOF, the + * file has more likely been truncated. + */ + if (DATA(io)->sincelastend > 0) { + fprintf(stderr, "Unexpected EOF while reading compressed file -- file is probably incomplete\n"); + errno = EIO; + DATA(io)->err = ERR_ERROR; + return -1; + } + + /* EOF */ if (DATA(io)->strm.avail_out == (uint32_t)len) { - DATA(io)->err = ERR_EOF; + DATA(io)->err = ERR_EOF; return 0; } /* Return how much data we've managed to read so far. */ @@ -127,6 +142,7 @@ } DATA(io)->strm.next_in = DATA(io)->inbuff; DATA(io)->strm.avail_in = bytes_read; + DATA(io)->sincelastend += bytes_read; } /* Decompress some data into the output buffer */ int err=inflate(&DATA(io)->strm, 0); @@ -143,6 +159,7 @@ inflateEnd(&DATA(io)->strm); inflateInit2(&DATA(io)->strm, 15 | 32); DATA(io)->err = ERR_OK; + DATA(io)->sincelastend = 0; break; default: errno=EIO; diff -Nru libtrace3-3.0.21/Makefile.am libtrace3-3.0.22/Makefile.am --- libtrace3-3.0.21/Makefile.am 2014-07-07 02:22:32.000000000 +0300 +++ libtrace3-3.0.22/Makefile.am 2015-02-10 06:54:12.000000000 +0200 @@ -21,12 +21,6 @@ lib/Makefile.in replace/libreplace.la replace/Makefile.in $(RM) -rf autom4te.cache/ -dist-hook: - if which svnversion > /dev/null; then \ - r=`svnversion -nc . | sed -e 's/^[^:]*://;s/[A-Za-z]//'` ;\ - sed -i "s/SVN_REVISION.*/SVN_REVISION $$r/" $(distdir)/lib/libtrace.h.in; \ - fi - if HAS_DOXYGEN docs/doxygen/man/man3/*.3: docs else diff -Nru libtrace3-3.0.21/Makefile.in libtrace3-3.0.22/Makefile.in --- libtrace3-3.0.21/Makefile.in 2014-09-09 00:55:28.000000000 +0300 +++ libtrace3-3.0.22/Makefile.in 2015-02-10 06:56:57.000000000 +0200 @@ -642,9 +642,6 @@ || exit 1; \ fi; \ done - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" distdir="$(distdir)" \ - dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ @@ -891,14 +888,14 @@ .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-generic \ clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \ - dist-gzip dist-hook dist-lzip dist-lzma dist-shar dist-tarZ \ - dist-xz dist-zip distcheck distclean distclean-generic \ - distclean-hdr distclean-libtool distclean-tags distcleancheck \ - distdir distuninstallcheck dvi dvi-am html html-am info \ - info-am install install-am install-data install-data-am \ - install-dvi install-dvi-am install-exec install-exec-am \ - install-html install-html-am install-info install-info-am \ - install-man install-man3 install-pdf install-pdf-am install-ps \ + dist-gzip dist-lzip dist-lzma dist-shar dist-tarZ dist-xz \ + dist-zip distcheck distclean distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man3 install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ @@ -915,12 +912,6 @@ lib/Makefile.in replace/libreplace.la replace/Makefile.in $(RM) -rf autom4te.cache/ -dist-hook: - if which svnversion > /dev/null; then \ - r=`svnversion -nc . | sed -e 's/^[^:]*://;s/[A-Za-z]//'` ;\ - sed -i "s/SVN_REVISION.*/SVN_REVISION $$r/" $(distdir)/lib/libtrace.h.in; \ - fi - @HAS_DOXYGEN_TRUE@docs/doxygen/man/man3/*.3: docs @HAS_DOXYGEN_FALSE@docs/doxygen/man/man3/*.3: diff -Nru libtrace3-3.0.21/README libtrace3-3.0.22/README --- libtrace3-3.0.21/README 2014-09-05 02:25:48.000000000 +0300 +++ libtrace3-3.0.22/README 2015-02-10 06:56:03.000000000 +0200 @@ -1,7 +1,7 @@ -libtrace 3.0.21 +libtrace 3.0.22 --------------------------------------------------------------------------- -Copyright (c) 2007-2014 The University of Waikato, Hamilton, New Zealand. +Copyright (c) 2007-2015 The University of Waikato, Hamilton, New Zealand. All rights reserved. This code has been developed by the University of Waikato WAND diff -Nru libtrace3-3.0.21/tools/tracestats/tracestats.c libtrace3-3.0.22/tools/tracestats/tracestats.c --- libtrace3-3.0.21/tools/tracestats/tracestats.c 2014-07-07 02:22:32.000000000 +0300 +++ libtrace3-3.0.22/tools/tracestats/tracestats.c 2015-02-10 06:54:12.000000000 +0200 @@ -156,7 +156,7 @@ totbytes+=bytes; if (trace_is_err(trace)) - trace_perror(trace,"%s",uri); + trace_perror(trace,"Processing trace"); trace_destroy(trace); } diff -Nru libtrace3-3.0.21/tools/tracestats/tracesummary libtrace3-3.0.22/tools/tracestats/tracesummary --- libtrace3-3.0.21/tools/tracestats/tracesummary 2014-07-07 02:22:32.000000000 +0300 +++ libtrace3-3.0.22/tools/tracestats/tracesummary 2015-02-10 06:54:12.000000000 +0200 @@ -17,4 +17,4 @@ --filter 'tcp and port imap or imaps' \ --filter 'port domain' \ --filter 'icmp[icmptype]=icmp-echoreply' \ - $@ + "$@"