summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2006-12-02 22:07:13 -0800
committerDavid S. Miller <davem@davemloft.net>2006-12-02 22:07:13 -0800
commit5b1158e909ecbe1a052203e0d8df15633f829930 (patch)
tree1d29320fd6184b982b1a8a83e7e1e9f25537d3ff /include
parentd2483ddefd38b06053cdce7206382ca61f6282b1 (diff)
downloadlinux-5b1158e909ecbe1a052203e0d8df15633f829930.tar.bz2
[NETFILTER]: Add NAT support for nf_conntrack
Add NAT support for nf_conntrack. Joint work of Jozsef Kadlecsik, Yasuyuki Kozakai, Martin Josefsson and myself. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/linux/netfilter.h2
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_ipv4.h20
-rw-r--r--include/net/netfilter/nf_conntrack.h29
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h2
-rw-r--r--include/net/netfilter/nf_nat.h77
-rw-r--r--include/net/netfilter/nf_nat_core.h27
-rw-r--r--include/net/netfilter/nf_nat_helper.h32
-rw-r--r--include/net/netfilter/nf_nat_protocol.h70
-rw-r--r--include/net/netfilter/nf_nat_rule.h35
9 files changed, 278 insertions, 16 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index f6f3fcbd70ed..d4c4c5120bc0 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -357,7 +357,7 @@ extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
static inline void
nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
{
-#ifdef CONFIG_IP_NF_NAT_NEEDED
+#if defined(CONFIG_IP_NF_NAT_NEEDED) || defined(CONFIG_NF_NAT_NEEDED)
void (*decodefn)(struct sk_buff *, struct flowi *);
if (family == AF_INET && (decodefn = ip_nat_decode_session) != NULL)
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 34b453a81a63..a1c57ee0a4fa 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -9,29 +9,23 @@
#ifndef _NF_CONNTRACK_IPV4_H
#define _NF_CONNTRACK_IPV4_H
-#ifdef CONFIG_IP_NF_NAT_NEEDED
-#include <linux/netfilter_ipv4/ip_nat.h>
+#ifdef CONFIG_NF_NAT_NEEDED
+#include <net/netfilter/nf_nat.h>
/* per conntrack: nat application helper private data */
-union ip_conntrack_nat_help {
+union nf_conntrack_nat_help {
/* insert nat helper private data here */
};
-struct nf_conntrack_ipv4_nat {
- struct ip_nat_info info;
- union ip_conntrack_nat_help help;
+struct nf_conn_nat {
+ struct nf_nat_info info;
+ union nf_conntrack_nat_help help;
#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
int masq_index;
#endif
};
-#endif /* CONFIG_IP_NF_NAT_NEEDED */
-
-struct nf_conntrack_ipv4 {
-#ifdef CONFIG_IP_NF_NAT_NEEDED
- struct nf_conntrack_ipv4_nat *nat;
-#endif
-};
+#endif /* CONFIG_NF_NAT_NEEDED */
/* Returns new sk_buff, or NULL */
struct sk_buff *
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index b4beb8c799e5..9948af068688 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -264,18 +264,45 @@ nf_conntrack_unregister_cache(u_int32_t features);
/* valid combinations:
* basic: nf_conn, nf_conn .. nf_conn_help
- * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat, nf_conn help
+ * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat .. nf_conn help
*/
+#ifdef CONFIG_NF_NAT_NEEDED
+static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
+{
+ unsigned int offset = sizeof(struct nf_conn);
+
+ if (!(ct->features & NF_CT_F_NAT))
+ return NULL;
+
+ offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
+ return (struct nf_conn_nat *) ((void *)ct + offset);
+}
+
static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
{
unsigned int offset = sizeof(struct nf_conn);
if (!(ct->features & NF_CT_F_HELP))
return NULL;
+ if (ct->features & NF_CT_F_NAT) {
+ offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
+ offset += sizeof(struct nf_conn_nat);
+ }
offset = ALIGN(offset, __alignof__(struct nf_conn_help));
return (struct nf_conn_help *) ((void *)ct + offset);
}
+#else /* No NAT */
+static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
+{
+ unsigned int offset = sizeof(struct nf_conn);
+
+ if (!(ct->features & NF_CT_F_HELP))
+ return NULL;
+ offset = ALIGN(offset, __alignof__(struct nf_conn_help));
+ return (struct nf_conn_help *) ((void *)ct + offset);
+}
+#endif /* CONFIG_NF_NAT_NEEDED */
#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_H */
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 5d853e826d1d..b969c430b36a 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -43,7 +43,7 @@ struct nf_conntrack_expect
#ifdef CONFIG_NF_NAT_NEEDED
/* This is the original per-proto part, used to map the
* expected connection the way the recipient expects. */
- union nf_conntrack_manip_proto saved_proto;
+ union nf_conntrack_man_proto saved_proto;
/* Direction relative to the master connection. */
enum ip_conntrack_dir dir;
#endif
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
new file mode 100644
index 000000000000..61c62068ca6b
--- /dev/null
+++ b/include/net/netfilter/nf_nat.h
@@ -0,0 +1,77 @@
+#ifndef _NF_NAT_H
+#define _NF_NAT_H
+#include <linux/netfilter_ipv4.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16
+
+enum nf_nat_manip_type
+{
+ IP_NAT_MANIP_SRC,
+ IP_NAT_MANIP_DST
+};
+
+/* SRC manip occurs POST_ROUTING or LOCAL_IN */
+#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING && (hooknum) != NF_IP_LOCAL_IN)
+
+#define IP_NAT_RANGE_MAP_IPS 1
+#define IP_NAT_RANGE_PROTO_SPECIFIED 2
+
+/* NAT sequence number modifications */
+struct nf_nat_seq {
+ /* position of the last TCP sequence number modification (if any) */
+ u_int32_t correction_pos;
+
+ /* sequence number offset before and after last modification */
+ int16_t offset_before, offset_after;
+};
+
+/* Single range specification. */
+struct nf_nat_range
+{
+ /* Set to OR of flags above. */
+ unsigned int flags;
+
+ /* Inclusive: network order. */
+ __be32 min_ip, max_ip;
+
+ /* Inclusive: network order */
+ union nf_conntrack_man_proto min, max;
+};
+
+/* For backwards compat: don't use in modern code. */
+struct nf_nat_multi_range_compat
+{
+ unsigned int rangesize; /* Must be 1. */
+
+ /* hangs off end. */
+ struct nf_nat_range range[1];
+};
+
+#ifdef __KERNEL__
+#include <linux/list.h>
+
+/* The structure embedded in the conntrack structure. */
+struct nf_nat_info
+{
+ struct list_head bysource;
+ struct nf_nat_seq seq[IP_CT_DIR_MAX];
+};
+
+struct nf_conn;
+
+/* Set up the info structure to map into this range. */
+extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
+ const struct nf_nat_range *range,
+ unsigned int hooknum);
+
+/* Is this tuple already taken? (not by us)*/
+extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack);
+
+extern int nf_nat_module_is_loaded;
+
+#else /* !__KERNEL__: iptables wants this to compile. */
+#define nf_nat_multi_range nf_nat_multi_range_compat
+#endif /*__KERNEL__*/
+#endif
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
new file mode 100644
index 000000000000..9778ffa93440
--- /dev/null
+++ b/include/net/netfilter/nf_nat_core.h
@@ -0,0 +1,27 @@
+#ifndef _NF_NAT_CORE_H
+#define _NF_NAT_CORE_H
+#include <linux/list.h>
+#include <net/netfilter/nf_conntrack.h>
+
+/* This header used to share core functionality between the standalone
+ NAT module, and the compatibility layer's use of NAT for masquerading. */
+
+extern unsigned int nf_nat_packet(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum,
+ struct sk_buff **pskb);
+
+extern int nf_nat_icmp_reply_translation(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum,
+ struct sk_buff **pskb);
+
+static inline int nf_nat_initialized(struct nf_conn *ct,
+ enum nf_nat_manip_type manip)
+{
+ if (manip == IP_NAT_MANIP_SRC)
+ return test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status);
+ else
+ return test_bit(IPS_DST_NAT_DONE_BIT, &ct->status);
+}
+#endif /* _NF_NAT_CORE_H */
diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h
new file mode 100644
index 000000000000..ec98ecf95fc8
--- /dev/null
+++ b/include/net/netfilter/nf_nat_helper.h
@@ -0,0 +1,32 @@
+#ifndef _NF_NAT_HELPER_H
+#define _NF_NAT_HELPER_H
+/* NAT protocol helper routines. */
+
+#include <net/netfilter/nf_conntrack.h>
+
+struct sk_buff;
+
+/* These return true or false. */
+extern int nf_nat_mangle_tcp_packet(struct sk_buff **skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len);
+extern int nf_nat_mangle_udp_packet(struct sk_buff **skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len);
+extern int nf_nat_seq_adjust(struct sk_buff **pskb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo);
+
+/* Setup NAT on this expected conntrack so it follows master, but goes
+ * to port ct->master->saved_proto. */
+extern void nf_nat_follow_master(struct nf_conn *ct,
+ struct nf_conntrack_expect *this);
+#endif
diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h
new file mode 100644
index 000000000000..a9ec5ef61468
--- /dev/null
+++ b/include/net/netfilter/nf_nat_protocol.h
@@ -0,0 +1,70 @@
+/* Header for use in defining a given protocol. */
+#ifndef _NF_NAT_PROTOCOL_H
+#define _NF_NAT_PROTOCOL_H
+#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+struct nf_nat_range;
+
+struct nf_nat_protocol
+{
+ /* Protocol name */
+ const char *name;
+
+ /* Protocol number. */
+ unsigned int protonum;
+
+ struct module *me;
+
+ /* Translate a packet to the target according to manip type.
+ Return true if succeeded. */
+ int (*manip_pkt)(struct sk_buff **pskb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype);
+
+ /* Is the manipable part of the tuple between min and max incl? */
+ int (*in_range)(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max);
+
+ /* Alter the per-proto part of the tuple (depending on
+ maniptype), to give a unique tuple in the given range if
+ possible; return false if not. Per-protocol part of tuple
+ is initialized to the incoming packet. */
+ int (*unique_tuple)(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct);
+
+ int (*range_to_nfattr)(struct sk_buff *skb,
+ const struct nf_nat_range *range);
+
+ int (*nfattr_to_range)(struct nfattr *tb[],
+ struct nf_nat_range *range);
+};
+
+/* Protocol registration. */
+extern int nf_nat_protocol_register(struct nf_nat_protocol *proto);
+extern void nf_nat_protocol_unregister(struct nf_nat_protocol *proto);
+
+extern struct nf_nat_protocol *nf_nat_proto_find_get(u_int8_t protocol);
+extern void nf_nat_proto_put(struct nf_nat_protocol *proto);
+
+/* Built-in protocols. */
+extern struct nf_nat_protocol nf_nat_protocol_tcp;
+extern struct nf_nat_protocol nf_nat_protocol_udp;
+extern struct nf_nat_protocol nf_nat_protocol_icmp;
+extern struct nf_nat_protocol nf_nat_unknown_protocol;
+
+extern int init_protocols(void) __init;
+extern void cleanup_protocols(void);
+extern struct nf_nat_protocol *find_nat_proto(u_int16_t protonum);
+
+extern int nf_nat_port_range_to_nfattr(struct sk_buff *skb,
+ const struct nf_nat_range *range);
+extern int nf_nat_port_nfattr_to_range(struct nfattr *tb[],
+ struct nf_nat_range *range);
+
+#endif /*_NF_NAT_PROTO_H*/
diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h
new file mode 100644
index 000000000000..f191c672bcc6
--- /dev/null
+++ b/include/net/netfilter/nf_nat_rule.h
@@ -0,0 +1,35 @@
+#ifndef _NF_NAT_RULE_H
+#define _NF_NAT_RULE_H
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+/* Compatibility definitions for ipt_FOO modules */
+#define ip_nat_range nf_nat_range
+#define ip_conntrack_tuple nf_conntrack_tuple
+#define ip_conntrack_get nf_ct_get
+#define ip_conntrack nf_conn
+#define ip_nat_setup_info nf_nat_setup_info
+#define ip_nat_multi_range_compat nf_nat_multi_range_compat
+#define ip_ct_iterate_cleanup nf_ct_iterate_cleanup
+#define IP_NF_ASSERT NF_CT_ASSERT
+
+extern int nf_nat_rule_init(void) __init;
+extern void nf_nat_rule_cleanup(void);
+extern int nf_nat_rule_find(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_conn *ct,
+ struct nf_nat_info *info);
+
+extern unsigned int
+alloc_null_binding(struct nf_conn *ct,
+ struct nf_nat_info *info,
+ unsigned int hooknum);
+
+extern unsigned int
+alloc_null_binding_confirmed(struct nf_conn *ct,
+ struct nf_nat_info *info,
+ unsigned int hooknum);
+#endif /* _NF_NAT_RULE_H */