|
@@ -30,7 +30,6 @@
|
|
|
#include <net/netfilter/nf_nat_helper.h>
|
|
|
#include <net/netfilter/nf_conntrack_helper.h>
|
|
|
#include <net/netfilter/nf_conntrack_l3proto.h>
|
|
|
-#include <net/netfilter/nf_conntrack_l4proto.h>
|
|
|
#include <net/netfilter/nf_conntrack_zones.h>
|
|
|
|
|
|
static DEFINE_SPINLOCK(nf_nat_lock);
|
|
@@ -57,7 +56,7 @@ hash_by_src(const struct net *net, u16 zone,
|
|
|
/* Original src, to ensure we map it consistently if poss. */
|
|
|
hash = jhash_3words((__force u32)tuple->src.u3.ip,
|
|
|
(__force u32)tuple->src.u.all ^ zone,
|
|
|
- tuple->dst.protonum, 0);
|
|
|
+ tuple->dst.protonum, nf_conntrack_hash_rnd);
|
|
|
return ((u64)hash * net->ipv4.nat_htable_size) >> 32;
|
|
|
}
|
|
|
|
|
@@ -82,14 +81,14 @@ EXPORT_SYMBOL(nf_nat_used_tuple);
|
|
|
* that meet the constraints of range. */
|
|
|
static int
|
|
|
in_range(const struct nf_conntrack_tuple *tuple,
|
|
|
- const struct nf_nat_range *range)
|
|
|
+ const struct nf_nat_ipv4_range *range)
|
|
|
{
|
|
|
const struct nf_nat_protocol *proto;
|
|
|
int ret = 0;
|
|
|
|
|
|
/* If we are supposed to map IPs, then we must be in the
|
|
|
range specified, otherwise let this drag us onto a new src IP. */
|
|
|
- if (range->flags & IP_NAT_RANGE_MAP_IPS) {
|
|
|
+ if (range->flags & NF_NAT_RANGE_MAP_IPS) {
|
|
|
if (ntohl(tuple->src.u3.ip) < ntohl(range->min_ip) ||
|
|
|
ntohl(tuple->src.u3.ip) > ntohl(range->max_ip))
|
|
|
return 0;
|
|
@@ -97,8 +96,8 @@ in_range(const struct nf_conntrack_tuple *tuple,
|
|
|
|
|
|
rcu_read_lock();
|
|
|
proto = __nf_nat_proto_find(tuple->dst.protonum);
|
|
|
- if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
|
|
|
- proto->in_range(tuple, IP_NAT_MANIP_SRC,
|
|
|
+ if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) ||
|
|
|
+ proto->in_range(tuple, NF_NAT_MANIP_SRC,
|
|
|
&range->min, &range->max))
|
|
|
ret = 1;
|
|
|
rcu_read_unlock();
|
|
@@ -123,7 +122,7 @@ static int
|
|
|
find_appropriate_src(struct net *net, u16 zone,
|
|
|
const struct nf_conntrack_tuple *tuple,
|
|
|
struct nf_conntrack_tuple *result,
|
|
|
- const struct nf_nat_range *range)
|
|
|
+ const struct nf_nat_ipv4_range *range)
|
|
|
{
|
|
|
unsigned int h = hash_by_src(net, zone, tuple);
|
|
|
const struct nf_conn_nat *nat;
|
|
@@ -157,7 +156,7 @@ find_appropriate_src(struct net *net, u16 zone,
|
|
|
*/
|
|
|
static void
|
|
|
find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
|
|
|
- const struct nf_nat_range *range,
|
|
|
+ const struct nf_nat_ipv4_range *range,
|
|
|
const struct nf_conn *ct,
|
|
|
enum nf_nat_manip_type maniptype)
|
|
|
{
|
|
@@ -166,10 +165,10 @@ find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
|
|
|
u_int32_t minip, maxip, j;
|
|
|
|
|
|
/* No IP mapping? Do nothing. */
|
|
|
- if (!(range->flags & IP_NAT_RANGE_MAP_IPS))
|
|
|
+ if (!(range->flags & NF_NAT_RANGE_MAP_IPS))
|
|
|
return;
|
|
|
|
|
|
- if (maniptype == IP_NAT_MANIP_SRC)
|
|
|
+ if (maniptype == NF_NAT_MANIP_SRC)
|
|
|
var_ipp = &tuple->src.u3.ip;
|
|
|
else
|
|
|
var_ipp = &tuple->dst.u3.ip;
|
|
@@ -189,7 +188,7 @@ find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
|
|
|
minip = ntohl(range->min_ip);
|
|
|
maxip = ntohl(range->max_ip);
|
|
|
j = jhash_2words((__force u32)tuple->src.u3.ip,
|
|
|
- range->flags & IP_NAT_RANGE_PERSISTENT ?
|
|
|
+ range->flags & NF_NAT_RANGE_PERSISTENT ?
|
|
|
0 : (__force u32)tuple->dst.u3.ip ^ zone, 0);
|
|
|
j = ((u64)j * (maxip - minip + 1)) >> 32;
|
|
|
*var_ipp = htonl(minip + j);
|
|
@@ -204,7 +203,7 @@ find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
|
|
|
static void
|
|
|
get_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|
|
const struct nf_conntrack_tuple *orig_tuple,
|
|
|
- const struct nf_nat_range *range,
|
|
|
+ const struct nf_nat_ipv4_range *range,
|
|
|
struct nf_conn *ct,
|
|
|
enum nf_nat_manip_type maniptype)
|
|
|
{
|
|
@@ -219,8 +218,8 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|
|
This is only required for source (ie. NAT/masq) mappings.
|
|
|
So far, we don't do local source mappings, so multiple
|
|
|
manips not an issue. */
|
|
|
- if (maniptype == IP_NAT_MANIP_SRC &&
|
|
|
- !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
|
|
|
+ if (maniptype == NF_NAT_MANIP_SRC &&
|
|
|
+ !(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) {
|
|
|
/* try the original tuple first */
|
|
|
if (in_range(orig_tuple, range)) {
|
|
|
if (!nf_nat_used_tuple(orig_tuple, ct)) {
|
|
@@ -247,8 +246,8 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|
|
proto = __nf_nat_proto_find(orig_tuple->dst.protonum);
|
|
|
|
|
|
/* Only bother mapping if it's not already in range and unique */
|
|
|
- if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
|
|
|
- if (range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
|
|
|
+ if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) {
|
|
|
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
|
|
if (proto->in_range(tuple, maniptype, &range->min,
|
|
|
&range->max) &&
|
|
|
(range->min.all == range->max.all ||
|
|
@@ -267,7 +266,7 @@ out:
|
|
|
|
|
|
unsigned int
|
|
|
nf_nat_setup_info(struct nf_conn *ct,
|
|
|
- const struct nf_nat_range *range,
|
|
|
+ const struct nf_nat_ipv4_range *range,
|
|
|
enum nf_nat_manip_type maniptype)
|
|
|
{
|
|
|
struct net *net = nf_ct_net(ct);
|
|
@@ -284,8 +283,8 @@ nf_nat_setup_info(struct nf_conn *ct,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- NF_CT_ASSERT(maniptype == IP_NAT_MANIP_SRC ||
|
|
|
- maniptype == IP_NAT_MANIP_DST);
|
|
|
+ NF_CT_ASSERT(maniptype == NF_NAT_MANIP_SRC ||
|
|
|
+ maniptype == NF_NAT_MANIP_DST);
|
|
|
BUG_ON(nf_nat_initialized(ct, maniptype));
|
|
|
|
|
|
/* What we've got will look like inverse of reply. Normally
|
|
@@ -306,13 +305,13 @@ nf_nat_setup_info(struct nf_conn *ct,
|
|
|
nf_conntrack_alter_reply(ct, &reply);
|
|
|
|
|
|
/* Non-atomic: we own this at the moment. */
|
|
|
- if (maniptype == IP_NAT_MANIP_SRC)
|
|
|
+ if (maniptype == NF_NAT_MANIP_SRC)
|
|
|
ct->status |= IPS_SRC_NAT;
|
|
|
else
|
|
|
ct->status |= IPS_DST_NAT;
|
|
|
}
|
|
|
|
|
|
- if (maniptype == IP_NAT_MANIP_SRC) {
|
|
|
+ if (maniptype == NF_NAT_MANIP_SRC) {
|
|
|
unsigned int srchash;
|
|
|
|
|
|
srchash = hash_by_src(net, nf_ct_zone(ct),
|
|
@@ -327,7 +326,7 @@ nf_nat_setup_info(struct nf_conn *ct,
|
|
|
}
|
|
|
|
|
|
/* It's done. */
|
|
|
- if (maniptype == IP_NAT_MANIP_DST)
|
|
|
+ if (maniptype == NF_NAT_MANIP_DST)
|
|
|
ct->status |= IPS_DST_NAT_DONE;
|
|
|
else
|
|
|
ct->status |= IPS_SRC_NAT_DONE;
|
|
@@ -361,7 +360,7 @@ manip_pkt(u_int16_t proto,
|
|
|
|
|
|
iph = (void *)skb->data + iphdroff;
|
|
|
|
|
|
- if (maniptype == IP_NAT_MANIP_SRC) {
|
|
|
+ if (maniptype == NF_NAT_MANIP_SRC) {
|
|
|
csum_replace4(&iph->check, iph->saddr, target->src.u3.ip);
|
|
|
iph->saddr = target->src.u3.ip;
|
|
|
} else {
|
|
@@ -381,7 +380,7 @@ unsigned int nf_nat_packet(struct nf_conn *ct,
|
|
|
unsigned long statusbit;
|
|
|
enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum);
|
|
|
|
|
|
- if (mtype == IP_NAT_MANIP_SRC)
|
|
|
+ if (mtype == NF_NAT_MANIP_SRC)
|
|
|
statusbit = IPS_SRC_NAT;
|
|
|
else
|
|
|
statusbit = IPS_DST_NAT;
|
|
@@ -414,8 +413,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
|
|
struct icmphdr icmp;
|
|
|
struct iphdr ip;
|
|
|
} *inside;
|
|
|
- const struct nf_conntrack_l4proto *l4proto;
|
|
|
- struct nf_conntrack_tuple inner, target;
|
|
|
+ struct nf_conntrack_tuple target;
|
|
|
int hdrlen = ip_hdrlen(skb);
|
|
|
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
|
|
unsigned long statusbit;
|
|
@@ -447,7 +445,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- if (manip == IP_NAT_MANIP_SRC)
|
|
|
+ if (manip == NF_NAT_MANIP_SRC)
|
|
|
statusbit = IPS_SRC_NAT;
|
|
|
else
|
|
|
statusbit = IPS_DST_NAT;
|
|
@@ -463,16 +461,6 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
|
|
"dir %s\n", skb, manip,
|
|
|
dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
|
|
|
|
|
|
- /* rcu_read_lock()ed by nf_hook_slow */
|
|
|
- l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
|
|
|
-
|
|
|
- if (!nf_ct_get_tuple(skb, hdrlen + sizeof(struct icmphdr),
|
|
|
- (hdrlen +
|
|
|
- sizeof(struct icmphdr) + inside->ip.ihl * 4),
|
|
|
- (u_int16_t)AF_INET, inside->ip.protocol,
|
|
|
- &inner, l3proto, l4proto))
|
|
|
- return 0;
|
|
|
-
|
|
|
/* Change inner back to look like incoming packet. We do the
|
|
|
opposite manip on this hook to normal, because it might not
|
|
|
pass all hooks (locally-generated ICMP). Consider incoming
|
|
@@ -575,26 +563,6 @@ static struct nf_ct_ext_type nat_extend __read_mostly = {
|
|
|
#include <linux/netfilter/nfnetlink.h>
|
|
|
#include <linux/netfilter/nfnetlink_conntrack.h>
|
|
|
|
|
|
-static const struct nf_nat_protocol *
|
|
|
-nf_nat_proto_find_get(u_int8_t protonum)
|
|
|
-{
|
|
|
- const struct nf_nat_protocol *p;
|
|
|
-
|
|
|
- rcu_read_lock();
|
|
|
- p = __nf_nat_proto_find(protonum);
|
|
|
- if (!try_module_get(p->me))
|
|
|
- p = &nf_nat_unknown_protocol;
|
|
|
- rcu_read_unlock();
|
|
|
-
|
|
|
- return p;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-nf_nat_proto_put(const struct nf_nat_protocol *p)
|
|
|
-{
|
|
|
- module_put(p->me);
|
|
|
-}
|
|
|
-
|
|
|
static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
|
|
|
[CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 },
|
|
|
[CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 },
|
|
@@ -602,7 +570,7 @@ static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
|
|
|
|
|
|
static int nfnetlink_parse_nat_proto(struct nlattr *attr,
|
|
|
const struct nf_conn *ct,
|
|
|
- struct nf_nat_range *range)
|
|
|
+ struct nf_nat_ipv4_range *range)
|
|
|
{
|
|
|
struct nlattr *tb[CTA_PROTONAT_MAX+1];
|
|
|
const struct nf_nat_protocol *npt;
|
|
@@ -612,21 +580,23 @@ static int nfnetlink_parse_nat_proto(struct nlattr *attr,
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
|
|
|
- npt = nf_nat_proto_find_get(nf_ct_protonum(ct));
|
|
|
+ rcu_read_lock();
|
|
|
+ npt = __nf_nat_proto_find(nf_ct_protonum(ct));
|
|
|
if (npt->nlattr_to_range)
|
|
|
err = npt->nlattr_to_range(tb, range);
|
|
|
- nf_nat_proto_put(npt);
|
|
|
+ rcu_read_unlock();
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
|
|
|
[CTA_NAT_MINIP] = { .type = NLA_U32 },
|
|
|
[CTA_NAT_MAXIP] = { .type = NLA_U32 },
|
|
|
+ [CTA_NAT_PROTO] = { .type = NLA_NESTED },
|
|
|
};
|
|
|
|
|
|
static int
|
|
|
nfnetlink_parse_nat(const struct nlattr *nat,
|
|
|
- const struct nf_conn *ct, struct nf_nat_range *range)
|
|
|
+ const struct nf_conn *ct, struct nf_nat_ipv4_range *range)
|
|
|
{
|
|
|
struct nlattr *tb[CTA_NAT_MAX+1];
|
|
|
int err;
|
|
@@ -646,7 +616,7 @@ nfnetlink_parse_nat(const struct nlattr *nat,
|
|
|
range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]);
|
|
|
|
|
|
if (range->min_ip)
|
|
|
- range->flags |= IP_NAT_RANGE_MAP_IPS;
|
|
|
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
|
|
|
|
|
|
if (!tb[CTA_NAT_PROTO])
|
|
|
return 0;
|
|
@@ -663,7 +633,7 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct,
|
|
|
enum nf_nat_manip_type manip,
|
|
|
const struct nlattr *attr)
|
|
|
{
|
|
|
- struct nf_nat_range range;
|
|
|
+ struct nf_nat_ipv4_range range;
|
|
|
|
|
|
if (nfnetlink_parse_nat(attr, ct, &range) < 0)
|
|
|
return -EINVAL;
|