summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@coreworks.de>2004-09-23 00:42:59 -0700
committerDavid S. Miller <davem@kernel.bkbits.net>2004-09-23 00:42:59 -0700
commit549499a746f144fc71a1d60adae2a65f24e261b6 (patch)
tree5b49fd8721214137430123f121f43842b4383964
parentc1041076b7abe2674f2de9dd0a46ad405eb3eb51 (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.h4
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_protocol.h12
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_core.h6
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_protocol.h16
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c41
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_sctp.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c25
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c39
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_icmp.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_tcp.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_udp.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_unknown.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c15
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. */