From 6364f4534ec93c230070c78513f7ad158e85d764 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 10 May 2022 14:01:44 +0200 Subject: tcpdump01: New test Update #4649. --- libbsd.py | 1 + testsuite/tcpdump01/test_main.c | 292 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 293 insertions(+) create mode 100644 testsuite/tcpdump01/test_main.c diff --git a/libbsd.py b/libbsd.py index cab130cf..83450b59 100644 --- a/libbsd.py +++ b/libbsd.py @@ -5230,6 +5230,7 @@ class tests(builder.Module): self.addTest(mm.generator['test']('ipsec01', ['test_main'])) self.addTest(mm.generator['test']('openssl01', ['test_main'])) self.addTest(mm.generator['test']('openssl02', ['test_main'])) + self.addTest(mm.generator['test']('tcpdump01', ['test_main'])) def load(mm): diff --git a/testsuite/tcpdump01/test_main.c b/testsuite/tcpdump01/test_main.c new file mode 100644 index 00000000..0f31cdde --- /dev/null +++ b/testsuite/tcpdump01/test_main.c @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @brief Tests the tcpdump command. + */ + +/* + * Copyright (C) 2022 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define TEST_NAME "LIBBSD TCPDUMP 1" + +typedef struct { + rtems_id main_id; + int sp[2]; +} test_context; + +static test_context test_instance; + +static void +epoch_cleanup(void) +{ + rtems_status_code sc; + + sc = rtems_task_wake_after(CK_EPOCH_LENGTH); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void +init_addr(struct sockaddr_in *addr) +{ + int ok; + + memset(addr, 0, sizeof(*addr)); + addr->sin_family = AF_INET; + addr->sin_port = htons(1234); + ok = inet_aton("127.0.0.1", &addr->sin_addr); + assert(ok != 0); +} + +static rtems_id +start_task(rtems_task_entry entry, void *arg) +{ + rtems_task_priority prio; + rtems_id id; + rtems_status_code sc; + + sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &prio); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create(rtems_build_name('T', 'E', 'S', 'T' ), prio - 1, + 32 * 1024, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &id); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(id, entry, (rtems_task_argument)arg); + assert(sc == RTEMS_SUCCESSFUL); + + return id; +} + +static void +test_tcpdump_help(void) +{ + char *argv[] = { + "tcpdump", + "-h", + NULL + }; + rtems_resource_snapshot snapshot; + int exit_code; + + rtems_resource_snapshot_take(&snapshot); + + exit_code = rtems_bsd_command_tcpdump(RTEMS_BSD_ARGC(argv), argv); + assert(exit_code == 0); + + assert(rtems_resource_snapshot_check(&snapshot)); +} + +static const char raw_packets_file[] = "packets.bin"; + +static void +run_tcpdump_write_raw_packets(rtems_task_argument arg) +{ + test_context *ctx; + FILE *file; + FILE *saved_stdin; + FILE *saved_stdout; + FILE *saved_stderr; + int rv; + char *argv[] = { + "tcpdump", + "-n", + "-i", + "lo0", + "-w", + RTEMS_DECONST(char *, raw_packets_file), + NULL + }; + int exit_code; + rtems_status_code sc; + + ctx = (test_context *)arg; + + saved_stdin = stdin; + saved_stdout = stdout; + saved_stderr = stderr; + + file = fdopen(ctx->sp[1], "r+"); + assert(file != NULL); + + stdin = file; + stdout = file; + stderr = file; + + exit_code = rtems_bsd_command_tcpdump(RTEMS_BSD_ARGC(argv), argv); + assert(exit_code == 0); + + stdin = saved_stdin; + stdout = saved_stdout; + stderr = saved_stderr; + + rv = fclose(file); + assert(rv == 0); + + sc = rtems_event_transient_send(ctx->main_id); + assert(sc == RTEMS_SUCCESSFUL); + + rtems_task_exit(); +} + +static void +test_tcpdump_write_raw_packets(test_context *ctx) +{ + char *argv[] = { + "tcpdump", + "-n", + "-r", + RTEMS_DECONST(char *, raw_packets_file), + NULL + }; + rtems_resource_snapshot snapshot; + int in; + int out; + int rv; + char c; + ssize_t n; + struct sockaddr_in addr; + socklen_t addr_len; + rtems_status_code sc; + int exit_code; + + rtems_resource_snapshot_take(&snapshot); + + rv = socketpair(PF_UNIX, SOCK_STREAM, 0, ctx->sp); + assert(rv == 0); + + start_task(run_tcpdump_write_raw_packets, ctx); + + init_addr(&addr); + + in = socket(PF_INET, SOCK_DGRAM, 0); + assert(out >= 0); + + rv = bind(in, (const struct sockaddr *) &addr, sizeof(addr)); + assert(rv == 0); + + out = socket(PF_INET, SOCK_DGRAM, 0); + assert(out >= 0); + + c = 'x'; + n = sendto(out, &c, sizeof(c), 0, + (const struct sockaddr *) &addr, sizeof(addr)); + assert(n == 1); + + c = 'y'; + addr_len = sizeof(addr); + n = recvfrom(in, &c, sizeof(c), 0, + (struct sockaddr *) &addr, &addr_len); + assert(n == 1); + assert(c == 'x'); + + /* The tcpdump pcap read timeout is 1000ms */ + sc = rtems_task_wake_after(rtems_clock_get_ticks_per_second()); + assert(sc == RTEMS_SUCCESSFUL); + + c = 'q'; + n = write(ctx->sp[0], &c, sizeof(c)); + assert(n == 1); + + rv = close(out); + assert(rv == 0); + + rv = close(in); + assert(rv == 0); + + sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); + assert(sc == RTEMS_SUCCESSFUL); + + rv = close(ctx->sp[0]); + assert(rv == 0); + + exit_code = rtems_bsd_command_tcpdump(RTEMS_BSD_ARGC(argv), argv); + assert(exit_code == 0); + + rv = unlink(raw_packets_file); + assert(rv == 0); + + epoch_cleanup(); + assert(rtems_resource_snapshot_check(&snapshot)); +} + +static void +test_main(void) +{ + test_context *ctx; + FILE *file; + int rv; + + ctx = &test_instance; + ctx->main_id = rtems_task_self(); + + /* Fill dynamic file pool in Newlib */ + file = fopen(CONSOLE_DEVICE_NAME, "r+"); + assert(file != NULL); + rv = fclose(file); + assert(rv == 0); + + /* + * Stop interferences of uma_timeout() which may need some dynamic + * memory. + */ + rtems_uma_drain_timeout(); + + rtems_bsd_ifconfig_lo0(); + epoch_cleanup(); + + test_tcpdump_help(); + test_tcpdump_write_raw_packets(ctx); + + exit(0); +} + +#include -- cgit v1.2.3