diff options
-rw-r--r-- | include/helper.h | 2 | ||||
-rw-r--r-- | src/expect.c | 4 | ||||
-rw-r--r-- | src/helpers/ftp.c | 2 | ||||
-rw-r--r-- | src/helpers/rpc.c | 2 | ||||
-rw-r--r-- | src/helpers/tns.c | 25 | ||||
-rwxr-xr-x | tests/conntrackd/cthelper/main.c | 61 | ||||
-rw-r--r-- | tests/conntrackd/cthelper/run-test.sh | 3 |
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 |