From 74ebfa714450953ba5c242751bc62e1c6c8f7344 Mon Sep 17 00:00:00 2001 From: Michal Ruprich Date: Oct 11 2019 11:46:27 +0000 Subject: Merge #1 `Adds tests according to the CI` --- diff --git a/tests/sanity-tests/Makefile b/tests/sanity-tests/Makefile new file mode 100644 index 0000000..23291eb --- /dev/null +++ b/tests/sanity-tests/Makefile @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Makefile of /CoreOS/libpcap +# Description: Sanity +# Author: Susant Sahani +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +export TEST=/CoreOS/libpcap +export TESTVERSION=1.0 + +INCLUDES = +OBJS = test-libpcap.c +CFLAG = -Wall -g3 +CC = gcc +LIBS = -lnet -lcmocka -lpcap -lpthread + +test-libpcap:${OBJ} + ${CC} ${CFLAGS} ${INCLUDES} -o $@ ${OBJS} ${LIBS} + +run: test-libpcap + ./runtest.sh +clean: + -rm -f *~ test-libpcap + +.c.o: + ${CC} ${CFLAGS} ${INCLUDES} -c $< + +CC = gcc + +include /usr/share/rhts/lib/rhts-make.include +$(METADATA): Makefile + @echo "Owner: Susant Sahani" > $(METADATA) + @echo "Name: $(TEST)" >> $(METADATA) + @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) + @echo "Path: $(TEST_DIR)" >> $(METADATA) + @echo "Description: Test libpcap sanity" >> $(METADATA) + @echo "Type: Sanity" >> $(METADATA) + @echo "TestTime: 5m" >> $(METADATA) + @echo "RunFor: libpcap" >> $(METADATA) + @echo "Requires: libpcap libpcap-devel" >> $(METADATA) + @echo "Priority: Normal" >> $(METADATA) + @echo "License: GPLv2" >> $(METADATA) + @echo "Confidential: no" >> $(METADATA) + @echo "Destructive: no" >> $(METADATA) + @echo "Releases: -Fedora 29" >> $(METADATA) + rhts-lint $(METADATA) diff --git a/tests/sanity-tests/runtest.sh b/tests/sanity-tests/runtest.sh new file mode 100755 index 0000000..eb1cbc3 --- /dev/null +++ b/tests/sanity-tests/runtest.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# SPDX-License-Identifier: LGPL-2.1+ +# ~~~ +# runtest.sh of libpcap +# Description: Tests for libpcap +# +# Author: Susant Sahani +# Copyright (c) 2018 Red Hat, Inc. +# ~~~ + +# Include Beaker environment +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +PACKAGE="libpcap" + +rlJournalStart + rlPhaseStartSetup + rlAssertRpm $PACKAGE + + rlLog "Setting up veth Interface " + rlRun "ip link add veth-test type veth peer name veth-peer" + rlRun "ip addr add 192.168.50.5 dev veth-test" + rlRun "ip addr add 192.168.50.6 dev veth-peer" + rlRun "ip link set dev veth-test up" + rlRun "ip link set dev veth-peer up" + + rlRun "cp test-libpcap /usr/bin/" + rlRun "systemctl daemon-reload" + rlPhaseEnd + + rlPhaseStartTest + rlLog "Starting libpcap tests ..." + rlRun "/usr/bin/test-libpcap" + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "rm /usr/bin/test-libpcap" + rlRun "ip link del veth-test" + rlLog "libpcap tests done" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd + +rlGetTestState diff --git a/tests/sanity-tests/test-libpcap.c b/tests/sanity-tests/test-libpcap.c new file mode 100644 index 0000000..f48d8be --- /dev/null +++ b/tests/sanity-tests/test-libpcap.c @@ -0,0 +1,229 @@ +/* +# SPDX-License-Identifier: LGPL-2.1+ +# ~~~ +# Description: libpcap tests +# +# Author: Susant Sahani +# Copyright (c) 2018 Red Hat, Inc. +# ~~~ +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCAP_FILE "/var/run/libpcap-test.pcap" + +pcap_t *handle; + +struct UDP_hdr { + u_short uh_sport; /* source port */ + u_short uh_dport; /* destination port */ + u_short uh_ulen; /* datagram length */ + u_short uh_sum; /* datagram checksum */ +}; + +static void assert_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) { + unsigned int ipl; + uint32_t src, dst; + struct ip *ip; + struct ether_header *eth_header; + + eth_header = (struct ether_header *) packet; + if (ntohs(eth_header->ether_type) != ETHERTYPE_IP) + return; + + packet += sizeof(struct ether_header); + ip = (struct ip *) packet; + ipl = ip->ip_hl * 4; + + src = inet_addr("192.168.50.6"); + dst = inet_addr("192.168.50.5"); + + assert_memory_equal(&dst, &ip->ip_dst, sizeof(uint32_t)); + assert_memory_equal(&src, &ip->ip_src, sizeof(uint32_t)); + + if (ip->ip_p == IPPROTO_UDP) { + struct UDP_hdr *udp; + + packet += ipl; + + udp = (struct UDP_hdr *) packet; + + printf("UDP src_port=%d dst_port=%d\n", ntohs(udp->uh_sport), ntohs(udp->uh_dport)); + + assert_int_equal(2425, ntohs(udp->uh_sport)); + assert_int_equal(2426, ntohs(udp->uh_dport)); + } else if (ip->ip_p == IPPROTO_TCP) { + struct tcphdr *tcp; + packet += ipl; + + tcp = (struct tcphdr *) packet; + + printf("TCP src_port=%d dst_port=%d\n", ntohs(tcp->th_sport), ntohs(tcp->th_dport)); + + assert_int_equal(2425, ntohs(tcp->th_sport)); + assert_int_equal(2426, ntohs(tcp->th_dport)); + } +} + +void *capture_packet_live(void *ptr) { + char dev[] = "veth-test"; + char error_buffer[PCAP_ERRBUF_SIZE]; + struct bpf_program filter; + bpf_u_int32 subnet_mask, ip; + int total_packet_count; + int r; + + r = pcap_lookupnet(dev, &ip, &subnet_mask, error_buffer); + assert_true(r >=0); + + handle = pcap_open_live(dev, BUFSIZ, 1, 1000, error_buffer); + assert_non_null(handle); + + r = pcap_compile(handle, &filter, ptr, 0, ip); + assert_true(r >= 0); + + r = pcap_setfilter(handle, &filter); + assert_true(r >= 0); + + pcap_loop(handle, total_packet_count, assert_packet, NULL); + + return 0; +} + +void terminate_thread(int signum) { + + pcap_breakloop(handle); + pcap_close(handle); + + handle = NULL; + pthread_exit(NULL); +} + +static void test_udp_packet_ipv4(void **state) { + char dst[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + char src[6] = {0x12,0x34,0x56,0x78,0x9a,0xab}; + char err_buf[LIBNET_ERRBUF_SIZE] = {}; + char buf[1024] = {}; + libnet_t* l; + int r, i; + uint32_t len; + pthread_t pcap_thread; + struct itimerval tval; + + timerclear(& tval.it_interval); /* zero interval means no reset of timer */ + timerclear(& tval.it_value); + tval.it_value.tv_sec = 10; /* 10 second timeout */ + + (void) signal(SIGALRM, terminate_thread); + (void) setitimer(ITIMER_REAL, & tval, NULL); + + r = pthread_create(&pcap_thread, NULL, capture_packet_live, "udp port 2425"); + assert_true(r >=0); + + l = libnet_init(LIBNET_LINK_ADV, "veth-peer", err_buf); + assert_non_null(l); + len = sprintf(buf, "1:1:1111111111111:32:hello world%d", 1); + + for (i = 0; i < 5; i++) { + + r = libnet_build_udp(2425, 2426, len + 8, 0, buf, len, l, 0); + assert_true(r >= 0); + + r = libnet_build_ipv4(20 + 8 + len, 0, 0, 0, 128, 17, 0, inet_addr("192.168.50.6"), inet_addr("192.168.50.5"), NULL, 0, l, 0); + assert_true(r >= 0); + + r = libnet_build_ethernet(dst, src, 0x0800, NULL, 0, l, 0); + assert_true(r >= 0); + + r = libnet_write(l); + assert_true(r >= 0); + + sleep(1); + } + + libnet_destroy(l); +} + +static void test_tcp_packet_ipv4(void **state) { + char dst[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + char src[6] = {0x12,0x34,0x56,0x78,0x9a,0xab}; + char errbuf[LIBNET_ERRBUF_SIZE]; + uint8_t *payload, payload_s; + libnet_ptag_t tcp, ip, eth; + int c, i, j, seqn, ack; + char buf[1024] = {}; + pthread_t pcap_thread; + struct itimerval tval; + uint32_t len; + libnet_t *l; + int r; + + timerclear(& tval.it_interval); + timerclear(& tval.it_value); + tval.it_value.tv_sec = 10; + + (void) signal(SIGALRM, terminate_thread); + (void) setitimer(ITIMER_REAL, & tval, NULL); + + r = pthread_create(&pcap_thread, NULL, capture_packet_live, "tcp port 2425"); + assert_true(r >=0); + + payload_s = 10; + payload = malloc(payload_s*sizeof(uint8_t)); + assert_non_null(payload); + memset(payload,0,payload_s); + + l = libnet_init(LIBNET_LINK, "veth-peer", errbuf); + assert_non_null(l); + + tcp = ip = eth = LIBNET_PTAG_INITIALIZER; + for (i=0; i<5; i++){ + seqn=i * (LIBNET_TCP_H+payload_s + 1); + r = libnet_build_tcp(2425, 2426, seqn, seqn + LIBNET_TCP_H + payload_s + 1, + TH_SYN, 32767, 0, 10, LIBNET_TCP_H + payload_s, + payload, payload_s, l, tcp); + assert_true(r >=0); + + r = libnet_build_ipv4(LIBNET_IPV4_H + LIBNET_TCP_H + payload_s,0,242,0,64,IPPROTO_TCP,0, + inet_addr("192.168.50.6"), inet_addr("192.168.50.5"), + NULL,0,l,ip); + assert_true(r >=0); + + r = libnet_build_ethernet(dst, src, ETHERTYPE_IP, NULL, 0, l, eth); + assert_true(r >=0); + + r = libnet_write(l); + assert_true(r >=0); + + sleep(1); + } +} + +int main(int argc, char *argv[]) { + const struct CMUnitTest libpcap_tests[] = { + cmocka_unit_test(test_udp_packet_ipv4), + cmocka_unit_test(test_tcp_packet_ipv4), + }; + + return cmocka_run_group_tests(libpcap_tests, NULL, NULL); +} diff --git a/tests/tests.yml b/tests/tests.yml new file mode 100644 index 0000000..6f5f1cc --- /dev/null +++ b/tests/tests.yml @@ -0,0 +1,17 @@ +- hosts: localhost + roles: + - role: standard-test-beakerlib + tags: + - classic + tests: + - sanity-tests + required_packages: + - libnet + - libnet-devel + - libpcap + - libpcap-devel + - systemd + - wireshark-cli + - libcmocka + - libcmocka-devel + - gcc