diff options
| author | Patrick McHardy <kaber@coreworks.de> | 2004-09-23 00:42:59 -0700 |
|---|---|---|
| committer | David S. Miller <davem@kernel.bkbits.net> | 2004-09-23 00:42:59 -0700 |
| commit | 549499a746f144fc71a1d60adae2a65f24e261b6 (patch) | |
| tree | 5b49fd8721214137430123f121f43842b4383964 | |
| parent | c1041076b7abe2674f2de9dd0a46ad405eb3eb51 (diff) | |
[NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/linux/netfilter_ipv4/ip_conntrack_core.h | 4 | ||||
| -rw-r--r-- | include/linux/netfilter_ipv4/ip_conntrack_protocol.h | 12 | ||||
| -rw-r--r-- | include/linux/netfilter_ipv4/ip_nat_core.h | 6 | ||||
| -rw-r--r-- | include/linux/netfilter_ipv4/ip_nat_protocol.h | 16 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_conntrack_core.c | 41 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_conntrack_proto_sctp.c | 1 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_conntrack_standalone.c | 25 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_nat_core.c | 39 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_icmp.c | 2 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_tcp.c | 2 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_udp.c | 2 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_unknown.c | 4 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 15 |
13 files changed, 58 insertions, 111 deletions
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h index 0acb025c5422..bb9b11c680ac 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_core.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h @@ -16,10 +16,6 @@ extern int ip_conntrack_init(void); extern void ip_conntrack_cleanup(void); struct ip_conntrack_protocol; -extern struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol); -/* Like above, but you already have conntrack read lock. */ -extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol); -extern struct list_head protocol_list; extern int ip_ct_get_tuple(const struct iphdr *iph, diff --git a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h index f53a126ade1e..0ff067b3fdb0 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h @@ -7,9 +7,6 @@ struct seq_file; struct ip_conntrack_protocol { - /* Next pointer. */ - struct list_head list; - /* Protocol number. */ u_int8_t proto; @@ -58,14 +55,23 @@ struct ip_conntrack_protocol struct module *me; }; +#define MAX_IP_CT_PROTO 256 +extern struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO]; + /* Protocol registration. */ extern int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto); extern void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto); +static inline struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol) +{ + return ip_ct_protos[protocol]; +} + /* Existing built-in protocols */ extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp; extern struct ip_conntrack_protocol ip_conntrack_protocol_udp; extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp; +extern struct ip_conntrack_protocol ip_conntrack_generic_protocol; extern int ip_conntrack_protocol_tcp_init(void); /* Log invalid packets */ diff --git a/include/linux/netfilter_ipv4/ip_nat_core.h b/include/linux/netfilter_ipv4/ip_nat_core.h index a8bcdc9874a5..4f01f882f2fc 100644 --- a/include/linux/netfilter_ipv4/ip_nat_core.h +++ b/include/linux/netfilter_ipv4/ip_nat_core.h @@ -14,8 +14,6 @@ extern unsigned int do_bindings(struct ip_conntrack *ct, unsigned int hooknum, struct sk_buff **pskb); -extern struct list_head protos; - extern int icmp_reply_translation(struct sk_buff **pskb, struct ip_conntrack *conntrack, unsigned int hooknum, @@ -26,8 +24,4 @@ extern void replace_in_hashes(struct ip_conntrack *conntrack, extern void place_in_hashes(struct ip_conntrack *conntrack, struct ip_nat_info *info); -/* Built-in protocols. */ -extern struct ip_nat_protocol ip_nat_protocol_tcp; -extern struct ip_nat_protocol ip_nat_protocol_udp; -extern struct ip_nat_protocol ip_nat_protocol_icmp; #endif /* _IP_NAT_CORE_H */ diff --git a/include/linux/netfilter_ipv4/ip_nat_protocol.h b/include/linux/netfilter_ipv4/ip_nat_protocol.h index 998ab2bd325c..e81795806ee3 100644 --- a/include/linux/netfilter_ipv4/ip_nat_protocol.h +++ b/include/linux/netfilter_ipv4/ip_nat_protocol.h @@ -9,8 +9,6 @@ struct ip_nat_range; struct ip_nat_protocol { - struct list_head list; - /* Protocol name */ const char *name; @@ -47,10 +45,24 @@ struct ip_nat_protocol const struct ip_nat_range *range); }; +#define MAX_IP_NAT_PROTO 256 +extern struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO]; + /* Protocol registration. */ extern int ip_nat_protocol_register(struct ip_nat_protocol *proto); extern void ip_nat_protocol_unregister(struct ip_nat_protocol *proto); +static inline struct ip_nat_protocol *ip_nat_find_proto(u_int8_t protocol) +{ + return ip_nat_protos[protocol]; +} + +/* Built-in protocols. */ +extern struct ip_nat_protocol ip_nat_protocol_tcp; +extern struct ip_nat_protocol ip_nat_protocol_udp; +extern struct ip_nat_protocol ip_nat_protocol_icmp; +extern struct ip_nat_protocol ip_nat_unknown_protocol; + extern int init_protocols(void) __init; extern void cleanup_protocols(void); extern struct ip_nat_protocol *find_nat_proto(u_int16_t protonum); diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index d38a00225095..a5ce8ad2229e 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -66,7 +66,7 @@ EXPORT_SYMBOL(ip_conntrack_count); void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL; LIST_HEAD(ip_conntrack_expect_list); -LIST_HEAD(protocol_list); +struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO]; static LIST_HEAD(helpers); unsigned int ip_conntrack_htable_size = 0; int ip_conntrack_max; @@ -77,37 +77,6 @@ struct ip_conntrack ip_conntrack_untracked; DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat); -extern struct ip_conntrack_protocol ip_conntrack_generic_protocol; - -static inline int proto_cmpfn(const struct ip_conntrack_protocol *curr, - u_int8_t protocol) -{ - return protocol == curr->proto; -} - -struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol) -{ - struct ip_conntrack_protocol *p; - - MUST_BE_READ_LOCKED(&ip_conntrack_lock); - p = LIST_FIND(&protocol_list, proto_cmpfn, - struct ip_conntrack_protocol *, protocol); - if (!p) - p = &ip_conntrack_generic_protocol; - - return p; -} - -struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol) -{ - struct ip_conntrack_protocol *p; - - READ_LOCK(&ip_conntrack_lock); - p = __ip_ct_find_proto(protocol); - READ_UNLOCK(&ip_conntrack_lock); - return p; -} - inline void ip_conntrack_put(struct ip_conntrack *ct) { @@ -1397,10 +1366,12 @@ int __init ip_conntrack_init(void) /* Don't NEED lock here, but good form anyway. */ WRITE_LOCK(&ip_conntrack_lock); + for (i = 0; i < MAX_IP_CT_PROTO; i++) + ip_ct_protos[i] = &ip_conntrack_generic_protocol; /* Sew in builtin protocols. */ - list_append(&protocol_list, &ip_conntrack_protocol_tcp); - list_append(&protocol_list, &ip_conntrack_protocol_udp); - list_append(&protocol_list, &ip_conntrack_protocol_icmp); + ip_ct_protos[IPPROTO_TCP] = &ip_conntrack_protocol_tcp; + ip_ct_protos[IPPROTO_UDP] = &ip_conntrack_protocol_udp; + ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp; WRITE_UNLOCK(&ip_conntrack_lock); for (i = 0; i < ip_conntrack_htable_size; i++) diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index 638809386107..3105e2b0149b 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c @@ -496,7 +496,6 @@ static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp, } struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { - .list = { NULL, NULL }, .proto = IPPROTO_SCTP, .name = "sctp", .pkt_to_tuple = sctp_pkt_to_tuple, diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 195f7b2662e9..c9ef4ce7a04e 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -112,7 +112,7 @@ static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash, if (DIRECTION(hash)) return 0; - proto = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL] + proto = ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL] .tuple.dst.protonum); IP_NF_ASSERT(proto); @@ -242,7 +242,7 @@ static int exp_seq_show(struct seq_file *s, void *v) expect->tuple.dst.protonum); print_tuple(s, &expect->tuple, - __ip_ct_find_proto(expect->tuple.dst.protonum)); + ip_ct_find_proto(expect->tuple.dst.protonum)); return seq_putc(s, '\n'); } @@ -824,19 +824,13 @@ cleanup_proc_exp: int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto) { int ret = 0; - struct list_head *i; WRITE_LOCK(&ip_conntrack_lock); - list_for_each(i, &protocol_list) { - if (((struct ip_conntrack_protocol *)i)->proto - == proto->proto) { - ret = -EBUSY; - goto out; - } + if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) { + ret = -EBUSY; + goto out; } - - list_prepend(&protocol_list, proto); - + ip_ct_protos[proto->proto] = proto; out: WRITE_UNLOCK(&ip_conntrack_lock); return ret; @@ -845,10 +839,7 @@ int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto) void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto) { WRITE_LOCK(&ip_conntrack_lock); - - /* ip_ct_find_proto() returns proto_generic in case there is no protocol - * helper. So this should be enough - HW */ - LIST_DELETE(&protocol_list, proto); + ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol; WRITE_UNLOCK(&ip_conntrack_lock); /* Somebody could be still looking at the proto in bh. */ @@ -888,8 +879,8 @@ EXPORT_SYMBOL(ip_conntrack_helper_register); EXPORT_SYMBOL(ip_conntrack_helper_unregister); EXPORT_SYMBOL(ip_ct_selective_cleanup); EXPORT_SYMBOL(ip_ct_refresh_acct); +EXPORT_SYMBOL(ip_ct_protos); EXPORT_SYMBOL(ip_ct_find_proto); -EXPORT_SYMBOL(__ip_ct_find_proto); EXPORT_SYMBOL(ip_ct_find_helper); EXPORT_SYMBOL(ip_conntrack_expect_alloc); EXPORT_SYMBOL(ip_conntrack_expect_related); diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index d47a837990c4..49595abe2609 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -48,9 +48,8 @@ static unsigned int ip_nat_htable_size; static struct list_head *bysource; static struct list_head *byipsproto; -LIST_HEAD(protos); +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 @@ -103,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, @@ -142,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 }; @@ -394,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; @@ -705,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; @@ -731,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); @@ -976,9 +957,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++) { diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c index f7d31f850d79..6fb50dee520c 100644 --- a/net/ipv4/netfilter/ip_nat_proto_icmp.c +++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c @@ -104,7 +104,7 @@ icmp_print_range(char *buffer, const struct ip_nat_range *range) } struct ip_nat_protocol ip_nat_protocol_icmp -= { { NULL, NULL }, "ICMP", IPPROTO_ICMP, += { "ICMP", IPPROTO_ICMP, icmp_manip_pkt, icmp_in_range, icmp_unique_tuple, diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c index 731a12d08819..197bd01e2166 100644 --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c @@ -162,7 +162,7 @@ tcp_print_range(char *buffer, const struct ip_nat_range *range) } struct ip_nat_protocol ip_nat_protocol_tcp -= { { NULL, NULL }, "TCP", IPPROTO_TCP, += { "TCP", IPPROTO_TCP, tcp_manip_pkt, tcp_in_range, tcp_unique_tuple, diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index 293846556910..240004eede81 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -148,7 +148,7 @@ udp_print_range(char *buffer, const struct ip_nat_range *range) } struct ip_nat_protocol ip_nat_protocol_udp -= { { NULL, NULL }, "UDP", IPPROTO_UDP, += { "UDP", IPPROTO_UDP, udp_manip_pkt, udp_in_range, udp_unique_tuple, diff --git a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c index 2d42a00f0bef..b57103fa907c 100644 --- a/net/ipv4/netfilter/ip_nat_proto_unknown.c +++ b/net/ipv4/netfilter/ip_nat_proto_unknown.c @@ -60,8 +60,8 @@ unknown_print_range(char *buffer, const struct ip_nat_range *range) return 0; } -struct ip_nat_protocol unknown_nat_protocol = { - { NULL, NULL }, "unknown", 0, +struct ip_nat_protocol ip_nat_unknown_protocol = { + "unknown", 0, unknown_manip_pkt, unknown_in_range, unknown_unique_tuple, diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index fcc74c0facfe..e4e961225c5f 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -283,18 +283,13 @@ static struct nf_hook_ops ip_nat_local_in_ops = { int ip_nat_protocol_register(struct ip_nat_protocol *proto) { int ret = 0; - struct list_head *i; WRITE_LOCK(&ip_nat_lock); - list_for_each(i, &protos) { - if (((struct ip_nat_protocol *)i)->protonum - == proto->protonum) { - ret = -EBUSY; - goto out; - } + if (ip_nat_protos[proto->protonum] != &ip_nat_unknown_protocol) { + ret = -EBUSY; + goto out; } - - list_prepend(&protos, proto); + ip_nat_protos[proto->protonum] = proto; out: WRITE_UNLOCK(&ip_nat_lock); return ret; @@ -304,7 +299,7 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto) void ip_nat_protocol_unregister(struct ip_nat_protocol *proto) { WRITE_LOCK(&ip_nat_lock); - LIST_DELETE(&protos, proto); + ip_nat_protos[proto->protonum] = &ip_nat_unknown_protocol; WRITE_UNLOCK(&ip_nat_lock); /* Someone could be still looking at the proto in a bh. */ |
