summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-05-15 01:51:29 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2012-08-01 19:20:06 +0200
commit5e8f64f46cb1dd71b0a94cb7dad87da00b8c5e32 (patch)
tree49a4e4123ca5be197a2f33ce87289db9d7af5880 /include
parent5a0d0ecf30fb1686cfb10aaa852fee9c8ed4360a (diff)
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 <pablo@netfilter.org>
Diffstat (limited to 'include')
-rw-r--r--include/Makefile.am3
-rw-r--r--include/conntrackd.h21
-rw-r--r--include/helper.h104
-rw-r--r--include/linux/netfilter/Makefile.am2
-rw-r--r--include/linux/netfilter/nfnetlink_cthelper.h55
-rw-r--r--include/linux/netfilter/nfnetlink_queue.h99
-rw-r--r--include/myct.h43
-rw-r--r--include/nfct.h10
-rw-r--r--include/stack.h28
9 files changed, 361 insertions, 4 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
index 138005d..6bd0f7f 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -5,5 +5,6 @@ noinst_HEADERS = alarm.h jhash.h cache.h linux_list.h linux_rbtree.h \
debug.h log.h hash.h mcast.h conntrack.h \
network.h filter.h queue.h vector.h cidr.h \
traffic_stats.h netlink.h fds.h event.h bitops.h channel.h \
- process.h origin.h internal.h external.h date.h nfct.h
+ process.h origin.h internal.h external.h date.h nfct.h \
+ helper.h myct.h stack.h
diff --git a/include/conntrackd.h b/include/conntrackd.h
index ec720ec..19e613c 100644
--- a/include/conntrackd.h
+++ b/include/conntrackd.h
@@ -69,6 +69,7 @@
#define CTD_SYNC_NOTRACK (1UL << 4)
#define CTD_POLL (1UL << 5)
#define CTD_EXPECT (1UL << 6)
+#define CTD_HELPER (1UL << 7)
/* FILENAME_MAX is 4096 on my system, perhaps too much? */
#ifndef FILENAME_MAXLEN
@@ -134,6 +135,9 @@ struct ct_conf {
int syslog_facility;
size_t buffer_size;
} stats;
+ struct {
+ struct list_head list;
+ } cthelper;
};
#define STATE(x) st.x
@@ -252,13 +256,21 @@ struct ct_stats_state {
struct cache *cache; /* internal events cache (netlink) */
};
-union ct_state {
+#define STATE_CTH(x) state.cthelper->x
+
+struct ct_helper_state {
+ struct mnl_socket *nl;
+ uint32_t portid;
+};
+
+struct ct_state {
struct ct_sync_state *sync;
struct ct_stats_state *stats;
+ struct ct_helper_state *cthelper;
};
extern struct ct_conf conf;
-extern union ct_state state;
+extern struct ct_state state;
extern struct ct_general_state st;
struct ct_mode {
@@ -273,6 +285,11 @@ void ctnl_kill(void);
int ctnl_local(int fd, int type, void *data);
int ctnl_init(void);
+/* basic cthelper functions */
+void cthelper_kill(void);
+int cthelper_local(int fd, int type, void *data);
+int cthelper_init(void);
+
/* conntrackd ctnl modes */
extern struct ct_mode sync_mode;
extern struct ct_mode stats_mode;
diff --git a/include/helper.h b/include/helper.h
new file mode 100644
index 0000000..02ff3df
--- /dev/null
+++ b/include/helper.h
@@ -0,0 +1,104 @@
+#ifndef _CTD_HELPER_H_
+#define _CTD_HELPER_H_
+
+#include <stdint.h>
+#include "linux_list.h"
+#include "myct.h"
+
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+
+struct pkt_buff;
+
+#define CTD_HELPER_NAME_LEN 16
+#define CTD_HELPER_POLICY_MAX 4
+
+struct ctd_helper_policy {
+ char name[CTD_HELPER_NAME_LEN];
+ uint32_t expect_timeout;
+ uint32_t expect_max;
+};
+
+struct ctd_helper {
+ struct list_head head;
+ char name[CTD_HELPER_NAME_LEN];
+ uint8_t l4proto;
+ int (*cb)(struct pkt_buff *pkt,
+ uint32_t protoff,
+ struct myct *ct,
+ u_int32_t ctinfo);
+
+ struct ctd_helper_policy policy[CTD_HELPER_POLICY_MAX];
+
+ int priv_data_len;
+};
+
+struct ctd_helper_instance {
+ struct list_head head;
+ uint32_t queue_num;
+ uint16_t l3proto;
+ uint8_t l4proto;
+ struct ctd_helper *helper;
+ 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, uint32_t flags);
+extern int cthelper_add_expect(struct nf_expect *exp);
+extern int cthelper_del_expect(struct nf_expect *exp);
+
+extern void cthelper_get_addr_src(struct nf_conntrack *ct, int dir, union nfct_attr_grp_addr *addr);
+extern void cthelper_get_addr_dst(struct nf_conntrack *ct, int dir, union nfct_attr_grp_addr *addr);
+
+extern int in4_pton(const char *src, int srclen, uint8_t *dst, int delim, const char **end);
+extern int in6_pton(const char *src, int srclen, uint8_t *dst, int delim, const char **end);
+
+extern void helper_register(struct ctd_helper *helper);
+struct ctd_helper *helper_find(const char *libdir_path, const char *name, uint8_t l4proto, int flags);
+
+#define min_t(type, x, y) ({ \
+ type __min1 = (x); \
+ type __min2 = (y); \
+ __min1 < __min2 ? __min1: __min2; })
+
+#define max_t(type, x, y) ({ \
+ type __max1 = (x); \
+ type __max2 = (y); \
+ __max1 > __max2 ? __max1: __max2; })
+
+#define ARRAY_SIZE MNL_ARRAY_SIZE
+
+enum ip_conntrack_dir {
+ IP_CT_DIR_ORIGINAL,
+ IP_CT_DIR_REPLY,
+ IP_CT_DIR_MAX
+};
+
+/* Connection state tracking for netfilter. This is separated from,
+ but required by, the NAT layer; it can also be used by an iptables
+ extension. */
+enum ip_conntrack_info {
+ /* Part of an established connection (either direction). */
+ IP_CT_ESTABLISHED,
+
+ /* Like NEW, but related to an existing connection, or ICMP error
+ (in either direction). */
+ IP_CT_RELATED,
+
+ /* Started a new connection to track (only
+ IP_CT_DIR_ORIGINAL); may be a retransmission. */
+ IP_CT_NEW,
+
+ /* >= this indicates reply direction */
+ IP_CT_IS_REPLY,
+
+ IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY,
+ IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY,
+ IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY,
+ /* Number of distinct IP_CT types (no NEW in reply dirn). */
+ IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1
+};
+
+#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
+
+#define pr_debug printf
+
+#endif
diff --git a/include/linux/netfilter/Makefile.am b/include/linux/netfilter/Makefile.am
index 84315e3..6574060 100644
--- a/include/linux/netfilter/Makefile.am
+++ b/include/linux/netfilter/Makefile.am
@@ -1 +1 @@
-noinst_HEADERS = nfnetlink.h nfnetlink_cttimeout.h
+noinst_HEADERS = nfnetlink.h nfnetlink_cttimeout.h nfnetlink_queue.h nfnetlink_cthelper.h
diff --git a/include/linux/netfilter/nfnetlink_cthelper.h b/include/linux/netfilter/nfnetlink_cthelper.h
new file mode 100644
index 0000000..33659f6
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_cthelper.h
@@ -0,0 +1,55 @@
+#ifndef _NFNL_CTHELPER_H_
+#define _NFNL_CTHELPER_H_
+
+#define NFCT_HELPER_STATUS_DISABLED 0
+#define NFCT_HELPER_STATUS_ENABLED 1
+
+enum nfnl_acct_msg_types {
+ NFNL_MSG_CTHELPER_NEW,
+ NFNL_MSG_CTHELPER_GET,
+ NFNL_MSG_CTHELPER_DEL,
+ NFNL_MSG_CTHELPER_MAX
+};
+
+enum nfnl_cthelper_type {
+ NFCTH_UNSPEC,
+ NFCTH_NAME,
+ NFCTH_TUPLE,
+ NFCTH_QUEUE_NUM,
+ NFCTH_POLICY,
+ NFCTH_PRIV_DATA_LEN,
+ NFCTH_STATUS,
+ __NFCTH_MAX
+};
+#define NFCTH_MAX (__NFCTH_MAX - 1)
+
+enum nfnl_cthelper_policy_type {
+ NFCTH_POLICY_SET_UNSPEC,
+ NFCTH_POLICY_SET_NUM,
+ NFCTH_POLICY_SET,
+ NFCTH_POLICY_SET1 = NFCTH_POLICY_SET,
+ NFCTH_POLICY_SET2,
+ NFCTH_POLICY_SET3,
+ NFCTH_POLICY_SET4,
+ __NFCTH_POLICY_SET_MAX
+};
+#define NFCTH_POLICY_SET_MAX (__NFCTH_POLICY_SET_MAX - 1)
+
+enum nfnl_cthelper_pol_type {
+ NFCTH_POLICY_UNSPEC,
+ NFCTH_POLICY_NAME,
+ NFCTH_POLICY_EXPECT_MAX,
+ NFCTH_POLICY_EXPECT_TIMEOUT,
+ __NFCTH_POLICY_MAX
+};
+#define NFCTH_POLICY_MAX (__NFCTH_POLICY_MAX - 1)
+
+enum nfnl_cthelper_tuple_type {
+ NFCTH_TUPLE_UNSPEC,
+ NFCTH_TUPLE_L3PROTONUM,
+ NFCTH_TUPLE_L4PROTONUM,
+ __NFCTH_TUPLE_MAX,
+};
+#define NFCTH_TUPLE_MAX (__NFCTH_TUPLE_MAX - 1)
+
+#endif /* _NFNL_CTHELPER_H */
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
new file mode 100644
index 0000000..e0d8fd8
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -0,0 +1,99 @@
+#ifndef _NFNETLINK_QUEUE_H
+#define _NFNETLINK_QUEUE_H
+
+#include <linux/types.h>
+#include <linux/netfilter/nfnetlink.h>
+
+enum nfqnl_msg_types {
+ NFQNL_MSG_PACKET, /* packet from kernel to userspace */
+ NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */
+ NFQNL_MSG_CONFIG, /* connect to a particular queue */
+ NFQNL_MSG_VERDICT_BATCH, /* batchv from userspace to kernel */
+
+ NFQNL_MSG_MAX
+};
+
+struct nfqnl_msg_packet_hdr {
+ __be32 packet_id; /* unique ID of packet in queue */
+ __be16 hw_protocol; /* hw protocol (network order) */
+ __u8 hook; /* netfilter hook */
+} __attribute__ ((packed));
+
+struct nfqnl_msg_packet_hw {
+ __be16 hw_addrlen;
+ __u16 _pad;
+ __u8 hw_addr[8];
+};
+
+struct nfqnl_msg_packet_timestamp {
+ __aligned_be64 sec;
+ __aligned_be64 usec;
+};
+
+enum nfqnl_attr_type {
+ NFQA_UNSPEC,
+ NFQA_PACKET_HDR,
+ NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */
+ NFQA_MARK, /* __u32 nfmark */
+ NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */
+ NFQA_IFINDEX_INDEV, /* __u32 ifindex */
+ NFQA_IFINDEX_OUTDEV, /* __u32 ifindex */
+ NFQA_IFINDEX_PHYSINDEV, /* __u32 ifindex */
+ NFQA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */
+ NFQA_HWADDR, /* nfqnl_msg_packet_hw */
+ NFQA_PAYLOAD, /* opaque data payload */
+ NFQA_CT, /* nf_conntrack_netlink.h */
+ NFQA_CT_INFO, /* enum ip_conntrack_info */
+
+ __NFQA_MAX
+};
+#define NFQA_MAX (__NFQA_MAX - 1)
+
+struct nfqnl_msg_verdict_hdr {
+ __be32 verdict;
+ __be32 id;
+};
+
+
+enum nfqnl_msg_config_cmds {
+ NFQNL_CFG_CMD_NONE,
+ NFQNL_CFG_CMD_BIND,
+ NFQNL_CFG_CMD_UNBIND,
+ NFQNL_CFG_CMD_PF_BIND,
+ NFQNL_CFG_CMD_PF_UNBIND,
+};
+
+struct nfqnl_msg_config_cmd {
+ __u8 command; /* nfqnl_msg_config_cmds */
+ __u8 _pad;
+ __be16 pf; /* AF_xxx for PF_[UN]BIND */
+};
+
+enum nfqnl_config_mode {
+ NFQNL_COPY_NONE,
+ NFQNL_COPY_META,
+ NFQNL_COPY_PACKET,
+};
+
+struct nfqnl_msg_config_params {
+ __be32 copy_range;
+ __u8 copy_mode; /* enum nfqnl_config_mode */
+} __attribute__ ((packed));
+
+
+enum nfqnl_attr_config {
+ NFQA_CFG_UNSPEC,
+ NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */
+ NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */
+ NFQA_CFG_QUEUE_MAXLEN, /* __u32 */
+ NFQA_CFG_MASK, /* identify which flags to change */
+ NFQA_CFG_FLAGS, /* value of these flags (__u32) */
+ __NFQA_CFG_MAX
+};
+#define NFQA_CFG_MAX (__NFQA_CFG_MAX-1)
+
+/* Flags for NFQA_CFG_FLAGS */
+#define NFQA_CFG_F_FAIL_OPEN (1 << 0)
+#define NFQA_CFG_F_CONNTRACK (1 << 1)
+
+#endif /* _NFNETLINK_QUEUE_H */
diff --git a/include/myct.h b/include/myct.h
new file mode 100644
index 0000000..45d9f29
--- /dev/null
+++ b/include/myct.h
@@ -0,0 +1,43 @@
+#ifndef _MYCT_H_
+#define _MYCT_H_
+
+#include "linux_list.h"
+
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+
+struct nf_conntrack;
+
+enum {
+ MYCT_NONE = 0,
+ MYCT_ESTABLISHED = (1 << 0),
+};
+
+enum {
+ MYCT_DIR_ORIG = 0,
+ MYCT_DIR_REPL,
+ MYCT_DIR_MAX,
+};
+
+union myct_proto {
+ uint16_t port;
+ uint16_t all;
+};
+
+struct myct_man {
+ union nfct_attr_grp_addr u3;
+ union myct_proto u;
+ uint16_t l3num;
+ uint8_t protonum;
+};
+
+struct myct_tuple {
+ struct myct_man src;
+ struct myct_man dst;
+};
+
+struct myct {
+ struct nf_conntrack *ct;
+ void *priv_data;
+};
+
+#endif
diff --git a/include/nfct.h b/include/nfct.h
index d6271cf..5548b03 100644
--- a/include/nfct.h
+++ b/include/nfct.h
@@ -4,6 +4,7 @@
enum {
NFCT_SUBSYS_NONE = 0,
NFCT_SUBSYS_TIMEOUT,
+ NFCT_SUBSYS_HELPER,
NFCT_SUBSYS_VERSION,
NFCT_SUBSYS_HELP,
};
@@ -15,6 +16,7 @@ enum {
NFCT_CMD_DELETE,
NFCT_CMD_GET,
NFCT_CMD_FLUSH,
+ NFCT_CMD_DISABLE,
};
void nfct_perror(const char *msg);
@@ -26,4 +28,12 @@ int nfct_cmd_timeout_delete(int argc, char *argv[]);
int nfct_cmd_timeout_get(int argc, char *argv[]);
int nfct_cmd_timeout_flush(int argc, char *argv[]);
+int nfct_cmd_helper_parse_params(int argc, char *argv[]);
+int nfct_cmd_helper_list(int argc, char *argv[]);
+int nfct_cmd_helper_add(int argc, char *argv[]);
+int nfct_cmd_helper_delete(int argc, char *argv[]);
+int nfct_cmd_helper_get(int argc, char *argv[]);
+int nfct_cmd_helper_flush(int argc, char *argv[]);
+int nfct_cmd_helper_disable(int argc, char *argv[]);
+
#endif
diff --git a/include/stack.h b/include/stack.h
new file mode 100644
index 0000000..512a30f
--- /dev/null
+++ b/include/stack.h
@@ -0,0 +1,28 @@
+#ifndef _STACK_H_
+#define _STACK_H_
+
+#include "linux_list.h"
+
+struct stack {
+ struct list_head list;
+ int items;
+};
+
+static inline void stack_init(struct stack *s)
+{
+ INIT_LIST_HEAD(&s->list);
+}
+
+struct stack_item {
+ struct list_head head;
+ int type;
+ int data_len;
+ char data[0];
+};
+
+struct stack_item *stack_item_alloc(int type, size_t data_len);
+void stack_item_free(struct stack_item *e);
+void stack_item_push(struct stack *s, struct stack_item *e);
+struct stack_item *stack_item_pop(struct stack *s, int type);
+
+#endif