Skip to content

Commit

Permalink
netfilter: add protocol independent NAT core
Browse files Browse the repository at this point in the history
Convert the IPv4 NAT implementation to a protocol independent core and
address family specific modules.

Signed-off-by: Patrick McHardy <kaber@trash.net>
  • Loading branch information
Patrick McHardy authored and Pablo Neira Ayuso committed Aug 30, 2012
1 parent 051966c commit c7232c9
Show file tree
Hide file tree
Showing 49 changed files with 1,495 additions and 1,140 deletions.
14 changes: 6 additions & 8 deletions include/linux/netfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,21 +342,19 @@ extern int nf_register_afinfo(const struct nf_afinfo *afinfo);
extern void nf_unregister_afinfo(const struct nf_afinfo *afinfo);

#include <net/flow.h>
extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
extern void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);

static inline void
nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
{
#ifdef CONFIG_NF_NAT_NEEDED
void (*decodefn)(struct sk_buff *, struct flowi *);

if (family == AF_INET) {
rcu_read_lock();
decodefn = rcu_dereference(ip_nat_decode_session);
if (decodefn)
decodefn(skb, fl);
rcu_read_unlock();
}
rcu_read_lock();
decodefn = rcu_dereference(nf_nat_decode_session_hook);
if (decodefn)
decodefn(skb, fl);
rcu_read_unlock();
#endif
}

Expand Down
8 changes: 8 additions & 0 deletions include/linux/netfilter/nf_nat.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ struct nf_nat_ipv4_multi_range_compat {
struct nf_nat_ipv4_range range[1];
};

struct nf_nat_range {
unsigned int flags;
union nf_inet_addr min_addr;
union nf_inet_addr max_addr;
union nf_conntrack_man_proto min_proto;
union nf_conntrack_man_proto max_proto;
};

#endif /* _NETFILTER_NF_NAT_H */
6 changes: 4 additions & 2 deletions include/linux/netfilter/nfnetlink_conntrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ enum ctattr_tstamp {

enum ctattr_nat {
CTA_NAT_UNSPEC,
CTA_NAT_MINIP,
CTA_NAT_MAXIP,
CTA_NAT_V4_MINIP,
#define CTA_NAT_MINIP CTA_NAT_V4_MINIP
CTA_NAT_V4_MAXIP,
#define CTA_NAT_MAXIP CTA_NAT_V4_MAXIP
CTA_NAT_PROTO,
__CTA_NAT_MAX
};
Expand Down
1 change: 0 additions & 1 deletion include/linux/netfilter_ipv4.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ enum nf_ip_hook_priorities {

#ifdef __KERNEL__
extern int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type);
extern int ip_xfrm_me_harder(struct sk_buff *skb);
extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol);
#endif /*__KERNEL__*/
Expand Down
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 {
unsigned int class;

#ifdef CONFIG_NF_NAT_NEEDED
__be32 saved_ip;
union nf_inet_addr saved_addr;
/* This is the original per-proto part, used to map the
* expected connection the way the recipient expects. */
union nf_conntrack_man_proto saved_proto;
Expand Down
2 changes: 1 addition & 1 deletion include/net/netfilter/nf_nat.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ struct nf_conn_nat {

/* 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_ipv4_range *range,
const struct nf_nat_range *range,
enum nf_nat_manip_type maniptype);

/* Is this tuple already taken? (not by us)*/
Expand Down
5 changes: 1 addition & 4 deletions include/net/netfilter/nf_nat_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ extern unsigned int nf_nat_packet(struct nf_conn *ct,
unsigned int hooknum,
struct sk_buff *skb);

extern int nf_nat_icmp_reply_translation(struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum,
struct sk_buff *skb);
extern int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family);

static inline int nf_nat_initialized(struct nf_conn *ct,
enum nf_nat_manip_type manip)
Expand Down
47 changes: 47 additions & 0 deletions include/net/netfilter/nf_nat_l3proto.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifndef _NF_NAT_L3PROTO_H
#define _NF_NAT_L3PROTO_H

struct nf_nat_l4proto;
struct nf_nat_l3proto {
u8 l3proto;

bool (*in_range)(const struct nf_conntrack_tuple *t,
const struct nf_nat_range *range);

u32 (*secure_port)(const struct nf_conntrack_tuple *t, __be16);

bool (*manip_pkt)(struct sk_buff *skb,
unsigned int iphdroff,
const struct nf_nat_l4proto *l4proto,
const struct nf_conntrack_tuple *target,
enum nf_nat_manip_type maniptype);

void (*csum_update)(struct sk_buff *skb, unsigned int iphdroff,
__sum16 *check,
const struct nf_conntrack_tuple *t,
enum nf_nat_manip_type maniptype);

void (*csum_recalc)(struct sk_buff *skb, u8 proto,
void *data, __sum16 *check,
int datalen, int oldlen);

void (*decode_session)(struct sk_buff *skb,
const struct nf_conn *ct,
enum ip_conntrack_dir dir,
unsigned long statusbit,
struct flowi *fl);

int (*nlattr_to_range)(struct nlattr *tb[],
struct nf_nat_range *range);
};

extern int nf_nat_l3proto_register(const struct nf_nat_l3proto *);
extern void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *);
extern const struct nf_nat_l3proto *__nf_nat_l3proto_find(u8 l3proto);

