static struct list_head *bysource;
static struct list_head *byipsproto;
-LIST_HEAD(protos);
-LIST_HEAD(helpers);
+struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
-extern struct ip_nat_protocol unknown_nat_protocol;
/* We keep extra hashes for each conntrack, for fast searching. */
static inline size_t
if (!info->initialized)
return;
- IP_NF_ASSERT(info->bysource.conntrack);
- IP_NF_ASSERT(info->byipsproto.conntrack);
-
hs = hash_by_src(&conn->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src,
conn->tuplehash[IP_CT_DIR_ORIGINAL]
.tuple.dst.protonum);
.tuple.dst.protonum);
WRITE_LOCK(&ip_nat_lock);
- LIST_DELETE(&bysource[hs], &info->bysource);
- LIST_DELETE(&byipsproto[hp], &info->byipsproto);
+ list_del(&info->bysource);
+ list_del(&info->byipsproto);
WRITE_UNLOCK(&ip_nat_lock);
}
oldcheck^0xFFFF));
}
-static inline int cmp_proto(const struct ip_nat_protocol *i, int proto)
-{
- return i->protonum == proto;
-}
-
-struct ip_nat_protocol *
-find_nat_proto(u_int16_t protonum)
-{
- struct ip_nat_protocol *i;
-
- MUST_BE_READ_LOCKED(&ip_nat_lock);
- i = LIST_FIND(&protos, cmp_proto, struct ip_nat_protocol *, protonum);
- if (!i)
- i = &unknown_nat_protocol;
- return i;
-}
-
/* Is this tuple already taken? (not by us) */
int
ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
const struct ip_conntrack_manip *manip,
const struct ip_nat_multi_range *mr)
{
- struct ip_nat_protocol *proto = find_nat_proto(tuple->dst.protonum);
+ struct ip_nat_protocol *proto = ip_nat_find_proto(tuple->dst.protonum);
unsigned int i;
struct ip_conntrack_tuple newtuple = { *manip, tuple->dst };
}
static inline int
-src_cmp(const struct ip_nat_hash *i,
+src_cmp(const struct ip_conntrack *ct,
const struct ip_conntrack_tuple *tuple,
const struct ip_nat_multi_range *mr)
{
- return (i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum
+ return (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum
== tuple->dst.protonum
- && i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip
+ && ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip
== tuple->src.ip
- && i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all
+ && ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all
== tuple->src.u.all
&& in_range(tuple,
- &i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
- .tuple.src,
- mr));
+ &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src, mr));
}
/* Only called for SRC manip */
const struct ip_nat_multi_range *mr)
{
unsigned int h = hash_by_src(&tuple->src, tuple->dst.protonum);
- struct ip_nat_hash *i;
+ struct ip_conntrack *ct;
MUST_BE_READ_LOCKED(&ip_nat_lock);
- i = LIST_FIND(&bysource[h], src_cmp, struct ip_nat_hash *, tuple, mr);
- if (i)
- return &i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src;
- else
- return NULL;
+ list_for_each_entry(ct, &bysource[h], nat.info.bysource)
+ if (src_cmp(ct, tuple, mr))
+ return &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src;
+ return NULL;
}
#ifdef CONFIG_IP_NF_NAT_LOCAL
#endif
/* Simple way to iterate through all. */
-static inline int fake_cmp(const struct ip_nat_hash *i,
+static inline int fake_cmp(const struct ip_conntrack *ct,
u_int32_t src, u_int32_t dst, u_int16_t protonum,
- unsigned int *score,
- const struct ip_conntrack *conntrack)
+ unsigned int *score, const struct ip_conntrack *ct2)
{
/* Compare backwards: we're dealing with OUTGOING tuples, and
inside the conntrack is the REPLY tuple. Don't count this
conntrack. */
- if (i->conntrack != conntrack
- && i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == dst
- && i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == src
- && (i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum
- == protonum))
+ if (ct != ct2
+ && ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == dst
+ && ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == src
+ && (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum == protonum))
(*score)++;
return 0;
}
count_maps(u_int32_t src, u_int32_t dst, u_int16_t protonum,
const struct ip_conntrack *conntrack)
{
+ struct ip_conntrack *ct;
unsigned int score = 0;
unsigned int h;
MUST_BE_READ_LOCKED(&ip_nat_lock);
h = hash_by_ipsproto(src, dst, protonum);
- LIST_FIND(&byipsproto[h], fake_cmp, struct ip_nat_hash *,
- src, dst, protonum, &score, conntrack);
+ list_for_each_entry(ct, &byipsproto[h], nat.info.byipsproto)
+ fake_cmp(ct, src, dst, protonum, &score, conntrack);
return score;
}
unsigned int hooknum)
{
struct ip_nat_protocol *proto
- = find_nat_proto(orig_tuple->dst.protonum);
+ = ip_nat_find_proto(orig_tuple->dst.protonum);
struct ip_nat_range *rptr;
unsigned int i;
int ret;
return ret;
}
-static inline int
-helper_cmp(const struct ip_nat_helper *helper,
- const struct ip_conntrack_tuple *tuple)
-{
- return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
-}
-
/* Where to manip the reply packets (will be reverse manip). */
static unsigned int opposite_hook[NF_IP_NUMHOOKS]
= { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
/* If there's a helper, assign it; based on new tuple. */
if (!conntrack->master)
- info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
- &reply);
+ info->helper = __ip_nat_find_helper(&reply);
/* It's done. */
info->initialized |= (1 << HOOK2MANIP(hooknum));
- if (in_hashes) {
- IP_NF_ASSERT(info->bysource.conntrack);
+ if (in_hashes)
replace_in_hashes(conntrack, info);
- } else {
+ else
place_in_hashes(conntrack, info);
- }
return NF_ACCEPT;
}
conntrack->tuplehash[IP_CT_DIR_REPLY]
.tuple.dst.protonum);
- IP_NF_ASSERT(info->bysource.conntrack == conntrack);
MUST_BE_WRITE_LOCKED(&ip_nat_lock);
-
- list_del(&info->bysource.list);
- list_del(&info->byipsproto.list);
-
- list_prepend(&bysource[srchash], &info->bysource);
- list_prepend(&byipsproto[ipsprotohash], &info->byipsproto);
+ list_move(&info->bysource, &bysource[srchash]);
+ list_move(&info->byipsproto, &byipsproto[ipsprotohash]);
}
void place_in_hashes(struct ip_conntrack *conntrack,
conntrack->tuplehash[IP_CT_DIR_REPLY]
.tuple.dst.protonum);
- IP_NF_ASSERT(!info->bysource.conntrack);
-
MUST_BE_WRITE_LOCKED(&ip_nat_lock);
- info->byipsproto.conntrack = conntrack;
- info->bysource.conntrack = conntrack;
-
- list_prepend(&bysource[srchash], &info->bysource);
- list_prepend(&byipsproto[ipsprotohash], &info->byipsproto);
+ list_add(&info->bysource, &bysource[srchash]);
+ list_add(&info->byipsproto, &byipsproto[ipsprotohash]);
}
/* Returns true if succeeded. */
iph = (void *)(*pskb)->data + iphdroff;
/* Manipulate protcol part. */
- if (!find_nat_proto(proto)->manip_pkt(pskb,
- iphdroff + iph->ihl*4,
- manip, maniptype))
+ if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4,
+ manip, maniptype))
return 0;
iph = (void *)(*pskb)->data + iphdroff;
int ret = 1;
MUST_BE_READ_LOCKED(&ip_conntrack_lock);
- proto = __ip_ct_find_proto(skb->nh.iph->protocol);
+ proto = ip_ct_find_proto(skb->nh.iph->protocol);
if (proto->exp_matches_pkt)
ret = proto->exp_matches_pkt(exp, skb);
}
/* Must be RELATED */
- IP_NF_ASSERT((*pskb)->nfct
- - ((struct ip_conntrack *)(*pskb)->nfct->master)->infos
- == IP_CT_RELATED
- || (*pskb)->nfct
- - ((struct ip_conntrack *)(*pskb)->nfct->master)->infos
- == IP_CT_RELATED+IP_CT_IS_REPLY);
+ IP_NF_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED ||
+ (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
/* Redirects on non-null nats must be dropped, else they'll
start talking to each other without our translation, and be
/* Sew in builtin protocols. */
WRITE_LOCK(&ip_nat_lock);
- list_append(&protos, &ip_nat_protocol_tcp);
- list_append(&protos, &ip_nat_protocol_udp);
- list_append(&protos, &ip_nat_protocol_icmp);
+ for (i = 0; i < MAX_IP_NAT_PROTO; i++)
+ ip_nat_protos[i] = &ip_nat_unknown_protocol;
+ ip_nat_protos[IPPROTO_TCP] = &ip_nat_protocol_tcp;
+ ip_nat_protos[IPPROTO_UDP] = &ip_nat_protocol_udp;
+ ip_nat_protos[IPPROTO_ICMP] = &ip_nat_protocol_icmp;
WRITE_UNLOCK(&ip_nat_lock);
for (i = 0; i < ip_nat_htable_size; i++) {