* 26 Jan 2006: Harald Welte <laforge@netfilter.org>
* - restructure nf_conn (introduce nf_conn_help)
* - redesign 'features' how they were originally intended
+ * 26 Feb 2006: Pablo Neira Ayuso <pablo@eurodev.net>
+ * - add support for L3 protocol module load on demand.
*
* Derived from net/ipv4/netfilter/ip_conntrack_core.c
*/
static LIST_HEAD(unconfirmed);
static int nf_conntrack_vmalloc;
-static unsigned int nf_conntrack_next_id = 1;
-static unsigned int nf_conntrack_expect_next_id = 1;
+static unsigned int nf_conntrack_next_id;
+static unsigned int nf_conntrack_expect_next_id;
#ifdef CONFIG_NF_CONNTRACK_EVENTS
-struct notifier_block *nf_conntrack_chain;
-struct notifier_block *nf_conntrack_expect_chain;
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
DEBUGP("ecache: delivering events for %p\n", ecache->ct);
if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct)
&& ecache->events)
- notifier_call_chain(&nf_conntrack_chain, ecache->events,
+ atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events,
ecache->ct);
ecache->events = 0;
struct nf_conntrack_ecache *ecache;
int cpu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
ecache = &per_cpu(nf_conntrack_ecache, cpu);
if (ecache->ct)
nf_ct_put(ecache->ct);
/* allocated slab cache + modules which uses this slab cache */
int use;
- /* Initialization */
- int (*init_conntrack)(struct nf_conn *, u_int32_t);
-
} nf_ct_cache[NF_CT_F_NUM];
/* protect members of nf_ct_cache except of "use" */
preempt_disable();
p = __nf_ct_proto_find(l3proto, protocol);
- if (p) {
- if (!try_module_get(p->me))
- p = &nf_conntrack_generic_protocol;
- }
+ if (!try_module_get(p->me))
+ p = &nf_conntrack_generic_protocol;
preempt_enable();
return p;
preempt_disable();
p = __nf_ct_l3proto_find(l3proto);
- if (p) {
- if (!try_module_get(p->me))
- p = &nf_conntrack_generic_l3proto;
- }
+ if (!try_module_get(p->me))
+ p = &nf_conntrack_generic_l3proto;
preempt_enable();
return p;
module_put(p->me);
}
+int
+nf_ct_l3proto_try_module_get(unsigned short l3proto)
+{
+ int ret;
+ struct nf_conntrack_l3proto *p;
+
+retry: p = nf_ct_l3proto_find_get(l3proto);
+ if (p == &nf_conntrack_generic_l3proto) {
+ ret = request_module("nf_conntrack-%d", l3proto);
+ if (!ret)
+ goto retry;
+
+ return -EPROTOTYPE;
+ }
+
+ return 0;
+}
+
+void nf_ct_l3proto_module_put(unsigned short l3proto)
+{
+ struct nf_conntrack_l3proto *p;
+
+ preempt_disable();
+ p = __nf_ct_l3proto_find(l3proto);
+ preempt_enable();
+
+ module_put(p->me);
+}
+
static int nf_conntrack_hash_rnd_initted;
static unsigned int nf_conntrack_hash_rnd;
conntrack->master = exp->master;
#ifdef CONFIG_NF_CONNTRACK_MARK
conntrack->mark = exp->master->mark;
+#endif
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+ conntrack->secmark = exp->master->secmark;
#endif
nf_conntrack_get(&conntrack->master->ct_general);
NF_CT_STAT_INC(expect_new);
write_lock_bh(&nf_conntrack_lock);
+ /* Only update if this is not a fixed timeout */
+ if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) {
+ write_unlock_bh(&nf_conntrack_lock);
+ return;
+ }
+
/* If not in hash table, timer will not be active yet */
if (!nf_ct_is_confirmed(ct)) {
ct->timeout.expires = extra_jiffies;