summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/helper.h2
-rw-r--r--src/expect.c4
-rw-r--r--src/helpers/ftp.c2
-rw-r--r--src/helpers/rpc.c2
-rw-r--r--src/helpers/tns.c25
-rwxr-xr-xtests/conntrackd/cthelper/main.c61
-rw-r--r--tests/conntrackd/cthelper/run-test.sh3
7 files changed, 80 insertions, 19 deletions
diff --git a/include/helper.h b/include/helper.h
index ce5ae9b..02ff3df 100644
--- a/include/helper.h
+++ b/include/helper.h
@@ -41,7 +41,7 @@ struct ctd_helper_instance {
struct ctd_helper_policy policy[CTD_HELPER_POLICY_MAX];
};
-extern 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);
+extern 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, uint32_t flags);
extern int cthelper_add_expect(struct nf_expect *exp);
extern int cthelper_del_expect(struct nf_expect *exp);
diff --git a/src/expect.c b/src/expect.c
index eab9094..94c26bc 100644
--- a/src/expect.c
+++ b/src/expect.c
@@ -24,7 +24,8 @@ 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)
+ uint8_t l4proto, uint16_t *sport, uint16_t *dport,
+ uint32_t flags)
{
struct nf_conntrack *expected, *mask;
@@ -151,6 +152,7 @@ cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master,
nfexp_set_attr(exp, ATTR_EXP_MASTER, master);
nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected);
nfexp_set_attr(exp, ATTR_EXP_MASK, mask);
+ nfexp_set_attr_u32(exp, ATTR_EXP_FLAGS, flags);
nfct_destroy(expected);
nfct_destroy(mask);
diff --git a/src/helpers/ftp.c b/src/helpers/ftp.c
index 2772199..962020b 100644
--- a/src/helpers/ftp.c
+++ b/src/helpers/ftp.c
@@ -544,7 +544,7 @@ ftp_helper_cb(struct pkt_buff *pkt, uint32_t protoff,
cthelper_get_addr_src(myct->ct, !dir, &addr);
if (cthelper_expect_init(exp, myct->ct, 0, &addr, &daddr, IPPROTO_TCP,
- NULL, &cmd.u.port)) {
+ NULL, &cmd.u.port, 0)) {
pr_debug("conntrack_ftp: failed to init expectation\n");
goto out_update_nl;
}
diff --git a/src/helpers/rpc.c b/src/helpers/rpc.c
index 97c1b35..82493c2 100644
--- a/src/helpers/rpc.c
+++ b/src/helpers/rpc.c
@@ -423,7 +423,7 @@ rpc_helper_cb(struct pkt_buff *pkt, uint32_t protoff,
if (cthelper_expect_init(exp, myct->ct, 0, &addr, &daddr,
rpc_info->pm_prot,
- NULL, &port)) {
+ NULL, &port, NF_CT_EXPECT_PERMANENT)) {
pr_debug("RPC: failed to init expectation\n");
goto out_exp;
}
diff --git a/src/helpers/tns.c b/src/helpers/tns.c
index c4bfb91..5833fea 100644
--- a/src/helpers/tns.c
+++ b/src/helpers/tns.c
@@ -132,9 +132,9 @@ find_pattern(struct pkt_buff *pkt, unsigned int dataoff, size_t dlen,
{
const char *data = (const char *)pktb_network_header(pkt) + dataoff
+ sizeof(struct tns_header);
- int length, offset;
+ int length, offset, ret;
uint32_t array[4];
- const char *p;
+ const char *p, *start;
p = strstr(data, "(");
if (!p)
@@ -146,8 +146,9 @@ find_pattern(struct pkt_buff *pkt, unsigned int dataoff, size_t dlen,
return 0;
}
+ start = p + strlen("HOST=");
offset = (int)(p - data) + strlen("HOST=");
- *numoff = offset;
+ *numoff = offset + sizeof(struct tns_header);
data += offset;
length = try_number(data, dlen - offset, array, 4, '.', ')');
@@ -168,7 +169,12 @@ find_pattern(struct pkt_buff *pkt, unsigned int dataoff, size_t dlen,
}
p += strlen("PORT=");
- return get_port(p, dlen - offset - length, ')', cmd);
+ ret = get_port(p, dlen - offset - length, ')', cmd);
+ if (ret == 0)
+ return 0;
+
+ p += ret;
+ return (int)(p - start);
}
static inline uint16_t
@@ -238,7 +244,11 @@ nf_nat_tns(struct pkt_buff *pkt, struct tns_header *tns, struct nf_expect *exp,
return NF_DROP;
buflen = snprintf(buffer, sizeof(buffer),
- "%pI4)(PORT=%u)", &newip.ip, port);
+ "%u.%u.%u.%u)(PORT=%u)",
+ ((unsigned char *)&newip.ip)[0],
+ ((unsigned char *)&newip.ip)[1],
+ ((unsigned char *)&newip.ip)[2],
+ ((unsigned char *)&newip.ip)[3], port);
if (!buflen)
goto out;
@@ -346,7 +356,7 @@ parse:
if (cthelper_expect_init(exp, myct->ct, 0,
&addr, &cmd.u3,
IPPROTO_TCP,
- NULL, &cmd.u.port)) {
+ NULL, &cmd.u.port, 0)) {
pr_debug("TNS: failed to init expectation\n");
goto out_exp;
}
@@ -355,7 +365,8 @@ parse:
* (possibly changed) expectation itself.
*/
if (nfct_get_attr_u32(myct->ct, ATTR_STATUS) & IPS_NAT_MASK) {
- ret = nf_nat_tns(pkt, tns, exp, myct->ct, dir, numoff, numlen);
+ ret = nf_nat_tns(pkt, tns, exp, myct->ct, dir,
+ numoff + sizeof(struct tns_header), numlen);
goto out_exp;
}
diff --git a/tests/conntrackd/cthelper/main.c b/tests/conntrackd/cthelper/main.c
index 695054a..f229c5d 100755
--- a/tests/conntrackd/cthelper/main.c
+++ b/tests/conntrackd/cthelper/main.c
@@ -2,6 +2,7 @@
#include <pcap.h>
#include <stdlib.h>
#include <stdint.h>
+#include <stdbool.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
@@ -16,9 +17,15 @@
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)
+ struct ctd_helper *h, int proto, uint16_t port,
+ int type)
{
struct pkt_buff *pktb;
struct cthelper_proto_l2l3_helper *l3h;
@@ -94,7 +101,37 @@ cthelper_process_packet(const uint8_t *pkt, uint32_t pktlen,
return -1;
}
- ret = h->cb(pktb, dataoff, ct->myct, ctinfo);
+ /* 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;
@@ -102,7 +139,7 @@ cthelper_process_packet(const uint8_t *pkt, uint32_t pktlen,
static int
cthelper_test(const char *pcapfile, const char *helper_name,
- int l4proto, uint16_t port)
+ int l4proto, uint16_t port, int type)
{
struct pcap_pkthdr pcaph;
char errbuf[PCAP_ERRBUF_SIZE];
@@ -125,7 +162,8 @@ cthelper_test(const char *pcapfile, const char *helper_name,
}
while ((pkt = pcap_next(handle, &pcaph)) != NULL) {
cthelper_test_stats.pkts++;
- cthelper_process_packet(pkt, pcaph.caplen, h, l4proto, port);
+ cthelper_process_packet(pkt, pcaph.caplen, h, l4proto, port,
+ type);
}
ct_flush();
@@ -135,11 +173,12 @@ cthelper_test(const char *pcapfile, const char *helper_name,
int main(int argc, char *argv[])
{
- int ret, l4proto;
+ int ret, l4proto, type = TEST_NORMAL;
- if (argc != 5) {
+ if (argc < 5 || argc > 6) {
fprintf(stderr, "Wrong usage:\n");
- fprintf(stderr, "%s [pcap_file] [helper-name] [proto] [port]\n",
+ fprintf(stderr, "%s <pcap_file> <helper-name> <proto> "
+ "<port> [dnat]\n",
argv[0]);
fprintf(stderr, "example: %s file.pcap ftp tcp 21\n", argv[0]);
exit(EXIT_FAILURE);
@@ -153,13 +192,19 @@ int main(int argc, char *argv[])
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])) < 0)
+ if (cthelper_test(argv[1], argv[2], l4proto, atoi(argv[4]), type) < 0)
ret = EXIT_FAILURE;
else
ret = EXIT_SUCCESS;
diff --git a/tests/conntrackd/cthelper/run-test.sh b/tests/conntrackd/cthelper/run-test.sh
index ccce3ac..fe31602 100644
--- a/tests/conntrackd/cthelper/run-test.sh
+++ b/tests/conntrackd/cthelper/run-test.sh
@@ -1,6 +1,9 @@
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