extern int nf_nat_icmp_reply_translation(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum);

#endif /* _NF_NAT_L3PROTO_H */
71 changes: 71 additions & 0 deletions include/net/netfilter/nf_nat_l4proto.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* Header for use in defining a given protocol. */
#ifndef _NF_NAT_L4PROTO_H
#define _NF_NAT_L4PROTO_H
#include <net/netfilter/nf_nat.h>
#include <linux/netfilter/nfnetlink_conntrack.h>

struct nf_nat_range;
struct nf_nat_l3proto;

struct nf_nat_l4proto {
/* Protocol number. */
u8 l4proto;

/* Translate a packet to the target according to manip type.
* Return true if succeeded.
*/
bool (*manip_pkt)(struct sk_buff *skb,
const struct nf_nat_l3proto *l3proto,
unsigned int iphdroff, unsigned int hdroff,
const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype);

/* Is the manipable part of the tuple between min and max incl? */
bool (*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. Per-protocol part of tuple is initialized to the
* incoming packet.
*/
void (*unique_tuple)(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range,
enum nf_nat_manip_type maniptype,
const struct nf_conn *ct);

int (*nlattr_to_range)(struct nlattr *tb[],
struct nf_nat_range *range);
};

/* Protocol registration. */
extern int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto);
extern void nf_nat_l4proto_unregister(u8 l3proto, const struct nf_nat_l4proto *l4proto);

extern const struct nf_nat_l4proto *__nf_nat_l4proto_find(u8 l3proto, u8 l4proto);

/* Built-in protocols. */
extern const struct nf_nat_l4proto nf_nat_l4proto_tcp;
extern const struct nf_nat_l4proto nf_nat_l4proto_udp;
extern const struct nf_nat_l4proto nf_nat_l4proto_icmp;
extern const struct nf_nat_l4proto nf_nat_l4proto_unknown;

extern bool nf_nat_l4proto_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);

extern void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range,
enum nf_nat_manip_type maniptype,
const struct nf_conn *ct,
u16 *rover);

extern int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[],
struct nf_nat_range *range);

#endif /*_NF_NAT_L4PROTO_H*/
67 changes: 0 additions & 67 deletions include/net/netfilter/nf_nat_protocol.h

This file was deleted.

15 changes: 0 additions & 15 deletions include/net/netfilter/nf_nat_rule.h

This file was deleted.

4 changes: 4 additions & 0 deletions include/net/netns/conntrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ struct netns_ct {
int sysctl_auto_assign_helper;
bool auto_assign_helper_warned;
struct nf_ip_net nf_ct_proto;
#ifdef CONFIG_NF_NAT_NEEDED
struct hlist_head *nat_bysource;
unsigned int nat_htable_size;
#endif
#ifdef CONFIG_SYSCTL
struct ctl_table_header *sysctl_header;
struct ctl_table_header *acct_sysctl_header;
Expand Down
2 changes: 0 additions & 2 deletions include/net/netns/ipv4.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ struct netns_ipv4 {
struct xt_table *iptable_security;
#endif
struct xt_table *nat_table;
struct hlist_head *nat_bysource;
unsigned int nat_htable_size;
#endif

int sysctl_icmp_echo_ignore_all;
Expand Down
37 changes: 0 additions & 37 deletions net/ipv4/netfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,43 +72,6 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type)
}
EXPORT_SYMBOL(ip_route_me_harder);

#ifdef CONFIG_XFRM
int ip_xfrm_me_harder(struct sk_buff *skb)
{
struct flowi fl;
unsigned int hh_len;
struct dst_entry *dst;

if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
return 0;
if (xfrm_decode_session(skb, &fl, AF_INET) < 0)
return -1;

dst = skb_dst(skb);
if (dst->xfrm)
dst = ((struct xfrm_dst *)dst)->route;
dst_hold(dst);

dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0);
if (IS_ERR(dst))
return -1;

skb_dst_drop(skb);
skb_dst_set(skb, dst);

/* Change in oif may mean change in hh_len. */
hh_len = skb_dst(skb)->dev->hard_header_len;
if (skb_headroom(skb) < hh_len &&
pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
return -1;
return 0;
}
EXPORT_SYMBOL(ip_xfrm_me_harder);
#endif

void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
EXPORT_SYMBOL(ip_nat_decode_session);

/*
* Extra routing may needed on local out, as the QUEUE target never
* returns control to the table.
Expand Down
Loading

0 comments on commit c7232c9

Please sign in to comment.