Skip to content

Commit

Permalink
[NETFILTER]: Add NAT support for nf_conntrack
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jozsef Kadlecsik authored and davem330 committed Dec 3, 2006
1 parent d2483dd commit 5b1158e
Show file tree
Hide file tree
Showing 29 changed files with 2,667 additions and 59 deletions.
2 changes: 1 addition & 1 deletion include/linux/netfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
20 changes: 7 additions & 13 deletions include/net/netfilter/ipv4/nf_conntrack_ipv4.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand Down
29 changes: 28 additions & 1 deletion include/net/netfilter/nf_conntrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
2 changes: 1 addition & 1 deletion include/net/netfilter/nf_conntrack_expect.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
77 changes: 77 additions & 0 deletions include/net/netfilter/nf_nat.h
Original file line number Diff line number Diff line change
@@ -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
27 changes: 27 additions & 0 deletions include/net/netfilter/nf_nat_core.h
Original file line number Diff line number Diff line change
@@ -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 */
32 changes: 32 additions & 0 deletions include/net/netfilter/nf_nat_helper.h
Original file line number Diff line number Diff line change
@@ -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
70 changes: 70 additions & 0 deletions include/net/netfilter/nf_nat_protocol.h
Original file line number Diff line number Diff line change
@@ -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*/
35 changes: 35 additions & 0 deletions include/net/netfilter/nf_nat_rule.h
Original file line number Diff line number Diff line change
@@ -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 */
Loading

0 comments on commit 5b1158e

Please sign in to comment.