From 5e8f64f46cb1dd71b0a94cb7dad87da00b8c5e32 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 15 May 2012 01:51:29 +0200 Subject: conntrackd: add cthelper infrastructure (+ example FTP helper) This patch adds the user-space helper infrastructure. It also contains the implementation of the FTP helper in user-space. There's one example file that you can use to configure conntrackd as user-space connection tracking helper under: doc/helper/conntrackd.conf Signed-off-by: Pablo Neira Ayuso --- src/expect.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 src/expect.c (limited to 'src/expect.c') diff --git a/src/expect.c b/src/expect.c new file mode 100644 index 0000000..6069770 --- /dev/null +++ b/src/expect.c @@ -0,0 +1,214 @@ +/* + * (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 "helper.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, + uint32_t flags) +{ + 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); + nfexp_set_attr_u32(exp, ATTR_EXP_FLAGS, flags); + + nfct_destroy(expected); + nfct_destroy(mask); + + return 0; +} + +static int cthelper_expect_cmd(struct nf_expect *exp, int cmd) +{ + int ret; + struct nfct_handle *h; + + h = nfct_open(EXPECT, 0); + if (!h) + return -1; + + ret = nfexp_query(h, cmd, exp); + + nfct_close(h); + return ret; +} + +int cthelper_add_expect(struct nf_expect *exp) +{ + return cthelper_expect_cmd(exp, NFCT_Q_CREATE_UPDATE); +} + +int cthelper_del_expect(struct nf_expect *exp) +{ + return cthelper_expect_cmd(exp, NFCT_Q_DESTROY); +} + +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; + } +} -- cgit v1.2.3