X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fip_nat_core.c;h=1ecc3f28516ab2920d9663ccbbb9455e29d20aed;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=1c6b7810655a459315cd6d067090197c0afb19c7;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 1c6b78106..1ecc3f285 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -48,10 +48,8 @@ static unsigned int ip_nat_htable_size; 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 @@ -78,9 +76,6 @@ static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn) 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); @@ -91,8 +86,8 @@ static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn) .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); } @@ -107,23 +102,6 @@ ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) 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, @@ -146,7 +124,7 @@ in_range(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 }; @@ -172,20 +150,18 @@ in_range(const struct ip_conntrack_tuple *tuple, } 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 */ @@ -194,14 +170,13 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple, 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 @@ -227,19 +202,17 @@ do_extra_mangle(u_int32_t var_ip, u_int32_t *other_ipp) #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; } @@ -248,13 +221,14 @@ static inline unsigned int 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; } @@ -402,7 +376,7 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple, 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; @@ -498,13 +472,6 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple, 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, @@ -643,18 +610,15 @@ ip_nat_setup_info(struct ip_conntrack *conntrack, /* 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; } @@ -678,14 +642,9 @@ void replace_in_hashes(struct ip_conntrack *conntrack, 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, @@ -706,14 +665,9 @@ 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. */ @@ -733,9 +687,8 @@ manip_pkt(u_int16_t proto, 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; @@ -759,7 +712,7 @@ static inline int exp_for_packet(struct ip_conntrack_expect *exp, 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); @@ -899,12 +852,8 @@ icmp_reply_translation(struct sk_buff **pskb, } /* 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 @@ -1004,9 +953,11 @@ int __init ip_nat_init(void) /* 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++) {