Commit e068209a authored by David S. Miller's avatar David S. Miller

Merge nuts.davemloft.net:/disk1/BK/nf-work-2.6

into nuts.davemloft.net:/disk1/BK/nf-2.6
parents 6caaa717 480a73d5
......@@ -178,7 +178,7 @@ extern inline struct ip6t_target *
ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex);
extern inline struct arpt_target *
arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
extern void (*ip_ct_attach)(struct sk_buff *, struct nf_ct_info *);
extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
#ifdef CONFIG_NETFILTER_DEBUG
extern void nf_dump_skb(int pf, struct sk_buff *skb);
......
......@@ -172,9 +172,6 @@ struct ip_conntrack
plus 1 for any connection(s) we are `master' for */
struct nf_conntrack ct_general;
/* These are my tuples; original and reply */
struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
/* Have we seen traffic both ways yet? (bitset) */
unsigned long status;
......@@ -199,12 +196,7 @@ struct ip_conntrack
/* Helper, if any. */
struct ip_conntrack_helper *helper;
/* Our various nf_ct_info structs specify *what* relation this
packet has to the conntrack */
struct nf_ct_info infos[IP_CT_NUMBER];
/* Storage reserved for other modules: */
union ip_conntrack_proto proto;
union ip_conntrack_help help;
......@@ -220,6 +212,9 @@ struct ip_conntrack
} nat;
#endif /* CONFIG_IP_NF_NAT_NEEDED */
/* Traversed often, so hopefully in different cacheline to top */
/* These are my tuples; original and reply */
struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
};
/* get master conntrack via master expectation */
......@@ -238,8 +233,12 @@ ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
const struct ip_conntrack *ignored_conntrack);
/* Return conntrack_info and tuple hash for given skb. */
extern struct ip_conntrack *
ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo);
static inline struct ip_conntrack *
ip_conntrack_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
{
*ctinfo = skb->nfctinfo;
return (struct ip_conntrack *)skb->nfct;
}
/* decrement reference count on a conntrack */
extern inline void ip_conntrack_put(struct ip_conntrack *ct);
......@@ -306,12 +305,13 @@ struct ip_conntrack_stat
unsigned int insert_failed;
unsigned int drop;
unsigned int early_drop;
unsigned int icmp_error;
unsigned int error;
unsigned int expect_new;
unsigned int expect_create;
unsigned int expect_delete;
};
#define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
/* eg. PROVIDES_CONNTRACK(ftp); */
#define PROVIDES_CONNTRACK(name) \
......
......@@ -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,
......@@ -38,14 +34,14 @@ struct ip_conntrack_tuple_hash *
ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
const struct ip_conntrack *ignored_conntrack);
extern int __ip_conntrack_confirm(struct nf_ct_info *nfct);
extern int __ip_conntrack_confirm(struct sk_buff *skb);
/* Confirm a connection: returns NF_DROP if packet must be dropped. */
static inline int ip_conntrack_confirm(struct sk_buff *skb)
{
if (skb->nfct
&& !is_confirmed((struct ip_conntrack *)skb->nfct->master))
return __ip_conntrack_confirm(skb->nfct);
&& !is_confirmed((struct ip_conntrack *)skb->nfct))
return __ip_conntrack_confirm(skb);
return NF_ACCEPT;
}
......
......@@ -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 */
......
......@@ -80,27 +80,18 @@ struct ip_nat_info_manip
/* Protects NAT hash tables, and NAT-private part of conntracks. */
DECLARE_RWLOCK_EXTERN(ip_nat_lock);
/* Hashes for by-source and IP/protocol. */
struct ip_nat_hash
{
struct list_head list;
/* conntrack we're embedded in: NULL if not in hash. */
struct ip_conntrack *conntrack;
};
/* The structure embedded in the conntrack structure. */
struct ip_nat_info
{
/* Set to zero when conntrack created: bitmask of maniptypes */
int initialized;
u_int16_t initialized;
unsigned int num_manips;
u_int16_t num_manips;
/* Manipulations to be done on this conntrack. */
struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
struct ip_nat_hash bysource, byipsproto;
struct list_head bysource, byipsproto;
/* Helper (NULL if none). */
struct ip_nat_helper *helper;
......
......@@ -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 */
......@@ -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);
......
#ifndef _IPT_COMMENT_H
#define _IPT_COMMENT_H
#define IPT_MAX_COMMENT_LEN 256
struct ipt_comment_info {
unsigned char comment[IPT_MAX_COMMENT_LEN];
};
#endif /* _IPT_COMMENT_H */
......@@ -97,10 +97,6 @@ struct nf_conntrack {
void (*destroy)(struct nf_conntrack *);
};
struct nf_ct_info {
struct nf_conntrack *master;
};
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info {
atomic_t use;
......@@ -186,6 +182,7 @@ struct skb_shared_info {
* @nfmark: Can be used for communication between hooks
* @nfcache: Cache info
* @nfct: Associated connection, if any
* @nfctinfo: Relationship of this skb to the connection
* @nf_debug: Netfilter debugging
* @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
* @private: Data which is private to the HIPPI implementation
......@@ -253,7 +250,8 @@ struct sk_buff {
#ifdef CONFIG_NETFILTER
unsigned long nfmark;
__u32 nfcache;
struct nf_ct_info *nfct;
struct nf_conntrack *nfct;
__u32 nfctinfo;
#ifdef CONFIG_NETFILTER_DEBUG
unsigned int nf_debug;
#endif
......@@ -1141,15 +1139,15 @@ extern int skb_iter_next(const struct sk_buff *skb, struct skb_iter *i);
extern void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i);
#ifdef CONFIG_NETFILTER
static inline void nf_conntrack_put(struct nf_ct_info *nfct)
static inline void nf_conntrack_put(struct nf_conntrack *nfct)
{
if (nfct && atomic_dec_and_test(&nfct->master->use))
nfct->master->destroy(nfct->master);
if (nfct && atomic_dec_and_test(&nfct->use))
nfct->destroy(nfct);
}
static inline void nf_conntrack_get(struct nf_ct_info *nfct)
static inline void nf_conntrack_get(struct nf_conntrack *nfct)
{
if (nfct)
atomic_inc(&nfct->master->use);
atomic_inc(&nfct->use);
}
static inline void nf_reset(struct sk_buff *skb)
{
......
......@@ -424,6 +424,7 @@ enum
NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT=24,
NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD=25,
NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT=26,
NET_IPV4_NF_CONNTRACK_COUNT=27,
};
/* /proc/sys/net/ipv6 */
......
......@@ -806,7 +806,7 @@ EXPORT_SYMBOL(nf_log_packet);
tracking in use: without this, connection may not be in hash table,
and hence manufactured ICMP or RST packets will not be associated
with it. */
void (*ip_ct_attach)(struct sk_buff *, struct nf_ct_info *);
void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
void __init netfilter_init(void)
{
......
......@@ -311,6 +311,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
C(nfcache);
C(nfct);
nf_conntrack_get(skb->nfct);
C(nfctinfo);
#ifdef CONFIG_NETFILTER_DEBUG
C(nf_debug);
#endif
......@@ -377,6 +378,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->nfcache = old->nfcache;
new->nfct = old->nfct;
nf_conntrack_get(old->nfct);
new->nfctinfo = old->nfctinfo;
#ifdef CONFIG_NETFILTER_DEBUG
new->nf_debug = old->nf_debug;
#endif
......
......@@ -422,6 +422,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
nf_conntrack_put(to->nfct);
to->nfct = from->nfct;
nf_conntrack_get(to->nfct);
to->nfctinfo = from->nfctinfo;
#ifdef CONFIG_BRIDGE_NETFILTER
nf_bridge_put(to->nf_bridge);
to->nf_bridge = from->nf_bridge;
......
......@@ -332,6 +332,16 @@ config IP_NF_MATCH_SCTP
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
config IP_NF_MATCH_COMMENT
tristate 'comment match support'
depends on IP_NF_IPTABLES
help
This option adds a `comment' dummy-match, which allows you to put
comments in your iptables ruleset.
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
# `filter', generic and specific targets
config IP_NF_FILTER
tristate "Packet filtering"
......
......@@ -50,28 +50,23 @@ obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o
# targets
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
......
......@@ -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,45 +77,11 @@ 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)
{
IP_NF_ASSERT(ct);
IP_NF_ASSERT(ct->infos[0].master);
/* nf_conntrack_put wants to go via an info struct, so feed it
one at random. */
nf_conntrack_put(&ct->infos[0]);
nf_conntrack_put(&ct->ct_general);
}
static int ip_conntrack_hash_rnd_initted;
......@@ -185,7 +151,7 @@ destroy_expect(struct ip_conntrack_expect *exp)
IP_NF_ASSERT(!timer_pending(&exp->timeout));
kmem_cache_free(ip_conntrack_expect_cachep, exp);
__get_cpu_var(ip_conntrack_stat).expect_delete++;
CONNTRACK_STAT_INC(expect_delete);
}
inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
......@@ -354,14 +320,14 @@ destroy_conntrack(struct nf_conntrack *nfct)
DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
kmem_cache_free(ip_conntrack_cachep, ct);
atomic_dec(&ip_conntrack_count);
__get_cpu_var(ip_conntrack_stat).delete++;
CONNTRACK_STAT_INC(delete);
}
static void death_by_timeout(unsigned long ul_conntrack)
{
struct ip_conntrack *ct = (void *)ul_conntrack;
__get_cpu_var(ip_conntrack_stat).delete_list++;
CONNTRACK_STAT_INC(delete_list);
WRITE_LOCK(&ip_conntrack_lock);
clean_from_lists(ct);
......@@ -416,36 +382,15 @@ ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
return h;
}
static inline struct ip_conntrack *
__ip_conntrack_get(struct nf_ct_info *nfct, enum ip_conntrack_info *ctinfo)
{
struct ip_conntrack *ct
= (struct ip_conntrack *)nfct->master;
/* ctinfo is the index of the nfct inside the conntrack */
*ctinfo = nfct - ct->infos;
IP_NF_ASSERT(*ctinfo >= 0 && *ctinfo < IP_CT_NUMBER);
return ct;
}
/* Return conntrack and conntrack_info given skb->nfct->master */
struct ip_conntrack *
ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
{
if (skb->nfct)
return __ip_conntrack_get(skb->nfct, ctinfo);
return NULL;
}
/* Confirm a connection given skb->nfct; places it in hash table */
/* Confirm a connection given skb; places it in hash table */
int
__ip_conntrack_confirm(struct nf_ct_info *nfct)
__ip_conntrack_confirm(struct sk_buff *skb)
{
unsigned int hash, repl_hash;
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
ct = __ip_conntrack_get(nfct, &ctinfo);
ct = ip_conntrack_get(skb, &ctinfo);
/* ipt_REJECT uses ip_conntrack_attach to attach related
ICMP/TCP RST packets in other direction. Actual packet
......@@ -491,12 +436,12 @@ __ip_conntrack_confirm(struct nf_ct_info *nfct)
atomic_inc(&ct->ct_general.use);
set_bit(IPS_CONFIRMED_BIT, &ct->status);
WRITE_UNLOCK(&ip_conntrack_lock);
__get_cpu_var(ip_conntrack_stat).insert++;
CONNTRACK_STAT_INC(insert);
return NF_ACCEPT;
}
WRITE_UNLOCK(&ip_conntrack_lock);
__get_cpu_var(ip_conntrack_stat).insert_failed++;
CONNTRACK_STAT_INC(insert_failed);
return NF_DROP;
}
......@@ -540,7 +485,7 @@ static int early_drop(struct list_head *chain)
if (del_timer(&h->ctrack->timeout)) {
death_by_timeout((unsigned long)h->ctrack);
dropped = 1;
__get_cpu_var(ip_conntrack_stat).early_drop++;
CONNTRACK_STAT_INC(early_drop);
}
ip_conntrack_put(h->ctrack);
return dropped;
......@@ -570,8 +515,6 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
struct ip_conntrack_tuple repl_tuple;
size_t hash;
struct ip_conntrack_expect *expected;
int i;
static unsigned int drop_next;
if (!ip_conntrack_hash_rnd_initted) {
get_random_bytes(&ip_conntrack_hash_rnd, 4);
......@@ -580,15 +523,10 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
hash = hash_conntrack(tuple);
if (ip_conntrack_max &&
atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
/* Try dropping from random chain, or else from the
chain about to put into (in case they're trying to
bomb one hash chain). */
unsigned int next = (drop_next++)%ip_conntrack_htable_size;
if (!early_drop(&ip_conntrack_hash[next])
&& !early_drop(&ip_conntrack_hash[hash])) {
if (ip_conntrack_max
&& atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
/* Try dropping from this hash chain. */
if (!early_drop(&ip_conntrack_hash[hash])) {
if (net_ratelimit())
printk(KERN_WARNING
"ip_conntrack: table full, dropping"
......@@ -615,9 +553,6 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack;
conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack;
for (i=0; i < IP_CT_NUMBER; i++)
conntrack->infos[i].master = &conntrack->ct_general;
if (!protocol->new(conntrack, skb)) {
kmem_cache_free(ip_conntrack_cachep, conntrack);
return NULL;
......@@ -655,13 +590,13 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
conntrack, expected);
/* Welcome, Mr. Bond. We've been expecting you... */
IP_NF_ASSERT(master_ct(conntrack));
IP_NF_ASSERT(expected->expectant);
__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
conntrack->master = expected;
expected->sibling = conntrack;
LIST_DELETE(&ip_conntrack_expect_list, expected);
expected->expectant->expecting--;
nf_conntrack_get(&master_ct(conntrack)->infos[0]);
nf_conntrack_get(&master_ct(conntrack)->ct_general);
/* this is a braindead... --pablo */
atomic_inc(&ip_conntrack_count);
......@@ -670,13 +605,13 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
if (expected->expectfn)
expected->expectfn(conntrack);
__get_cpu_var(ip_conntrack_stat).expect_new++;
CONNTRACK_STAT_INC(expect_new);
goto ret;
} else {
conntrack->helper = ip_ct_find_helper(&repl_tuple);
__get_cpu_var(ip_conntrack_stat).new++;
CONNTRACK_STAT_INC(new);
}
end: atomic_inc(&ip_conntrack_count);
......@@ -734,7 +669,8 @@ resolve_normal_ct(struct sk_buff *skb,
}
*set_reply = 0;
}
skb->nfct = &h->ctrack->infos[*ctinfo];
skb->nfct = &h->ctrack->ct_general;
skb->nfctinfo = *ctinfo;
return h->ctrack;
}
......@@ -780,7 +716,7 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
/* Previously seen (loopback or untracked)? Ignore. */
if ((*pskb)->nfct) {
__get_cpu_var(ip_conntrack_stat).ignore++;
CONNTRACK_STAT_INC(ignore);
return NF_ACCEPT;
}
......@@ -791,19 +727,20 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
* core what to do with the packet. */
if (proto->error != NULL
&& (ret = proto->error(*pskb, &ctinfo, hooknum)) <= 0) {
__get_cpu_var(ip_conntrack_stat).icmp_error++;
CONNTRACK_STAT_INC(error);
CONNTRACK_STAT_INC(invalid);
return -ret;
}
if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) {
/* Not valid part of a connection */
__get_cpu_var(ip_conntrack_stat).invalid++;
CONNTRACK_STAT_INC(invalid);
return NF_ACCEPT;
}
if (IS_ERR(ct)) {
/* Too stressed to deal. */
__get_cpu_var(ip_conntrack_stat).drop++;
CONNTRACK_STAT_INC(drop);
return NF_DROP;
}
......@@ -815,7 +752,7 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
* the netfilter core what to do*/
nf_conntrack_put((*pskb)->nfct);
(*pskb)->nfct = NULL;
__get_cpu_var(ip_conntrack_stat).invalid++;
CONNTRACK_STAT_INC(invalid);
return -ret;
}
......@@ -823,7 +760,7 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
ret = ct->helper->help(*pskb, ct, ctinfo);
if (ret == -1) {
/* Invalid */
__get_cpu_var(ip_conntrack_stat).invalid++;
CONNTRACK_STAT_INC(invalid);
nf_conntrack_put((*pskb)->nfct);
(*pskb)->nfct = NULL;
return NF_ACCEPT;
......@@ -1027,7 +964,7 @@ out: ip_conntrack_expect_insert(expect, related_to);
WRITE_UNLOCK(&ip_conntrack_lock);
__get_cpu_var(ip_conntrack_stat).expect_create++;
CONNTRACK_STAT_INC(expect_create);
return ret;
}
......@@ -1219,23 +1156,23 @@ ip_ct_gather_frags(struct sk_buff *skb)
}
/* Used by ipt_REJECT. */
static void ip_conntrack_attach(struct sk_buff *nskb, struct nf_ct_info *nfct)
static void ip_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
{
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
ct = __ip_conntrack_get(nfct, &ctinfo);
/* This ICMP is in reverse direction to the packet which
caused it */
/* This ICMP is in reverse direction to the packet which caused it */
ct = ip_conntrack_get(skb, &ctinfo);
if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
ctinfo = IP_CT_RELATED + IP_CT_IS_REPLY;
else
ctinfo = IP_CT_RELATED;
/* Attach new skbuff, and increment count */
nskb->nfct = &ct->infos[ctinfo];
atomic_inc(&ct->ct_general.use);
/* Attach to new skbuff, and increment count */
nskb->nfct = &ct->ct_general;
nskb->nfctinfo = ctinfo;
nf_conntrack_get(nskb->nfct);
}
static inline int
......@@ -1430,10 +1367,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++)
......@@ -1447,11 +1386,6 @@ int __init ip_conntrack_init(void)
atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
/* - and look it like as a confirmed connection */
set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
/* - and prepare the ctinfo field for REJECT & NAT. */
ip_conntrack_untracked.infos[IP_CT_NEW].master =
ip_conntrack_untracked.infos[IP_CT_RELATED].master =
ip_conntrack_untracked.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master =
&ip_conntrack_untracked.ct_general;
return ret;
......
......@@ -195,7 +195,8 @@ icmp_error_message(struct sk_buff *skb,
}
/* Update skb to refer to this connection */
skb->nfct = &h->ctrack->infos[*ctinfo];
skb->nfct = &h->ctrack->ct_general;
skb->nfctinfo = *ctinfo;
return -NF_ACCEPT;
}
......
......@@ -430,16 +430,16 @@ static int sctp_new(struct ip_conntrack *conntrack,
DEBUGP("\n");
if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
return -1;
return 0;
if (do_basic_checks(conntrack, skb, map) != 0)
return -1;
return 0;
/* If an OOTB packet has any of these chunks discard (Sec 8.4) */
if ((test_bit (SCTP_CID_ABORT, (void *)map))
|| (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
|| (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
return -1;
return 0;
}
newconntrack = SCTP_CONNTRACK_MAX;
......@@ -461,7 +461,7 @@ static int sctp_new(struct ip_conntrack *conntrack,
if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
&inithdr, sizeof(inithdr)) != 0) {
return -1;
return 0;
}
DEBUGP("Setting vtag %x for new conn\n",
......@@ -471,7 +471,7 @@ static int sctp_new(struct ip_conntrack *conntrack,
inithdr.init_tag;
} else {
/* Sec 8.5.1 (A) */
return -1;
return 0;
}
}
/* If it is a shutdown ack OOTB packet, we expect a return
......@@ -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,
......
......@@ -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');
}
......@@ -317,7 +317,7 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v)
st->insert_failed,
st->drop,
st->early_drop,
st->icmp_error,
st->error,
st->expect_new,
st->expect_create,
......@@ -515,6 +515,14 @@ static ctl_table ip_ct_sysctl_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_COUNT,
.procname = "ip_conntrack_count",
.data = &ip_conntrack_count,
.maxlen = sizeof(int),
.mode = 0444,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS,
.procname = "ip_conntrack_buckets",
......@@ -816,19 +824,13 @@ static int init_or_cleanup(int init)
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;
......@@ -837,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. */
......@@ -880,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);
......
......@@ -146,7 +146,7 @@ check_for_demasq(struct sk_buff **pskb)
case IPPROTO_ICMP:
/* ICMP errors. */
protocol->error(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
ct = (struct ip_conntrack *)(*pskb)->nfct->master;
ct = (struct ip_conntrack *)(*pskb)->nfct;
if (ct) {
/* We only do SNAT in the compatibility layer.
So we can manipulate ICMP errors from
......@@ -187,7 +187,7 @@ check_for_demasq(struct sk_buff **pskb)
NULL, NULL, NULL);
/* Put back the reference gained from find_get */
nf_conntrack_put(&h->ctrack->infos[0]);
nf_conntrack_put(&h->ctrack->ct_general);
if (ret == NF_ACCEPT) {
struct ip_conntrack *ct;
ct = ip_conntrack_get(*pskb, &ctinfo);
......@@ -206,7 +206,7 @@ check_for_demasq(struct sk_buff **pskb)
} else {
if (h)
/* Put back the reference gained from find_get */
nf_conntrack_put(&h->ctrack->infos[0]);
nf_conntrack_put(&h->ctrack->ct_general);
ret = NF_ACCEPT;
}
......
......@@ -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
......@@ -77,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);
......@@ -90,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);
}
......@@ -106,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,
......@@ -145,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 };
......@@ -171,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 */
......@@ -193,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
......@@ -226,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;
}
......@@ -247,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;
}
......@@ -401,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;
......@@ -640,12 +615,10 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,
/* 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;
}
......@@ -669,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,
......@@ -697,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. */
......@@ -724,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;
......@@ -750,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);
......@@ -890,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
......@@ -995,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++) {
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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. */
......
......@@ -23,7 +23,8 @@ target(struct sk_buff **pskb,
If there is a real ct entry correspondig to this packet,
it'll hang aroun till timing out. We don't deal with it
for performance reasons. JK */
(*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
(*pskb)->nfct = &ip_conntrack_untracked.ct_general;
(*pskb)->nfctinfo = IP_CT_NEW;
nf_conntrack_get((*pskb)->nfct);
return IPT_CONTINUE;
......
......@@ -41,14 +41,14 @@ MODULE_DESCRIPTION("iptables REJECT target module");
/* If the original packet is part of a connection, but the connection
is not confirmed, our manufactured reply will not be associated
with it, so we need to do this manually. */
static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
static void connection_attach(struct sk_buff *new_skb, struct sk_buff *skb)
{
void (*attach)(struct sk_buff *, struct nf_ct_info *);
void (*attach)(struct sk_buff *, struct sk_buff *);
/* Avoid module unload race with ip_ct_attach being NULLed out */
if (nfct && (attach = ip_ct_attach) != NULL) {
if (skb->nfct && (attach = ip_ct_attach) != NULL) {
mb(); /* Just to be sure: must be read before executing this */
attach(new_skb, nfct);
attach(new_skb, skb);
}
}
......@@ -209,7 +209,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
if (nskb->len > dst_pmtu(nskb->dst))
goto free_nskb;
connection_attach(nskb, oldskb->nfct);
connection_attach(nskb, oldskb);
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
ip_finish_output);
......@@ -360,7 +360,7 @@ static void send_unreach(struct sk_buff *skb_in, int code)
icmph->checksum = ip_compute_csum((unsigned char *)icmph,
length - sizeof(struct iphdr));
connection_attach(nskb, skb_in->nfct);
connection_attach(nskb, skb_in);
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
ip_finish_output);
......
/*
* Implements a dummy match to allow attaching comments to rules
*
* 2003-05-13 Brad Fisher (brad@info-link.net)
*/
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_comment.h>
MODULE_AUTHOR("Brad Fisher <brad@info-link.net>");
MODULE_DESCRIPTION("iptables comment match module");
MODULE_LICENSE("GPL");
static int
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const void *matchinfo,
int offset,
int *hotdrop)
{
/* We always match */
return 1;
}
static int
checkentry(const char *tablename,
const struct ipt_ip *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
/* Check the size */
if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info)))
return 0;
return 1;
}
static struct ipt_match comment_match = {
.name = "comment",
.match = match,
.checkentry = checkentry,
.me = THIS_MODULE
};
static int __init init(void)
{
return ipt_register_match(&comment_match);
}
static void __exit fini(void)
{
ipt_unregister_match(&comment_match);
}
module_init(init);
module_exit(fini);
......@@ -35,7 +35,7 @@ match(const struct sk_buff *skb,
#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
if (ct == &ip_conntrack_untracked)
statebit = IPT_CONNTRACK_STATE_UNTRACKED;
else if (ct)
statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
......
......@@ -30,9 +30,9 @@ match(const struct sk_buff *skb,
enum ip_conntrack_info ctinfo;
unsigned int statebit;
if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
if (skb->nfct == &ip_conntrack_untracked.ct_general)
statebit = IPT_STATE_UNTRACKED;
else if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
else if (!ip_conntrack_get(skb, &ctinfo))
statebit = IPT_STATE_INVALID;
else
statebit = IPT_STATE_BIT(ctinfo);
......
......@@ -477,6 +477,7 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
/* Connection association is same as pre-frag packet */
to->nfct = from->nfct;
nf_conntrack_get(to->nfct);
to->nfctinfo = from->nfctinfo;
#ifdef CONFIG_BRIDGE_NETFILTER
nf_bridge_put(to->nf_bridge);
to->nf_bridge = from->nf_bridge;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment