From 5b6f524eea1ea8d2f0ecb2e17abfba7df708732f Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 26 May 2012 15:46:52 +0200 Subject: tests: add nfct tests for cttimeout This patch adds the automated tests for the cttimeout infrastructure. Signed-off-by: Pablo Neira Ayuso --- tests/nfct/run-test.sh | 20 +++++++++ tests/nfct/test-live.sh | 73 +++++++++++++++++++++++++++++++ tests/nfct/test.c | 100 +++++++++++++++++++++++++++++++++++++++++++ tests/nfct/timeout/00tcp | 16 +++++++ tests/nfct/timeout/01udp | 16 +++++++ tests/nfct/timeout/02generic | 16 +++++++ tests/nfct/timeout/03udplite | 16 +++++++ tests/nfct/timeout/04icmp | 16 +++++++ tests/nfct/timeout/05icmpv6 | 16 +++++++ tests/nfct/timeout/06sctp | 16 +++++++ tests/nfct/timeout/07dccp | 16 +++++++ tests/nfct/timeout/08gre | 16 +++++++ 12 files changed, 337 insertions(+) create mode 100644 tests/nfct/run-test.sh create mode 100644 tests/nfct/test-live.sh create mode 100644 tests/nfct/test.c create mode 100644 tests/nfct/timeout/00tcp create mode 100644 tests/nfct/timeout/01udp create mode 100644 tests/nfct/timeout/02generic create mode 100644 tests/nfct/timeout/03udplite create mode 100644 tests/nfct/timeout/04icmp create mode 100644 tests/nfct/timeout/05icmpv6 create mode 100644 tests/nfct/timeout/06sctp create mode 100644 tests/nfct/timeout/07dccp create mode 100644 tests/nfct/timeout/08gre (limited to 'tests') diff --git a/tests/nfct/run-test.sh b/tests/nfct/run-test.sh new file mode 100644 index 0000000..9bcad0d --- /dev/null +++ b/tests/nfct/run-test.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +UID=`id -u` +if [ $UID -ne 0 ] +then + echo "Run this test as root" + exit 1 +fi + +gcc test.c -o test +# +# XXX: module auto-load not support by nfnetlink_cttimeout yet :-( +# +modprobe nf_conntrack_ipv4 +modprobe nf_conntrack_ipv6 +modprobe nf_conntrack_proto_udplite +modprobe nf_conntrack_proto_sctp +modprobe nf_conntrack_proto_dccp +modprobe nf_conntrack_proto_gre +./test timeout diff --git a/tests/nfct/test-live.sh b/tests/nfct/test-live.sh new file mode 100644 index 0000000..c338e63 --- /dev/null +++ b/tests/nfct/test-live.sh @@ -0,0 +1,73 @@ +#!/bin/sh +# +# simple testing for cttimeout infrastructure using one single computer +# + +WAIT_BETWEEN_TESTS=10 + +# flush cttimeout table +nfct timeout flush + +# flush the conntrack table +conntrack -F + +# +# No.1: test generic timeout policy +# + +echo "---- test no. 1 ----" + +conntrack -E -p 13 & + +nfct timeout add test-generic inet generic timeout 100 +iptables -I OUTPUT -t raw -p all -j CT --timeout test-generic +hping3 -c 1 -V -I eth0 -0 8.8.8.8 -H 13 + +killall -15 conntrack + +echo "---- end test no. 1 ----" + +sleep $WAIT_BETWEEN_TESTS + +iptables -D OUTPUT -t raw -p all -j CT --timeout test-generic +nfct timeout del test-generic + +# +# No.2: test TCP timeout policy +# + +echo "---- test no. 2 ----" + +conntrack -E -p tcp & + +nfct timeout add test-tcp inet tcp syn_sent 100 +iptables -I OUTPUT -t raw -p tcp -j CT --timeout test-tcp +hping3 -V -S -p 80 -s 5050 8.8.8.8 -c 1 + +sleep $WAIT_BETWEEN_TESTS + +iptables -D OUTPUT -t raw -p tcp -j CT --timeout test-tcp +nfct timeout del test-tcp + +killall -15 conntrack + +echo "---- end test no. 2 ----" + +# +# No. 3: test ICMP timeout policy +# + +echo "---- test no. 3 ----" + +conntrack -E -p icmp & + +nfct timeout add test-icmp inet icmp timeout 50 +iptables -I OUTPUT -t raw -p icmp -j CT --timeout test-icmp +hping3 -1 8.8.8.8 -c 2 + +iptables -D OUTPUT -t raw -p icmp -j CT --timeout test-icmp +nfct timeout del test-icmp + +killall -15 conntrack + +echo "---- end test no. 3 ----" diff --git a/tests/nfct/test.c b/tests/nfct/test.c new file mode 100644 index 0000000..a833dcc --- /dev/null +++ b/tests/nfct/test.c @@ -0,0 +1,100 @@ +/* + * (c) 2012 by Pablo Neira Ayuso + * + * Extremely simple test utility for the command line tools. + * + * Based on test-conntrack.c + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PATH "/usr/sbin" + +int main(int argc, char *argv[]) +{ + int ret, ok = 0, bad = 0, line; + FILE *fp; + DIR *d; + char buf[1024]; + struct dirent *dent; + char file[1024]; + + if (argc < 2) { + fprintf(stderr, "Usage: %s directory\n", argv[0]); + exit(EXIT_FAILURE); + } + + d = opendir(argv[1]); + if (d == NULL) { + perror("opendir"); + exit(EXIT_FAILURE); + } + + setenv("PATH", PATH, 1); + + while ((dent = readdir(d)) != NULL) { + + sprintf(file, "%s/%s", argv[1], dent->d_name); + + line = 0; + + fp = fopen(file, "r"); + if (fp == NULL) { + perror("cannot find testsuite file"); + exit(EXIT_FAILURE); + } + + while (fgets(buf, sizeof(buf), fp)) { + char *res; + + line++; + + if (buf[0] == '#' || buf[0] == ' ') + continue; + + res = strchr(buf, ';'); + if (!res) { + printf("malformed file %s at line %d\n", + dent->d_name, line); + exit(EXIT_FAILURE); + } + *res = '\0'; + res+=2; + + printf("(%d) Executing: %s\n", line, buf); + + ret = system(buf); + + if (WIFEXITED(ret) && + WEXITSTATUS(ret) == EXIT_SUCCESS) { + if (res[0] == 'O' && + res[1] == 'K') + ok++; + else { + bad++; + printf("^----- BAD\n"); + } + } else { + if (res[0] == 'B' && + res[1] == 'A' && + res[2] == 'D') + ok++; + else { + bad++; + printf("^----- BAD\n"); + } + } + printf("=====\n"); + } + fclose(fp); + } + closedir(d); + + fprintf(stdout, "OK: %d BAD: %d\n", ok, bad); +} diff --git a/tests/nfct/timeout/00tcp b/tests/nfct/timeout/00tcp new file mode 100644 index 0000000..c9d7d24 --- /dev/null +++ b/tests/nfct/timeout/00tcp @@ -0,0 +1,16 @@ +# add policy object `test' +nfct timeout add test inet tcp established 100 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK +# get unexistent policy object `dummy' +nfct timeout get test ; BAD +# delete policy object `test', however, it does not exists anymore +nfct timeout delete test ; BAD +# add policy object `test' +nfct timeout add test inet tcp syn_sent 1 syn_recv 2 established 3 fin_wait 4 close_wait 5 last_ack 6 time_wait 7 close 8 syn_sent2 9 retrans 10 unacknowledged 11 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK diff --git a/tests/nfct/timeout/01udp b/tests/nfct/timeout/01udp new file mode 100644 index 0000000..952526c --- /dev/null +++ b/tests/nfct/timeout/01udp @@ -0,0 +1,16 @@ +# add policy object `test' +nfct timeout add test inet udp unreplied 10 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK +# get unexistent policy object `dummy' +nfct timeout get test ; BAD +# delete policy object `test', however, it does not exists anymore +nfct timeout delete test ; BAD +# add policy object `test' +nfct timeout add test inet udp unreplied 1 replied 2 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK diff --git a/tests/nfct/timeout/02generic b/tests/nfct/timeout/02generic new file mode 100644 index 0000000..b6ca699 --- /dev/null +++ b/tests/nfct/timeout/02generic @@ -0,0 +1,16 @@ +# add policy object `test' +nfct timeout add test inet generic timeout 10 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK +# get unexistent policy object `dummy' +nfct timeout get test ; BAD +# delete policy object `test', however, it does not exists anymore +nfct timeout delete test ; BAD +# add policy object `test' +nfct timeout add test inet generic timeout 1 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK diff --git a/tests/nfct/timeout/03udplite b/tests/nfct/timeout/03udplite new file mode 100644 index 0000000..69dda15 --- /dev/null +++ b/tests/nfct/timeout/03udplite @@ -0,0 +1,16 @@ +# add policy object `test' +nfct timeout add test inet udplite unreplied 10 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK +# get unexistent policy object `dummy' +nfct timeout get test ; BAD +# delete policy object `test', however, it does not exists anymore +nfct timeout delete test ; BAD +# add policy object `test' +nfct timeout add test inet udplite unreplied 1 replied 2 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK diff --git a/tests/nfct/timeout/04icmp b/tests/nfct/timeout/04icmp new file mode 100644 index 0000000..606e8b9 --- /dev/null +++ b/tests/nfct/timeout/04icmp @@ -0,0 +1,16 @@ +# add policy object `test' +nfct timeout add test inet icmp timeout 10 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK +# get unexistent policy object `dummy' +nfct timeout get test ; BAD +# delete policy object `test', however, it does not exists anymore +nfct timeout delete test ; BAD +# add policy object `test' +nfct timeout add test inet icmp timeout 1 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK diff --git a/tests/nfct/timeout/05icmpv6 b/tests/nfct/timeout/05icmpv6 new file mode 100644 index 0000000..16541f5 --- /dev/null +++ b/tests/nfct/timeout/05icmpv6 @@ -0,0 +1,16 @@ +# add policy object `test' +nfct timeout add test inet6 icmpv6 timeout 10 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK +# get unexistent policy object `dummy' +nfct timeout get test ; BAD +# delete policy object `test', however, it does not exists anymore +nfct timeout delete test ; BAD +# add policy object `test' +nfct timeout add test inet6 icmpv6 timeout 1 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK diff --git a/tests/nfct/timeout/06sctp b/tests/nfct/timeout/06sctp new file mode 100644 index 0000000..f475215 --- /dev/null +++ b/tests/nfct/timeout/06sctp @@ -0,0 +1,16 @@ +# add policy object `test' +nfct timeout add test inet sctp established 100 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK +# get unexistent policy object `dummy' +nfct timeout get test ; BAD +# delete policy object `test', however, it does not exists anymore +nfct timeout delete test ; BAD +# add policy object `test' +nfct timeout add test inet sctp closed 1 cookie_wait 2 cookie_echoed 3 established 4 shutdown_sent 5 shutdown_recd 6 shutdown_ack_sent 7 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK diff --git a/tests/nfct/timeout/07dccp b/tests/nfct/timeout/07dccp new file mode 100644 index 0000000..1bd4fa5 --- /dev/null +++ b/tests/nfct/timeout/07dccp @@ -0,0 +1,16 @@ +# add policy object `test' +nfct timeout add test inet dccp request 100 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK +# get unexistent policy object `dummy' +nfct timeout get test ; BAD +# delete policy object `test', however, it does not exists anymore +nfct timeout delete test ; BAD +# add policy object `test' +nfct timeout add test inet dccp request 1 respond 2 partopen 3 open 4 closereq 5 closing 6 timewait 7 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK diff --git a/tests/nfct/timeout/08gre b/tests/nfct/timeout/08gre new file mode 100644 index 0000000..7ef4bdb --- /dev/null +++ b/tests/nfct/timeout/08gre @@ -0,0 +1,16 @@ +# add policy object `test' +nfct timeout add test inet gre unreplied 10 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK +# get unexistent policy object `dummy' +nfct timeout get test ; BAD +# delete policy object `test', however, it does not exists anymore +nfct timeout delete test ; BAD +# add policy object `test' +nfct timeout add test inet gre unreplied 1 replied 2 ; OK +# get policy object `test' +nfct timeout get test ; OK +# delete policy object `test' +nfct timeout delete test ; OK -- cgit v1.2.3 From 0e1ce4f491e2134d6207f55c4a5f52e157a54707 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 26 May 2012 17:43:49 +0200 Subject: move qa directory to tests/conntrack/ All automated testing for the conntrack-tools will now reside under the test directory. Signed-off-by: Pablo Neira Ayuso --- qa/test-conntrack.c | 94 -------------------------------------- qa/testsuite/00create | 20 -------- qa/testsuite/01delete | 6 --- qa/testsuite/02filter | 23 ---------- qa/testsuite/03nat | 40 ---------------- qa/testsuite/04zone | 8 ---- qa/testsuite/05mark | 27 ----------- qa/testsuite/06update | 8 ---- tests/conntrack/test-conntrack.c | 94 ++++++++++++++++++++++++++++++++++++++ tests/conntrack/testsuite/00create | 20 ++++++++ tests/conntrack/testsuite/01delete | 6 +++ tests/conntrack/testsuite/02filter | 23 ++++++++++ tests/conntrack/testsuite/03nat | 40 ++++++++++++++++ tests/conntrack/testsuite/04zone | 8 ++++ tests/conntrack/testsuite/05mark | 27 +++++++++++ tests/conntrack/testsuite/06update | 8 ++++ 16 files changed, 226 insertions(+), 226 deletions(-) delete mode 100644 qa/test-conntrack.c delete mode 100644 qa/testsuite/00create delete mode 100644 qa/testsuite/01delete delete mode 100644 qa/testsuite/02filter delete mode 100644 qa/testsuite/03nat delete mode 100644 qa/testsuite/04zone delete mode 100644 qa/testsuite/05mark delete mode 100644 qa/testsuite/06update create mode 100644 tests/conntrack/test-conntrack.c create mode 100644 tests/conntrack/testsuite/00create create mode 100644 tests/conntrack/testsuite/01delete create mode 100644 tests/conntrack/testsuite/02filter create mode 100644 tests/conntrack/testsuite/03nat create mode 100644 tests/conntrack/testsuite/04zone create mode 100644 tests/conntrack/testsuite/05mark create mode 100644 tests/conntrack/testsuite/06update (limited to 'tests') diff --git a/qa/test-conntrack.c b/qa/test-conntrack.c deleted file mode 100644 index c9097b6..0000000 --- a/qa/test-conntrack.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Very simple test-tool for the command line tool `conntrack'. - * This code is released under GPLv2 or any later at your option. - * - * gcc test-conntrack.c -o test - * - * Do not forget that you need *root* or CAP_NET_ADMIN capabilities ;-) - * - * (c) 2008 Pablo Neira Ayuso - */ - -#include -#include -#include -#include -#include -#include -#include - -#define CT_PROG "/usr/sbin/conntrack" - -int main() -{ - int ret, ok = 0, bad = 0, line; - FILE *fp; - DIR *d; - char buf[1024]; - struct dirent *dent; - char file[1024]; - - d = opendir("testsuite"); - - while ((dent = readdir(d)) != NULL) { - - sprintf(file, "testsuite/%s", dent->d_name); - - line = 0; - - fp = fopen(file, "r"); - if (fp == NULL) { - perror("cannot find testsuite file"); - exit(EXIT_FAILURE); - } - - while (fgets(buf, sizeof(buf), fp)) { - char tmp[1024] = CT_PROG, *res; - tmp[strlen(CT_PROG)] = ' '; - - line++; - - if (buf[0] == '#' || buf[0] == ' ') - continue; - - res = strchr(buf, ';'); - if (!res) { - printf("malformed file %s at line %d\n", - dent->d_name, line); - exit(EXIT_FAILURE); - } - *res = '\0'; - res+=2; - - strcpy(tmp + strlen(CT_PROG) + 1, buf); - printf("(%d) Executing: %s\n", line, tmp); - - ret = system(tmp); - - if (WIFEXITED(ret) && - WEXITSTATUS(ret) == EXIT_SUCCESS) { - if (res[0] == 'O' && - res[1] == 'K') - ok++; - else { - bad++; - printf("^----- BAD\n"); - } - } else { - if (res[0] == 'B' && - res[1] == 'A' && - res[2] == 'D') - ok++; - else { - bad++; - printf("^----- BAD\n"); - } - } - printf("=====\n"); - } - fclose(fp); - } - closedir(d); - - fprintf(stdout, "OK: %d BAD: %d\n", ok, bad); -} diff --git a/qa/testsuite/00create b/qa/testsuite/00create deleted file mode 100644 index 40e2c19..0000000 --- a/qa/testsuite/00create +++ /dev/null @@ -1,20 +0,0 @@ -#missing destination --I -s 1.1.1.1 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD -#missing source --I -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD -#missing protocol --I -s 1.1.1.1 -d 2.2.2.2 --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD -#missing source port --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD -#missing timeout --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY ; BAD -# create a conntrack --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK -# create again --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD -# delete --D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 ; OK -# create from reply --I -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 --state LISTEN -u SEEN_REPLY -t 50 ; OK -# delete reverse --D -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 ; OK diff --git a/qa/testsuite/01delete b/qa/testsuite/01delete deleted file mode 100644 index 3c38ac5..0000000 --- a/qa/testsuite/01delete +++ /dev/null @@ -1,6 +0,0 @@ -# create dummy --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK -# delete bad source --D -s 2.2.2.2 -p tcp --sport 10 --dport 20 ; BAD -# delete by source --D -s 1.1.1.1 ; OK diff --git a/qa/testsuite/02filter b/qa/testsuite/02filter deleted file mode 100644 index 204c4e8..0000000 --- a/qa/testsuite/02filter +++ /dev/null @@ -1,23 +0,0 @@ -# create dummy -conntrack -I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK -# filter by source -conntrack -L -s 1.1.1.1 ; OK -# filter by destination -conntrack -L -d 2.2.2.2 ; OK -# filter by protocol -conntrack -L -p tcp ; OK -# filter by status -conntrack -L -u SEEN_REPLY ; OK -# filter by TCP protocol state -conntrack -L -p tcp --state LISTEN ; OK -# update mark of dummy conntrack -conntrack -U -s 1.1.1.1 -m 1 ; OK -# filter by mark -conntrack -L -m 1 ; OK -# filter by layer 3 protocol -conntrack -L -f ipv4 ; OK -# filter by mark -conntrack -L --mark 0 ; OK -conntrack -L --mark 0/0xffffffff; OK -# delete dummy -conntrack -D -d 2.2.2.2 ; OK diff --git a/qa/testsuite/03nat b/qa/testsuite/03nat deleted file mode 100644 index f94e8ff..0000000 --- a/qa/testsuite/03nat +++ /dev/null @@ -1,40 +0,0 @@ -# create dummy --I -s 1.1.1.1 -d 2.2.2.2 --dst-nat 3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK -# show --L --dst-nat ; OK -# show --L --dst-nat 3.3.3.3 ; OK -# show --L --src-nat ; OK -# delete --D -s 1.1.1.1 ; OK -# create dummy again --I -s 1.1.1.1 -d 2.2.2.2 --src-nat 3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK -# show --L --src-nat ; OK -# show --L --src-nat 3.3.3.3 ; OK -# show --L --dst-nat ; OK -# show any-nat --L --any-nat ; OK -# delete --D -s 1.1.1.1 ; OK -# bad combination --L --dst-nat --any-nat ; BAD -# bad combination --L --src-nat --any-nat ; BAD -# bad combination --L --src-nat --dst-nat --any-nat ; BAD -# create --I -s 1.1.1.1 -d 2.2.2.2 --dst-nat 3.3.3.3:80 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK -# show --L --dst-nat 3.3.3.3:80 ; OK -# show --L --any-nat 3.3.3.3:80 ; OK -# show --L --dst-nat 3.3.3.3:81 ; OK -# show --L --dst-nat 1.1.1.1:80 ; OK -# delete --D -s 1.1.1.1 ; OK diff --git a/qa/testsuite/04zone b/qa/testsuite/04zone deleted file mode 100644 index 4ff3d34..0000000 --- a/qa/testsuite/04zone +++ /dev/null @@ -1,8 +0,0 @@ -# create dummy --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --zone 1; OK -# display dummy --L --zone 1; OK -# display dummy --L --zone 0; OK -# delete dummy --D --zone 1; OK diff --git a/qa/testsuite/05mark b/qa/testsuite/05mark deleted file mode 100644 index 4d99dea..0000000 --- a/qa/testsuite/05mark +++ /dev/null @@ -1,27 +0,0 @@ -# create with a mark --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 42 ; OK -# find it again using mark --L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42 ; OK --L --mark 42; OK -# ct already exists --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 42/0xffffffff ; BAD -# delete by mark --D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/0xffffffff ; OK -# try again after del --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 417889/0xffffffff ; OK -# delete by mark --D --mark 417889 ; OK --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 0xffffffff ; OK -# zap top 16. --U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 0/0xffff0000 ; OK --L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 0x0000ffff ; OK --U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/0xffff ; OK --L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/0x0000ffff ; OK --L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/42 ; OK --L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 2/2 ; OK --L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 2/3 ; OK -# OK, but no flow entries should be shown here: --L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 2/0xf ; OK -# BAD, because no updates done (mark is already 42). --U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42 ; BAD --D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42 ; OK diff --git a/qa/testsuite/06update b/qa/testsuite/06update deleted file mode 100644 index 0408303..0000000 --- a/qa/testsuite/06update +++ /dev/null @@ -1,8 +0,0 @@ -# create dummy flow --I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state SYN_RECV -u SEEN_REPLY,ASSURED -t 50 ; OK -# find it again using mark --L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 ; OK -# set fixed timeout --U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 -u FIXED_TIMEOUT; OK -# delete it --D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20; OK diff --git a/tests/conntrack/test-conntrack.c b/tests/conntrack/test-conntrack.c new file mode 100644 index 0000000..c9097b6 --- /dev/null +++ b/tests/conntrack/test-conntrack.c @@ -0,0 +1,94 @@ +/* + * Very simple test-tool for the command line tool `conntrack'. + * This code is released under GPLv2 or any later at your option. + * + * gcc test-conntrack.c -o test + * + * Do not forget that you need *root* or CAP_NET_ADMIN capabilities ;-) + * + * (c) 2008 Pablo Neira Ayuso + */ + +#include +#include +#include +#include +#include +#include +#include + +#define CT_PROG "/usr/sbin/conntrack" + +int main() +{ + int ret, ok = 0, bad = 0, line; + FILE *fp; + DIR *d; + char buf[1024]; + struct dirent *dent; + char file[1024]; + + d = opendir("testsuite"); + + while ((dent = readdir(d)) != NULL) { + + sprintf(file, "testsuite/%s", dent->d_name); + + line = 0; + + fp = fopen(file, "r"); + if (fp == NULL) { + perror("cannot find testsuite file"); + exit(EXIT_FAILURE); + } + + while (fgets(buf, sizeof(buf), fp)) { + char tmp[1024] = CT_PROG, *res; + tmp[strlen(CT_PROG)] = ' '; + + line++; + + if (buf[0] == '#' || buf[0] == ' ') + continue; + + res = strchr(buf, ';'); + if (!res) { + printf("malformed file %s at line %d\n", + dent->d_name, line); + exit(EXIT_FAILURE); + } + *res = '\0'; + res+=2; + + strcpy(tmp + strlen(CT_PROG) + 1, buf); + printf("(%d) Executing: %s\n", line, tmp); + + ret = system(tmp); + + if (WIFEXITED(ret) && + WEXITSTATUS(ret) == EXIT_SUCCESS) { + if (res[0] == 'O' && + res[1] == 'K') + ok++; + else { + bad++; + printf("^----- BAD\n"); + } + } else { + if (res[0] == 'B' && + res[1] == 'A' && + res[2] == 'D') + ok++; + else { + bad++; + printf("^----- BAD\n"); + } + } + printf("=====\n"); + } + fclose(fp); + } + closedir(d); + + fprintf(stdout, "OK: %d BAD: %d\n", ok, bad); +} diff --git a/tests/conntrack/testsuite/00create b/tests/conntrack/testsuite/00create new file mode 100644 index 0000000..40e2c19 --- /dev/null +++ b/tests/conntrack/testsuite/00create @@ -0,0 +1,20 @@ +#missing destination +-I -s 1.1.1.1 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD +#missing source +-I -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD +#missing protocol +-I -s 1.1.1.1 -d 2.2.2.2 --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD +#missing source port +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD +#missing timeout +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY ; BAD +# create a conntrack +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK +# create again +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD +# delete +-D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 ; OK +# create from reply +-I -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 --state LISTEN -u SEEN_REPLY -t 50 ; OK +# delete reverse +-D -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 ; OK diff --git a/tests/conntrack/testsuite/01delete b/tests/conntrack/testsuite/01delete new file mode 100644 index 0000000..3c38ac5 --- /dev/null +++ b/tests/conntrack/testsuite/01delete @@ -0,0 +1,6 @@ +# create dummy +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK +# delete bad source +-D -s 2.2.2.2 -p tcp --sport 10 --dport 20 ; BAD +# delete by source +-D -s 1.1.1.1 ; OK diff --git a/tests/conntrack/testsuite/02filter b/tests/conntrack/testsuite/02filter new file mode 100644 index 0000000..204c4e8 --- /dev/null +++ b/tests/conntrack/testsuite/02filter @@ -0,0 +1,23 @@ +# create dummy +conntrack -I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK +# filter by source +conntrack -L -s 1.1.1.1 ; OK +# filter by destination +conntrack -L -d 2.2.2.2 ; OK +# filter by protocol +conntrack -L -p tcp ; OK +# filter by status +conntrack -L -u SEEN_REPLY ; OK +# filter by TCP protocol state +conntrack -L -p tcp --state LISTEN ; OK +# update mark of dummy conntrack +conntrack -U -s 1.1.1.1 -m 1 ; OK +# filter by mark +conntrack -L -m 1 ; OK +# filter by layer 3 protocol +conntrack -L -f ipv4 ; OK +# filter by mark +conntrack -L --mark 0 ; OK +conntrack -L --mark 0/0xffffffff; OK +# delete dummy +conntrack -D -d 2.2.2.2 ; OK diff --git a/tests/conntrack/testsuite/03nat b/tests/conntrack/testsuite/03nat new file mode 100644 index 0000000..f94e8ff --- /dev/null +++ b/tests/conntrack/testsuite/03nat @@ -0,0 +1,40 @@ +# create dummy +-I -s 1.1.1.1 -d 2.2.2.2 --dst-nat 3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK +# show +-L --dst-nat ; OK +# show +-L --dst-nat 3.3.3.3 ; OK +# show +-L --src-nat ; OK +# delete +-D -s 1.1.1.1 ; OK +# create dummy again +-I -s 1.1.1.1 -d 2.2.2.2 --src-nat 3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK +# show +-L --src-nat ; OK +# show +-L --src-nat 3.3.3.3 ; OK +# show +-L --dst-nat ; OK +# show any-nat +-L --any-nat ; OK +# delete +-D -s 1.1.1.1 ; OK +# bad combination +-L --dst-nat --any-nat ; BAD +# bad combination +-L --src-nat --any-nat ; BAD +# bad combination +-L --src-nat --dst-nat --any-nat ; BAD +# create +-I -s 1.1.1.1 -d 2.2.2.2 --dst-nat 3.3.3.3:80 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK +# show +-L --dst-nat 3.3.3.3:80 ; OK +# show +-L --any-nat 3.3.3.3:80 ; OK +# show +-L --dst-nat 3.3.3.3:81 ; OK +# show +-L --dst-nat 1.1.1.1:80 ; OK +# delete +-D -s 1.1.1.1 ; OK diff --git a/tests/conntrack/testsuite/04zone b/tests/conntrack/testsuite/04zone new file mode 100644 index 0000000..4ff3d34 --- /dev/null +++ b/tests/conntrack/testsuite/04zone @@ -0,0 +1,8 @@ +# create dummy +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --zone 1; OK +# display dummy +-L --zone 1; OK +# display dummy +-L --zone 0; OK +# delete dummy +-D --zone 1; OK diff --git a/tests/conntrack/testsuite/05mark b/tests/conntrack/testsuite/05mark new file mode 100644 index 0000000..4d99dea --- /dev/null +++ b/tests/conntrack/testsuite/05mark @@ -0,0 +1,27 @@ +# create with a mark +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 42 ; OK +# find it again using mark +-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42 ; OK +-L --mark 42; OK +# ct already exists +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 42/0xffffffff ; BAD +# delete by mark +-D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/0xffffffff ; OK +# try again after del +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 417889/0xffffffff ; OK +# delete by mark +-D --mark 417889 ; OK +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 --mark 0xffffffff ; OK +# zap top 16. +-U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 0/0xffff0000 ; OK +-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 0x0000ffff ; OK +-U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/0xffff ; OK +-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/0x0000ffff ; OK +-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42/42 ; OK +-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 2/2 ; OK +-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 2/3 ; OK +# OK, but no flow entries should be shown here: +-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 2/0xf ; OK +# BAD, because no updates done (mark is already 42). +-U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42 ; BAD +-D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --mark 42 ; OK diff --git a/tests/conntrack/testsuite/06update b/tests/conntrack/testsuite/06update new file mode 100644 index 0000000..0408303 --- /dev/null +++ b/tests/conntrack/testsuite/06update @@ -0,0 +1,8 @@ +# create dummy flow +-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state SYN_RECV -u SEEN_REPLY,ASSURED -t 50 ; OK +# find it again using mark +-L -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 ; OK +# set fixed timeout +-U -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 -u FIXED_TIMEOUT; OK +# delete it +-D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20; OK -- cgit v1.2.3 From 5e4ce59027bf7170c865388d3d703086f187ce59 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 26 May 2012 17:47:15 +0200 Subject: tests: conntrack: add run-test.sh script For automated testing of the conntrack utility. Signed-off-by: Pablo Neira Ayuso --- tests/conntrack/run-test.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/conntrack/run-test.sh (limited to 'tests') diff --git a/tests/conntrack/run-test.sh b/tests/conntrack/run-test.sh new file mode 100644 index 0000000..2b7b6f2 --- /dev/null +++ b/tests/conntrack/run-test.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +UID=`id -u` +if [ $UID -ne 0 ] +then + echo "Run this test as root" + exit 1 +fi + +gcc test-conntrack.c -o test +# +# XXX: module auto-load not support by nfnetlink_cttimeout yet :-( +# +modprobe nf_conntrack_ipv4 +modprobe nf_conntrack_ipv6 +modprobe nf_conntrack_proto_udplite +modprobe nf_conntrack_proto_sctp +modprobe nf_conntrack_proto_dccp +modprobe nf_conntrack_proto_gre +./test testcases -- cgit v1.2.3 From ee7cde037f8c39981df1237db4e8d8abfc06692d Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 25 May 2012 03:03:33 +0200 Subject: tests: conntrackd: add cthelper-test infrastructure This patch adds the automated testing infrastructure the user-space helpers. Basically, this adds the `cthelper-test' program that can be invoked from the command line: ./cthelper-test pcaps/oracle-tns-redirect.pcap tns tcp 1521 To test the helper with one PCAP file that contains traces of Oracle TNS traffic. It also provides tweaks to test the DNAT content mangling code: ./cthelper-test pcaps/oracle-tns-redirect.pcap tns tcp 1521 dnat This will also allow fuzzy testing of user-space helper, for further validation, not yet implemented. To compile this tool, you have to run: ./configure make check under the qa/cthelper-test/ directory. I'm doing like this because this directory is not included in the standalone tarball that make distcheck generates (I don't want to bloat it with development tools that can be retrieved from the git repository). Signed-off-by: Pablo Neira Ayuso --- tests/conntrackd/cthelper/.gitignore | 14 ++ tests/conntrackd/cthelper/Make_global.am | 7 + tests/conntrackd/cthelper/Makefile.am | 20 ++ tests/conntrackd/cthelper/README | 2 + tests/conntrackd/cthelper/configure.ac | 64 ++++++ tests/conntrackd/cthelper/ct.c | 91 +++++++++ tests/conntrackd/cthelper/ct.h | 22 +++ tests/conntrackd/cthelper/expect.c | 199 +++++++++++++++++++ tests/conntrackd/cthelper/l3_ipv4.c | 86 ++++++++ tests/conntrackd/cthelper/l4_tcp.c | 88 +++++++++ tests/conntrackd/cthelper/l4_udp.c | 88 +++++++++ tests/conntrackd/cthelper/main.c | 220 +++++++++++++++++++++ tests/conntrackd/cthelper/pcaps/nfsv3.pcap | Bin 0 -> 6824 bytes .../cthelper/pcaps/oracle-tns-redirect.pcap | Bin 0 -> 1095 bytes tests/conntrackd/cthelper/proto.c | 49 +++++ tests/conntrackd/cthelper/proto.h | 50 +++++ tests/conntrackd/cthelper/run-test.sh | 11 ++ tests/conntrackd/cthelper/test.h | 13 ++ 18 files changed, 1024 insertions(+) create mode 100644 tests/conntrackd/cthelper/.gitignore create mode 100644 tests/conntrackd/cthelper/Make_global.am create mode 100644 tests/conntrackd/cthelper/Makefile.am create mode 100644 tests/conntrackd/cthelper/README create mode 100644 tests/conntrackd/cthelper/configure.ac create mode 100755 tests/conntrackd/cthelper/ct.c create mode 100755 tests/conntrackd/cthelper/ct.h create mode 100644 tests/conntrackd/cthelper/expect.c create mode 100755 tests/conntrackd/cthelper/l3_ipv4.c create mode 100755 tests/conntrackd/cthelper/l4_tcp.c create mode 100755 tests/conntrackd/cthelper/l4_udp.c create mode 100755 tests/conntrackd/cthelper/main.c create mode 100644 tests/conntrackd/cthelper/pcaps/nfsv3.pcap create mode 100644 tests/conntrackd/cthelper/pcaps/oracle-tns-redirect.pcap create mode 100755 tests/conntrackd/cthelper/proto.c create mode 100755 tests/conntrackd/cthelper/proto.h create mode 100644 tests/conntrackd/cthelper/run-test.sh create mode 100644 tests/conntrackd/cthelper/test.h (limited to 'tests') diff --git a/tests/conntrackd/cthelper/.gitignore b/tests/conntrackd/cthelper/.gitignore new file mode 100644 index 0000000..928e44b --- /dev/null +++ b/tests/conntrackd/cthelper/.gitignore @@ -0,0 +1,14 @@ +.deps/ +.libs/ +Makefile +Makefile.in +*.o +*.la +*.lo + +/aclocal.m4 +/autom4te.cache/ +/build-aux/ +/config.* +/configure +/libtool diff --git a/tests/conntrackd/cthelper/Make_global.am b/tests/conntrackd/cthelper/Make_global.am new file mode 100644 index 0000000..06785a1 --- /dev/null +++ b/tests/conntrackd/cthelper/Make_global.am @@ -0,0 +1,7 @@ +AM_CPPFLAGS = -I$(top_srcdir)/include -I../../../include + +AM_CFLAGS = -std=gnu99 -W -Wall \ + -Wmissing-prototypes -Wwrite-strings -Wcast-qual -Wfloat-equal -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wstrict-prototypes -Wundef \ + -Wno-unused-parameter \ + ${LIBNETFILTER_CONNTRACK_CFLAGS} \ + ${LIBNETFILTER_CTTIMEOUT_CFLAGS} diff --git a/tests/conntrackd/cthelper/Makefile.am b/tests/conntrackd/cthelper/Makefile.am new file mode 100644 index 0000000..b8f0d42 --- /dev/null +++ b/tests/conntrackd/cthelper/Makefile.am @@ -0,0 +1,20 @@ +include $(top_srcdir)/Make_global.am + +check_PROGRAMS = cthelper-test + +cthelper_test_SOURCES = proto.c \ + ct.c \ + l3_ipv4.c \ + l4_tcp.c \ + l4_udp.c \ + expect.c \ + ../../../src/helpers.c \ + main.c + +cthelper_test_LDFLAGS = -dynamic \ + -lpcap \ + -ldl \ + -lmnl \ + -lnetfilter_queue \ + -lnetfilter_conntrack \ + -export-dynamic diff --git a/tests/conntrackd/cthelper/README b/tests/conntrackd/cthelper/README new file mode 100644 index 0000000..6e8b385 --- /dev/null +++ b/tests/conntrackd/cthelper/README @@ -0,0 +1,2 @@ +This directory contains PCAP files with traffic traces that we can use to test +the user-space helpers. diff --git a/tests/conntrackd/cthelper/configure.ac b/tests/conntrackd/cthelper/configure.ac new file mode 100644 index 0000000..8b3da5c --- /dev/null +++ b/tests/conntrackd/cthelper/configure.ac @@ -0,0 +1,64 @@ +AC_INIT(cthelper-test, 0.0.1, pablo@netfilter.org) +AC_CONFIG_AUX_DIR([build-aux]) + +AC_CANONICAL_HOST +AC_CONFIG_MACRO_DIR([m4]) +AM_INIT_AUTOMAKE([-Wall foreign subdir-objects + tar-pax no-dist-gzip dist-bzip2 1.6]) + +dnl kernel style compile messages +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_SEARCH_LIBS([dlopen], [dl], [libdl_LIBS="$LIBS"; LIBS=""]) +AC_SUBST([libdl_LIBS]) + +AC_PROG_CC +AC_DISABLE_STATIC +AM_PROG_LIBTOOL +AC_PROG_INSTALL +AC_PROG_LN_S +AM_PROG_LEX +AC_PROG_YACC + +case "$host" in +*-*-linux*) ;; +*) AC_MSG_ERROR([Linux only, dude!]);; +esac + +PKG_CHECK_MODULES([LIBNETFILTER_CONNTRACK], [libnetfilter_conntrack >= 1.0.0]) +PKG_CHECK_MODULES([LIBNETFILTER_QUEUE], [libnetfilter_queue >= 1.0.0]) + +AC_CHECK_HEADERS(arpa/inet.h) +dnl check for inet_pton +AC_CHECK_FUNCS(inet_pton) +dnl Some systems have it, but not IPv6 +if test "$ac_cv_func_inet_pton" = "yes" ; then +AC_MSG_CHECKING(if inet_pton supports IPv6) +AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +int main() + { + struct in6_addr addr6; + if (inet_pton(AF_INET6, "::1", &addr6) < 1) + exit(1); + else + exit(0); + } + ]])],[ AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6, 1, [Define to 1 if inet_pton supports IPv6.]) + ],[AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)]) +fi + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/tests/conntrackd/cthelper/ct.c b/tests/conntrackd/cthelper/ct.c new file mode 100755 index 0000000..1c17336 --- /dev/null +++ b/tests/conntrackd/cthelper/ct.c @@ -0,0 +1,91 @@ +#include +#include +#include + +#include + +#include + +#include "proto.h" +#include "helper.h" +#include "myct.h" +#include "ct.h" + +static LIST_HEAD(ct_list); + +struct nf_ct_entry * +ct_alloc(const uint8_t *pkt, unsigned int l3hdr_len, + struct cthelper_proto_l2l3_helper *l3h, + struct cthelper_proto_l4_helper *l4h) +{ + struct nf_ct_entry *ct; + + ct = calloc(1, sizeof(struct nf_ct_entry)); + if (ct == NULL) + return NULL; + + ct->myct = calloc(1, sizeof(struct myct)); + if (ct->myct == NULL) { + free(ct); + return NULL; + } + ct->myct->ct = nfct_new(); + if (ct->myct->ct == NULL) { + free(ct->myct); + free(ct); + return NULL; + } + /* FIXME: use good private helper size */ + ct->myct->priv_data = calloc(1, 128); + if (ct->myct->priv_data == NULL) { + nfct_destroy(ct->myct->ct); + free(ct->myct); + free(ct); + return NULL; + } + + l3h->l3ct_build(pkt, ct->myct->ct); + l4h->l4ct_build(pkt + l3hdr_len, ct->myct->ct); + + return ct; +} + +struct nf_ct_entry * +ct_find(const uint8_t *pkt, unsigned int l3hdr_len, + struct cthelper_proto_l2l3_helper *l3h, + struct cthelper_proto_l4_helper *l4h, unsigned int *ctinfo) +{ + struct nf_ct_entry *cur; + + list_for_each_entry(cur, &ct_list, head) { + if (l3h->l3ct_cmp_orig(pkt, cur->myct->ct) && + l4h->l4ct_cmp_orig(pkt + l3hdr_len, cur->myct->ct)) { + *ctinfo = 0; + return cur; + } + if (l3h->l3ct_cmp_repl(pkt, cur->myct->ct) && + l4h->l4ct_cmp_repl(pkt + l3hdr_len, cur->myct->ct)) { + *ctinfo = IP_CT_IS_REPLY; + return cur; + } + } + return NULL; +} + +void ct_add(struct nf_ct_entry *ct) +{ + list_add(&ct->head, &ct_list); +} + +void ct_flush(void) +{ + struct nf_ct_entry *cur, *tmp; + + list_for_each_entry_safe(cur, tmp, &ct_list, head) { + list_del(&cur->head); + free(cur->myct->priv_data); + free(cur->myct->ct); + free(cur->myct); + free(cur); + } +} diff --git a/tests/conntrackd/cthelper/ct.h b/tests/conntrackd/cthelper/ct.h new file mode 100755 index 0000000..f01d49d --- /dev/null +++ b/tests/conntrackd/cthelper/ct.h @@ -0,0 +1,22 @@ +#ifndef _CT_H_ +#define _CT_H_ + +#include "../../../include/linux_list.h" +#include "../../../include/myct.h" + +struct nf_ct_entry { + struct list_head head; + struct myct *myct; +}; + +struct cthelper_proto_l2l3_helper; +struct cthelper_proto_l4_helper; + +struct nf_ct_entry *ct_alloc(const uint8_t *pkt, unsigned int l3hdr_len, struct cthelper_proto_l2l3_helper *l3h, struct cthelper_proto_l4_helper *l4h); + +struct nf_ct_entry *ct_find(const uint8_t *pkt, unsigned int l3hdr_len, struct cthelper_proto_l2l3_helper *l3h, struct cthelper_proto_l4_helper *l4h, unsigned int *ctinfo); + +void ct_add(struct nf_ct_entry *ct); +void ct_flush(void); + +#endif diff --git a/tests/conntrackd/cthelper/expect.c b/tests/conntrackd/cthelper/expect.c new file mode 100644 index 0000000..c667293 --- /dev/null +++ b/tests/conntrackd/cthelper/expect.c @@ -0,0 +1,199 @@ +/* + * (C) 2012 by Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation (or any later at your option). + * + * This code has been sponsored by Vyatta Inc. + */ + +#include "../../../include/helper.h" +#include "test.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +int +cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, + uint32_t class, + union nfct_attr_grp_addr *saddr, + union nfct_attr_grp_addr *daddr, + uint8_t l4proto, uint16_t *sport, uint16_t *dport) +{ + struct nf_conntrack *expected, *mask; + + expected = nfct_new(); + if (!expected) + return -1; + + mask = nfct_new(); + if (!mask) + return -1; + + if (saddr) { + switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { + int i; + uint32_t addr[4] = {}; + + case AF_INET: + nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); + nfct_set_attr_u32(expected, ATTR_IPV4_SRC, saddr->ip); + + nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET); + nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0xffffffff); + break; + case AF_INET6: + nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); + nfct_set_attr(expected, ATTR_IPV6_SRC, saddr->ip6); + + for (i=0; i<4; i++) + memset(addr, 0xffffffff, sizeof(uint32_t)); + + nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET6); + nfct_set_attr(mask, ATTR_IPV6_SRC, addr); + break; + default: + break; + } + } else { + switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { + int i; + uint32_t addr[4] = {}; + + case AF_INET: + nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); + nfct_set_attr_u32(expected, ATTR_IPV4_SRC, 0x00000000); + + nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET); + nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0x00000000); + break; + case AF_INET6: + for (i=0; i<4; i++) + memset(addr, 0x00000000, sizeof(uint32_t)); + + nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); + nfct_set_attr(expected, ATTR_IPV6_SRC, addr); + + nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET6); + nfct_set_attr(mask, ATTR_IPV6_SRC, addr); + break; + default: + break; + } + } + + if (sport) { + switch(l4proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + nfct_set_attr_u8(expected, ATTR_L4PROTO, l4proto); + nfct_set_attr_u16(expected, ATTR_PORT_SRC, *sport); + nfct_set_attr_u8(mask, ATTR_L4PROTO, l4proto); + nfct_set_attr_u16(mask, ATTR_PORT_SRC, 0xffff); + break; + default: + break; + } + } else { + switch(l4proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + nfct_set_attr_u8(expected, ATTR_L4PROTO, l4proto); + nfct_set_attr_u16(expected, ATTR_PORT_SRC, 0x0000); + nfct_set_attr_u8(mask, ATTR_L4PROTO, l4proto); + nfct_set_attr_u16(mask, ATTR_PORT_SRC, 0x0000); + break; + default: + break; + } + } + + switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { + uint32_t addr[4] = {}; + int i; + + case AF_INET: + nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); + nfct_set_attr_u32(expected, ATTR_IPV4_DST, daddr->ip); + nfct_set_attr_u32(mask, ATTR_IPV4_DST, 0xffffffff); + break; + case AF_INET6: + nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); + nfct_set_attr(expected, ATTR_IPV6_DST, daddr->ip6); + + for (i=0; i<4; i++) + memset(addr, 0xffffffff, sizeof(uint32_t)); + + nfct_set_attr(mask, ATTR_IPV6_DST, addr); + break; + default: + break; + } + + switch(l4proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + nfct_set_attr_u8(expected, ATTR_L4PROTO, l4proto); + nfct_set_attr_u16(expected, ATTR_PORT_DST, *dport); + nfct_set_attr_u8(mask, ATTR_L4PROTO, l4proto); + nfct_set_attr_u16(mask, ATTR_PORT_DST, 0xffff); + break; + default: + break; + } + + nfexp_set_attr(exp, ATTR_EXP_MASTER, master); + nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected); + nfexp_set_attr(exp, ATTR_EXP_MASK, mask); + + nfct_destroy(expected); + nfct_destroy(mask); + + return 0; +} + +int cthelper_add_expect(struct nf_expect *exp) +{ + cthelper_test_stats.ct_expect_created++; + return 0; +} + +int cthelper_del_expect(struct nf_expect *exp) +{ + return 0; +} + +void +cthelper_get_addr_src(struct nf_conntrack *ct, int dir, + union nfct_attr_grp_addr *addr) +{ + switch (dir) { + case MYCT_DIR_ORIG: + nfct_get_attr_grp(ct, ATTR_GRP_ORIG_ADDR_SRC, addr); + break; + case MYCT_DIR_REPL: + nfct_get_attr_grp(ct, ATTR_GRP_REPL_ADDR_SRC, addr); + break; + } +} + +void +cthelper_get_addr_dst(struct nf_conntrack *ct, int dir, + union nfct_attr_grp_addr *addr) +{ + switch (dir) { + case MYCT_DIR_ORIG: + nfct_get_attr_grp(ct, ATTR_GRP_ORIG_ADDR_DST, addr); + break; + case MYCT_DIR_REPL: + nfct_get_attr_grp(ct, ATTR_GRP_REPL_ADDR_DST, addr); + break; + } +} diff --git a/tests/conntrackd/cthelper/l3_ipv4.c b/tests/conntrackd/cthelper/l3_ipv4.c new file mode 100755 index 0000000..8edfd2e --- /dev/null +++ b/tests/conntrackd/cthelper/l3_ipv4.c @@ -0,0 +1,86 @@ +#include +#include +#include + +#include "proto.h" + +#include + +#define PRINT_CMP(...) + +static void +l3_ipv4_ct_build_tuple(const uint8_t *pkt, struct nf_conntrack *ct) +{ + const struct iphdr *iph = (const struct iphdr *)pkt; + + nfct_set_attr_u16(ct, ATTR_ORIG_L3PROTO, AF_INET); + nfct_set_attr_u16(ct, ATTR_REPL_L3PROTO, AF_INET); + nfct_set_attr_u32(ct, ATTR_ORIG_IPV4_SRC, iph->saddr); + nfct_set_attr_u32(ct, ATTR_ORIG_IPV4_DST, iph->daddr); + nfct_set_attr_u32(ct, ATTR_REPL_IPV4_SRC, iph->daddr); + nfct_set_attr_u32(ct, ATTR_REPL_IPV4_DST, iph->saddr); +} + +static int +l3_ipv4_ct_cmp_tuple_orig(const uint8_t *pkt, struct nf_conntrack *ct) +{ + const struct iphdr *iph = (const struct iphdr *)pkt; + + PRINT_CMP("cmp_orig iph->saddr: %x == %x\n", + iph->saddr, nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC)); + PRINT_CMP("cmp_orig iph->daddr: %x == %x\n", + iph->daddr, nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST)); + + if (iph->saddr == nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC) && + iph->daddr == nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST)) + return 1; + + return 0; +} + +static int +l3_ipv4_ct_cmp_tuple_repl(const uint8_t *pkt, struct nf_conntrack *ct) +{ + const struct iphdr *iph = (const struct iphdr *)pkt; + + PRINT_CMP("cmp_repl iph->saddr: %x == %x\n", + iph->saddr, nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC)); + PRINT_CMP("cmp_repl iph->daddr: %x == %x\n", + iph->daddr, nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST)); + + if (iph->saddr == nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC) && + iph->daddr == nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST)) + return 1; + + return 0; +} + +static int l3_ipv4_pkt_l4proto_num(const uint8_t *pkt) +{ + const struct iphdr *iph = (const struct iphdr *)pkt; + + return iph->protocol; +} + +static int l3_ipv4_pkt_l3hdr_len(const uint8_t *pkt) +{ + const struct iphdr *iph = (const struct iphdr *)pkt; + + return iph->ihl << 2; +} + +static struct cthelper_proto_l2l3_helper ipv4 = { + .l2protonum = ETH_P_IP, + .l3protonum = AF_INET, + .l2hdr_len = ETH_HLEN, + .l3ct_build = l3_ipv4_ct_build_tuple, + .l3ct_cmp_orig = l3_ipv4_ct_cmp_tuple_orig, + .l3ct_cmp_repl = l3_ipv4_ct_cmp_tuple_repl, + .l3pkt_hdr_len = l3_ipv4_pkt_l3hdr_len, + .l4pkt_proto = l3_ipv4_pkt_l4proto_num, +}; + +void l2l3_ipv4_init(void) +{ + cthelper_proto_l2l3_helper_register(&ipv4); +} diff --git a/tests/conntrackd/cthelper/l4_tcp.c b/tests/conntrackd/cthelper/l4_tcp.c new file mode 100755 index 0000000..f27c85d --- /dev/null +++ b/tests/conntrackd/cthelper/l4_tcp.c @@ -0,0 +1,88 @@ +#include +#include + +#include "proto.h" + +#include + +#define PRINT_CMP(...) + +static void l4_tcp_ct_build_tuple(const uint8_t *pkt, struct nf_conntrack *ct) +{ + const struct tcphdr *tcph = (const struct tcphdr *)pkt; + + nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_TCP); + nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_TCP); + nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, tcph->source); + nfct_set_attr_u16(ct, ATTR_ORIG_PORT_DST, tcph->dest); + nfct_set_attr_u16(ct, ATTR_REPL_PORT_SRC, tcph->dest); + nfct_set_attr_u16(ct, ATTR_REPL_PORT_DST, tcph->source); +} + +static int l4_tcp_ct_cmp_tuple_orig(const uint8_t *pkt, struct nf_conntrack *ct) +{ + const struct tcphdr *tcph = (const struct tcphdr *)pkt; + + PRINT_CMP("cmp_orig tcph->source: %u == %u\n", + tcph->source, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); + PRINT_CMP("cmp_orig tcph->dest: %u == %u\n", + tcph->dest, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); + + if (tcph->source == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) && + tcph->dest == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)) + return 1; + + return 0; +} + +static int +l4_tcp_ct_cmp_tuple_repl(const uint8_t *pkt, struct nf_conntrack *ct) +{ + const struct tcphdr *tcph = (const struct tcphdr *)pkt; + + PRINT_CMP("cmp_repl tcph->source: %u == %u\n", + tcph->source, nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC)); + PRINT_CMP("cmp_repl tcph->dest: %u == %u\n", + tcph->dest, nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)); + + if (tcph->source == nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC) && + tcph->dest == nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)) + return 1; + + return 0; +} + +static int +l4_tcp_ct_cmp_port(struct nf_conntrack *ct, uint16_t port) +{ + PRINT_CMP("cmp_port src: %u == %u\n", + port, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); + PRINT_CMP("cmp_port dst: %u == %u\n", + port, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); + + if (port == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) || + port == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)) + return 1; + + return 0; +} + +static int l4_tcp_pkt_no_data(const uint8_t *pkt) +{ + const struct tcphdr *tcph = (const struct tcphdr *)pkt; + return tcph->syn || tcph->fin || tcph->rst || !tcph->psh; +} + +static struct cthelper_proto_l4_helper tcp = { + .l4protonum = IPPROTO_TCP, + .l4ct_build = l4_tcp_ct_build_tuple, + .l4ct_cmp_orig = l4_tcp_ct_cmp_tuple_orig, + .l4ct_cmp_repl = l4_tcp_ct_cmp_tuple_repl, + .l4ct_cmp_port = l4_tcp_ct_cmp_port, + .l4pkt_no_data = l4_tcp_pkt_no_data, +}; + +void l4_tcp_init(void) +{ + cthelper_proto_l4_helper_register(&tcp); +} diff --git a/tests/conntrackd/cthelper/l4_udp.c b/tests/conntrackd/cthelper/l4_udp.c new file mode 100755 index 0000000..4d52d0a --- /dev/null +++ b/tests/conntrackd/cthelper/l4_udp.c @@ -0,0 +1,88 @@ +#include +#include + +#include "proto.h" + +#include + +#define PRINT_CMP(...) + +static void l4_udp_ct_build_tuple(const uint8_t *pkt, struct nf_conntrack *ct) +{ + const struct udphdr *udph = (const struct udphdr *)pkt; + + nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_UDP); + nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_UDP); + nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, udph->source); + nfct_set_attr_u16(ct, ATTR_ORIG_PORT_DST, udph->dest); + nfct_set_attr_u16(ct, ATTR_REPL_PORT_SRC, udph->dest); + nfct_set_attr_u16(ct, ATTR_REPL_PORT_DST, udph->source); +} + +static int l4_udp_ct_cmp_tuple_orig(const uint8_t *pkt, struct nf_conntrack *ct) +{ + const struct udphdr *udph = (const struct udphdr *)pkt; + + PRINT_CMP("cmp_orig udph->source: %u == %u\n", + udph->source, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); + PRINT_CMP("cmp_orig udph->dest: %u == %u\n", + udph->dest, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); + + if (udph->source == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) && + udph->dest == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)) + return 1; + + return 0; +} + +static int +l4_udp_ct_cmp_tuple_repl(const uint8_t *pkt, struct nf_conntrack *ct) +{ + const struct udphdr *udph = (const struct udphdr *)pkt; + + PRINT_CMP("cmp_repl udph->source: %u == %u\n", + udph->source, nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC)); + PRINT_CMP("cmp_repl udph->dest: %u == %u\n", + udph->dest, nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)); + + if (udph->source == nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC) && + udph->dest == nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)) + return 1; + + return 0; +} + +static int +l4_udp_ct_cmp_port(struct nf_conntrack *ct, uint16_t port) +{ + PRINT_CMP("cmp_port src: %u == %u\n", + port, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); + PRINT_CMP("cmp_port dst: %u == %u\n", + port, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); + + if (port == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) || + port == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)) + return 1; + + return 0; +} + +static int l4_udp_pkt_no_data(const uint8_t *pkt) +{ + /* UDP has no control packets. */ + return 1; +} + +static struct cthelper_proto_l4_helper tcp = { + .l4protonum = IPPROTO_UDP, + .l4ct_build = l4_udp_ct_build_tuple, + .l4ct_cmp_orig = l4_udp_ct_cmp_tuple_orig, + .l4ct_cmp_repl = l4_udp_ct_cmp_tuple_repl, + .l4ct_cmp_port = l4_udp_ct_cmp_port, + .l4pkt_no_data = l4_udp_pkt_no_data, +}; + +void l4_udp_init(void) +{ + cthelper_proto_l4_helper_register(&tcp); +} diff --git a/tests/conntrackd/cthelper/main.c b/tests/conntrackd/cthelper/main.c new file mode 100755 index 0000000..f229c5d --- /dev/null +++ b/tests/conntrackd/cthelper/main.c @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ct.h" +#include "proto.h" +#include "../../../include/helper.h" +#include "test.h" + +#include + +struct cthelper_test_stats cthelper_test_stats; + +enum { + TEST_NORMAL = 0, + TEST_DNAT, +}; + +static int +cthelper_process_packet(const uint8_t *pkt, uint32_t pktlen, + struct ctd_helper *h, int proto, uint16_t port, + int type) +{ + struct pkt_buff *pktb; + struct cthelper_proto_l2l3_helper *l3h; + struct cthelper_proto_l4_helper *l4h; + unsigned int l3hdr_len, l4protonum; + struct nf_ct_entry *ct; + int ret, this_proto; + uint32_t dataoff, ctinfo = 0; + + l3h = cthelper_proto_l2l3_helper_find(pkt, &l4protonum, &l3hdr_len); + if (l3h == NULL) { + fprintf(stderr, "Unsupported layer 3 protocol, skipping.\n"); + return -1; + } + + l4h = cthelper_proto_l4_helper_find(pkt, l4protonum); + if (l4h == NULL) { + fprintf(stderr, "Unsupported layer 4 protocol, skipping.\n"); + return -1; + } + /* get layer 3 header. */ + pkt += l3h->l2hdr_len; + pktlen -= l3h->l2hdr_len; + + /* skip packet with mismatching protocol */ + this_proto = l3h->l4pkt_proto(pkt); + if (this_proto != proto) { + cthelper_test_stats.pkt_mismatch_proto++; + return 0; + } + + /* Look for the fake conntrack. */ + ct = ct_find(pkt, l3hdr_len, l3h, l4h, &ctinfo); + if (ct == NULL) { + /* It doesn't exist any, create one. */ + ct = ct_alloc(pkt, l3hdr_len, l3h, l4h); + if (ct == NULL) { + fprintf(stderr, "Not enough memory\n"); + return -1; + } + ct_add(ct); + ctinfo += IP_CT_NEW; + } else + ctinfo += IP_CT_ESTABLISHED; + + /* skip packets with mismatching ports */ + if (!l4h->l4ct_cmp_port(ct->myct->ct, ntohs(port))) { + cthelper_test_stats.pkt_mismatch_port++; + return -1; + } + + /* + * FIXME: reminder, implement this below in the kernel for cthelper. + */ + + /* This packet contains no data, skip it. */ +/* if (l4h->l4pkt_no_data && l4h->l4pkt_no_data(pkt + l3hdr_len)) { + NFG_DEBUG("skipping packet with no data\n"); + continue; + } */ + + /* Create the fake network buffer. */ + pktb = pktb_alloc(AF_INET, pkt, pktlen, 128); + if (pktb == NULL) { + fprintf(stderr, "Not enough memory\n"); + return -1; + } + + dataoff = l3h->l3pkt_hdr_len(pkt); + if (dataoff > pktb_len(pktb)) { + fprintf(stderr, "wrong layer 3 offset: %d > %d\n", + dataoff, pktb_len(pktb)); + return -1; + } + + /* tweak to run DNAT mangling code using the same PCAP file. */ + if (type == TEST_DNAT) { + struct nf_conntrack *tmp = ct->myct->ct; + /* as long as this is tested, who cares the destination IP? */ + in_addr_t addr = inet_addr("1.1.1.1"); + + /* clone the real conntrack, to add DNAT information */ + ct->myct->ct = nfct_clone(ct->myct->ct); + /* set fake DNAT information */ + nfct_set_attr_u32(ct->myct->ct, ATTR_STATUS, IPS_DST_NAT); + nfct_set_attr_u32(ct->myct->ct, ATTR_ORIG_IPV4_DST, addr); + /* pass it to helper */ + ret = h->cb(pktb, dataoff, ct->myct, ctinfo); + /* restore real conntrack */ + nfct_destroy(ct->myct->ct); + ct->myct->ct = tmp; + + if (pktb_mangled(pktb)) { + int i; + uint8_t *data = pktb_network_header(pktb); + + printf("\e[1;31mmangled content: ", pktb_len(pktb)); + + for (i=0; i < pktb_len(pktb); i++) + printf("%c", data[i]); + + printf("\e[0m\n"); + } + } else + ret = h->cb(pktb, dataoff, ct->myct, ctinfo); + + pktb_free(pktb); + + return ret; +} + +static int +cthelper_test(const char *pcapfile, const char *helper_name, + int l4proto, uint16_t port, int type) +{ + struct pcap_pkthdr pcaph; + char errbuf[PCAP_ERRBUF_SIZE]; + const u_char *pkt; + pcap_t *handle; + struct ctd_helper *h; + + h = helper_find("/usr/lib/conntrack-tools", + helper_name, l4proto, RTLD_NOW); + if (h == NULL) { + fprintf(stderr, "couldn't find helper: %s\n", helper_name); + return -1; + } + + handle = pcap_open_offline(pcapfile, errbuf); + if (handle == NULL) { + fprintf(stderr, "couldn't open pcap file %s: %s\n", + pcapfile, errbuf); + return -1; + } + while ((pkt = pcap_next(handle, &pcaph)) != NULL) { + cthelper_test_stats.pkts++; + cthelper_process_packet(pkt, pcaph.caplen, h, l4proto, port, + type); + } + + ct_flush(); + pcap_close(handle); + return 0; +} + +int main(int argc, char *argv[]) +{ + int ret, l4proto, type = TEST_NORMAL; + + if (argc < 5 || argc > 6) { + fprintf(stderr, "Wrong usage:\n"); + fprintf(stderr, "%s " + " [dnat]\n", + argv[0]); + fprintf(stderr, "example: %s file.pcap ftp tcp 21\n", argv[0]); + exit(EXIT_FAILURE); + } + if (strncmp("tcp", argv[3], strlen("tcp")) == 0) + l4proto = IPPROTO_TCP; + else if (strncmp("udp", argv[3], strlen("udp")) == 0) + l4proto = IPPROTO_UDP; + else { + fprintf(stderr, "%s not supported, send a patch to Pablo\n", + argv[3]); + exit(EXIT_FAILURE); + } + if (argc == 6) { + if (strncmp("dnat", argv[5], strlen("dnat")) == 0) { + type = TEST_DNAT; + printf("test dnat\n"); + } + } + + /* Initialization of supported layer 3 and 4 protocols here. */ + l2l3_ipv4_init(); + l4_tcp_init(); + l4_udp_init(); + + if (cthelper_test(argv[1], argv[2], l4proto, atoi(argv[4]), type) < 0) + ret = EXIT_FAILURE; + else + ret = EXIT_SUCCESS; + + printf("\e[1;34mTest results: expect_created=%d packets=%d " + "packets_skipped=%d\e[0m\n", + cthelper_test_stats.ct_expect_created, + cthelper_test_stats.pkts, + cthelper_test_stats.pkt_mismatch_proto + + cthelper_test_stats.pkt_mismatch_port); + + return ret; +} diff --git a/tests/conntrackd/cthelper/pcaps/nfsv3.pcap b/tests/conntrackd/cthelper/pcaps/nfsv3.pcap new file mode 100644 index 0000000..04606bd Binary files /dev/null and b/tests/conntrackd/cthelper/pcaps/nfsv3.pcap differ diff --git a/tests/conntrackd/cthelper/pcaps/oracle-tns-redirect.pcap b/tests/conntrackd/cthelper/pcaps/oracle-tns-redirect.pcap new file mode 100644 index 0000000..32f8952 Binary files /dev/null and b/tests/conntrackd/cthelper/pcaps/oracle-tns-redirect.pcap differ diff --git a/tests/conntrackd/cthelper/proto.c b/tests/conntrackd/cthelper/proto.c new file mode 100755 index 0000000..6a1f345 --- /dev/null +++ b/tests/conntrackd/cthelper/proto.c @@ -0,0 +1,49 @@ +#include +#include +#include + +#include "linux_list.h" +#include "proto.h" + +static LIST_HEAD(l2l3_helper_list); +static LIST_HEAD(l4_helper_list); + +struct cthelper_proto_l2l3_helper * +cthelper_proto_l2l3_helper_find(const uint8_t *pkt, + unsigned int *l4protonum, + unsigned int *l3hdr_len) +{ + const struct ethhdr *eh = (const struct ethhdr *)pkt; + struct cthelper_proto_l2l3_helper *cur; + + list_for_each_entry(cur, &l2l3_helper_list, head) { + if (ntohs(cur->l2protonum) == eh->h_proto) { + *l4protonum = cur->l4pkt_proto(pkt + ETH_HLEN); + *l3hdr_len = cur->l3pkt_hdr_len(pkt + ETH_HLEN); + return cur; + } + } + return NULL; +} + +void cthelper_proto_l2l3_helper_register(struct cthelper_proto_l2l3_helper *h) +{ + list_add(&h->head, &l2l3_helper_list); +} + +struct cthelper_proto_l4_helper * +cthelper_proto_l4_helper_find(const uint8_t *pkt, unsigned int l4protocol) +{ + struct cthelper_proto_l4_helper *cur; + + list_for_each_entry(cur, &l4_helper_list, head) { + if (cur->l4protonum == l4protocol) + return cur; + } + return NULL; +} + +void cthelper_proto_l4_helper_register(struct cthelper_proto_l4_helper *h) +{ + list_add(&h->head, &l4_helper_list); +} diff --git a/tests/conntrackd/cthelper/proto.h b/tests/conntrackd/cthelper/proto.h new file mode 100755 index 0000000..9e99eea --- /dev/null +++ b/tests/conntrackd/cthelper/proto.h @@ -0,0 +1,50 @@ +#ifndef _HELPER_H_ +#define _HELPER_H_ + +#include + +#include "../../../include/linux_list.h" + +struct nf_conntrack; + +struct cthelper_proto_l4_helper { + struct list_head head; + + unsigned int l4protonum; + + void (*l4ct_build)(const uint8_t *pkt, struct nf_conntrack *ct); + int (*l4ct_cmp_orig)(const uint8_t *pkt, struct nf_conntrack *ct); + int (*l4ct_cmp_repl)(const uint8_t *pkt, struct nf_conntrack *ct); + int (*l4ct_cmp_port)(struct nf_conntrack *ct, uint16_t port); + + int (*l4pkt_no_data)(const uint8_t *pkt); +}; + +struct cthelper_proto_l2l3_helper { + struct list_head head; + + unsigned int l2protonum; + unsigned int l2hdr_len; + + unsigned int l3protonum; + + void (*l3ct_build)(const uint8_t *pkt, struct nf_conntrack *ct); + int (*l3ct_cmp_orig)(const uint8_t *pkt, struct nf_conntrack *ct); + int (*l3ct_cmp_repl)(const uint8_t *pkt, struct nf_conntrack *ct); + + int (*l3pkt_hdr_len)(const uint8_t *pkt); + int (*l4pkt_proto)(const uint8_t *pkt); +}; + +struct cthelper_proto_l2l3_helper *cthelper_proto_l2l3_helper_find(const uint8_t *pkt, unsigned int *l4protonum, unsigned int *l3hdr_len); +void cthelper_proto_l2l3_helper_register(struct cthelper_proto_l2l3_helper *h); + +struct cthelper_proto_l4_helper *cthelper_proto_l4_helper_find(const uint8_t *pkt, unsigned int l4protonum); +void cthelper_proto_l4_helper_register(struct cthelper_proto_l4_helper *h); + +/* Initialization of supported protocols here. */ +void l2l3_ipv4_init(void); +void l4_tcp_init(void); +void l4_udp_init(void); + +#endif diff --git a/tests/conntrackd/cthelper/run-test.sh b/tests/conntrackd/cthelper/run-test.sh new file mode 100644 index 0000000..fe31602 --- /dev/null +++ b/tests/conntrackd/cthelper/run-test.sh @@ -0,0 +1,11 @@ +echo "Running test for oracle TNS port 1521" +./cthelper-test pcaps/oracle-tns-redirect.pcap tns tcp 1521 + +echo "Running test for oracle TNS port 1521" +./cthelper-test pcaps/oracle-tns-redirect.pcap tns tcp 1521 dnat + +echo "Running test for NFSv3 UDP port 111" +./cthelper-test pcaps/nfsv3.pcap rpc udp 111 + +echo "Running test for NFSv3 TCP port 111" +./cthelper-test pcaps/nfsv3.pcap rpc tcp 111 diff --git a/tests/conntrackd/cthelper/test.h b/tests/conntrackd/cthelper/test.h new file mode 100644 index 0000000..4f5a6b6 --- /dev/null +++ b/tests/conntrackd/cthelper/test.h @@ -0,0 +1,13 @@ +#ifndef _CTHELPER_TEST_H_ +#define _CTHELPER_TEST_H_ + +struct cthelper_test_stats { + int pkts; + int pkt_mismatch_proto; + int pkt_mismatch_port; + int ct_expect_created; +}; + +extern struct cthelper_test_stats cthelper_test_stats; + +#endif -- cgit v1.2.3