/* decrement reference count on an expectation */
void ip_conntrack_expect_put(struct ip_conntrack_expect *exp);
-extern struct module *ip_conntrack_module;
+/* call to create an explicit dependency on ip_conntrack. */
+extern void need_ip_conntrack(void);
extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
const struct ip_conntrack_tuple *orig);
duprintf("check_entry: `%s' not found\n", t->u.user.name);
goto out;
}
- if (target->me)
- __MOD_INC_USE_COUNT(target->me);
+ if (!try_module_get((target->me))) {
+ ret = -ENOENT;
+ goto out_unlock;
+ }
t->u.kernel.target = target;
up(&arpt_mutex);
t->u.target_size
- sizeof(*t),
e->comefrom)) {
- if (t->u.kernel.target->me)
- __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
+ module_put(t->u.kernel.target->me);
duprintf("arp_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
(*i)++;
return 0;
+out_unlock:
+ up(&arpt_mutex);
out:
return ret;
}
if (t->u.kernel.target->destroy)
t->u.kernel.target->destroy(t->data,
t->u.target_size - sizeof(*t));
- if (t->u.kernel.target->me)
- __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
-
+ module_put(t->u.kernel.target->me);
return 0;
}
{
int ret;
- MOD_INC_USE_COUNT;
ret = down_interruptible(&arpt_mutex);
- if (ret != 0) {
- MOD_DEC_USE_COUNT;
+ if (ret != 0)
return ret;
- }
+
if (!list_named_insert(&arpt_target, target)) {
duprintf("arpt_register_target: `%s' already in list!\n",
target->name);
ret = -EINVAL;
- MOD_DEC_USE_COUNT;
}
up(&arpt_mutex);
return ret;
down(&arpt_mutex);
LIST_DELETE(&arpt_target, target);
up(&arpt_mutex);
- MOD_DEC_USE_COUNT;
}
int arpt_register_table(struct arpt_table *table)
static struct arpt_table_info bootstrap
= { 0, 0, 0, { 0 }, { 0 }, { } };
- MOD_INC_USE_COUNT;
newinfo = vmalloc(sizeof(struct arpt_table_info)
+ SMP_ALIGN(table->table->size) * NR_CPUS);
if (!newinfo) {
ret = -ENOMEM;
- MOD_DEC_USE_COUNT;
return ret;
}
memcpy(newinfo->entries, table->table->entries, table->table->size);
duprintf("arpt_register_table: translate table gives %d\n", ret);
if (ret != 0) {
vfree(newinfo);
- MOD_DEC_USE_COUNT;
return ret;
}
ret = down_interruptible(&arpt_mutex);
if (ret != 0) {
vfree(newinfo);
- MOD_DEC_USE_COUNT;
return ret;
}
free_unlock:
vfree(newinfo);
- MOD_DEC_USE_COUNT;
goto unlock;
}
ARPT_ENTRY_ITERATE(table->private->entries, table->private->size,
cleanup_entry, NULL);
vfree(table->private);
- MOD_DEC_USE_COUNT;
}
/* The built-in targets: standard (NULL) and error. */
int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
{
- MOD_INC_USE_COUNT;
-
WRITE_LOCK(&ip_conntrack_lock);
list_prepend(&helpers, me);
WRITE_UNLOCK(&ip_conntrack_lock);
/* Someone could be still looking at the helper in a bh. */
br_write_lock_bh(BR_NETPROTO_LOCK);
br_write_unlock_bh(BR_NETPROTO_LOCK);
-
- MOD_DEC_USE_COUNT;
}
/* Refresh conntrack for this many jiffies. */
#define DEBUGP(format, args...)
#endif
-struct module *ip_conntrack_module = THIS_MODULE;
MODULE_LICENSE("GPL");
static int kill_proto(const struct ip_conntrack *i, void *data)
}
list_prepend(&protocol_list, proto);
- MOD_INC_USE_COUNT;
out:
WRITE_UNLOCK(&ip_conntrack_lock);
/* Remove all contrack entries for this protocol */
ip_ct_selective_cleanup(kill_proto, &proto->proto);
-
- MOD_DEC_USE_COUNT;
}
static int __init init(void)
module_init(init);
module_exit(fini);
+/* Some modules need us, but don't depend directly on any symbol.
+ They should call this. */
+void need_ip_conntrack(void)
+{
+}
+
EXPORT_SYMBOL(ip_conntrack_protocol_register);
EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
EXPORT_SYMBOL(invert_tuplepr);
EXPORT_SYMBOL(ip_conntrack_alter_reply);
EXPORT_SYMBOL(ip_conntrack_destroyed);
EXPORT_SYMBOL(ip_conntrack_get);
-EXPORT_SYMBOL(ip_conntrack_module);
+EXPORT_SYMBOL(need_ip_conntrack);
EXPORT_SYMBOL(ip_conntrack_helper_register);
EXPORT_SYMBOL(ip_conntrack_helper_unregister);
EXPORT_SYMBOL(ip_ct_selective_cleanup);
if (me->me && !(me->flags & IP_NAT_HELPER_F_STANDALONE)) {
struct ip_conntrack_helper *ct_helper;
- if ((ct_helper = ip_ct_find_helper(&me->tuple))
- && ct_helper->me) {
- __MOD_INC_USE_COUNT(ct_helper->me);
+ if ((ct_helper = ip_ct_find_helper(&me->tuple))) {
+ if (!try_module_get(ct_helper->me))
+ return -EBUSY;
} else {
/* We are a NAT helper for protocol X. If we need
* respective conntrack helper for protoccol X, compute
sprintf(name, "ip_conntrack%s", tmp);
#ifdef CONFIG_KMOD
if (!request_module(name)
- && (ct_helper = ip_ct_find_helper(&me->tuple))
- && ct_helper->me) {
- __MOD_INC_USE_COUNT(ct_helper->me);
+ && (ct_helper = ip_ct_find_helper(&me->tuple))) {
+ if (!try_module_get(ct_helper->me))
+ return -EBUSY;
} else {
printk("unable to load module %s\n", name);
return -EBUSY;
WRITE_LOCK(&ip_nat_lock);
if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple))
ret = -EBUSY;
- else {
+ else
list_prepend(&helpers, me);
- MOD_INC_USE_COUNT;
- }
WRITE_UNLOCK(&ip_nat_lock);
return ret;
void ip_nat_helper_unregister(struct ip_nat_helper *me)
{
- int found = 0;
-
WRITE_LOCK(&ip_nat_lock);
/* Autoloading conntrack helper might have failed */
if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple)) {
LIST_DELETE(&helpers, me);
- found = 1;
}
WRITE_UNLOCK(&ip_nat_lock);
worse. --RR */
ip_ct_selective_cleanup(kill_helper, me);
- if (found)
- MOD_DEC_USE_COUNT;
-
/* If we are no standalone NAT helper, we need to decrement usage count
* on our conntrack helper */
if (me->me && !(me->flags & IP_NAT_HELPER_F_STANDALONE)) {
struct ip_conntrack_helper *ct_helper;
- if ((ct_helper = ip_ct_find_helper(&me->tuple))
- && ct_helper->me) {
- __MOD_DEC_USE_COUNT(ct_helper->me);
- }
+ if ((ct_helper = ip_ct_find_helper(&me->tuple)))
+ module_put(ct_helper->me);
#ifdef CONFIG_MODULES
else
printk("%s: unable to decrement usage count"
}
list_prepend(&protos, proto);
- MOD_INC_USE_COUNT;
-
out:
WRITE_UNLOCK(&ip_nat_lock);
return ret;
/* Someone could be still looking at the proto in a bh. */
br_write_lock_bh(BR_NETPROTO_LOCK);
br_write_unlock_bh(BR_NETPROTO_LOCK);
-
- MOD_DEC_USE_COUNT;
}
static int init_or_cleanup(int init)
{
int ret = 0;
+ need_ip_conntrack();
+
if (!init) goto cleanup;
ret = ip_nat_rule_init();
goto cleanup_localoutops;
}
#endif
- if (ip_conntrack_module)
- __MOD_INC_USE_COUNT(ip_conntrack_module);
return ret;
cleanup:
- if (ip_conntrack_module)
- __MOD_DEC_USE_COUNT(ip_conntrack_module);
#ifdef CONFIG_IP_NF_NAT_LOCAL
nf_unregister_hook(&ip_nat_local_in_ops);
cleanup_localoutops:
if (m->u.kernel.match->destroy)
m->u.kernel.match->destroy(m->data,
m->u.match_size - sizeof(*m));
-
- if (m->u.kernel.match->me)
- __MOD_DEC_USE_COUNT(m->u.kernel.match->me);
-
+ module_put(m->u.kernel.match->me);
return 0;
}
duprintf("check_match: `%s' not found\n", m->u.user.name);
return ret;
}
- if (match->me)
- __MOD_INC_USE_COUNT(match->me);
+ if (!try_module_get(match->me)) {
+ up(&ipt_mutex);
+ return -ENOENT;
+ }
m->u.kernel.match = match;
up(&ipt_mutex);
&& !m->u.kernel.match->checkentry(name, ip, m->data,
m->u.match_size - sizeof(*m),
hookmask)) {
- if (m->u.kernel.match->me)
- __MOD_DEC_USE_COUNT(m->u.kernel.match->me);
+ module_put(m->u.kernel.match->me);
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
return -EINVAL;
duprintf("check_entry: `%s' not found\n", t->u.user.name);
goto cleanup_matches;
}
- if (target->me)
- __MOD_INC_USE_COUNT(target->me);
+ if (!try_module_get(target->me)) {
+ up(&ipt_mutex);
+ ret = -ENOENT;
+ goto cleanup_matches;
+ }
t->u.kernel.target = target;
up(&ipt_mutex);
t->u.target_size
- sizeof(*t),
e->comefrom)) {
- if (t->u.kernel.target->me)
- __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
+ module_put(t->u.kernel.target->me);
duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
if (t->u.kernel.target->destroy)
t->u.kernel.target->destroy(t->data,
t->u.target_size - sizeof(*t));
- if (t->u.kernel.target->me)
- __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
-
+ module_put(t->u.kernel.target->me);
return 0;
}
{
int ret;
- MOD_INC_USE_COUNT;
ret = down_interruptible(&ipt_mutex);
- if (ret != 0) {
- MOD_DEC_USE_COUNT;
+ if (ret != 0)
return ret;
- }
+
if (!list_named_insert(&ipt_target, target)) {
duprintf("ipt_register_target: `%s' already in list!\n",
target->name);
ret = -EINVAL;
- MOD_DEC_USE_COUNT;
}
up(&ipt_mutex);
return ret;
down(&ipt_mutex);
LIST_DELETE(&ipt_target, target);
up(&ipt_mutex);
- MOD_DEC_USE_COUNT;
}
int
{
int ret;
- MOD_INC_USE_COUNT;
ret = down_interruptible(&ipt_mutex);
- if (ret != 0) {
- MOD_DEC_USE_COUNT;
+ if (ret != 0)
return ret;
- }
+
if (!list_named_insert(&ipt_match, match)) {
duprintf("ipt_register_match: `%s' already in list!\n",
match->name);
- MOD_DEC_USE_COUNT;
ret = -EINVAL;
}
up(&ipt_mutex);
down(&ipt_mutex);
LIST_DELETE(&ipt_match, match);
up(&ipt_mutex);
- MOD_DEC_USE_COUNT;
}
int ipt_register_table(struct ipt_table *table)
static struct ipt_table_info bootstrap
= { 0, 0, 0, { 0 }, { 0 }, { } };
- MOD_INC_USE_COUNT;
newinfo = vmalloc(sizeof(struct ipt_table_info)
+ SMP_ALIGN(table->table->size) * NR_CPUS);
- if (!newinfo) {
- ret = -ENOMEM;
- MOD_DEC_USE_COUNT;
- return ret;
- }
+ if (!newinfo)
+ return -ENOMEM;
+
memcpy(newinfo->entries, table->table->entries, table->table->size);
ret = translate_table(table->name, table->valid_hooks,
table->table->underflow);
if (ret != 0) {
vfree(newinfo);
- MOD_DEC_USE_COUNT;
return ret;
}
ret = down_interruptible(&ipt_mutex);
if (ret != 0) {
vfree(newinfo);
- MOD_DEC_USE_COUNT;
return ret;
}
free_unlock:
vfree(newinfo);
- MOD_DEC_USE_COUNT;
goto unlock;
}
IPT_ENTRY_ITERATE(table->private->entries, table->private->size,
cleanup_entry, NULL);
vfree(table->private);
- MOD_DEC_USE_COUNT;
}
/* Returns 1 if the port is matched by the range, 0 otherwise */
static int __init init(void)
{
- /* NULL if ip_conntrack not a module */
- if (ip_conntrack_module)
- __MOD_INC_USE_COUNT(ip_conntrack_module);
+ need_ip_conntrack();
return ipt_register_match(&conntrack_match);
}
static void __exit fini(void)
{
ipt_unregister_match(&conntrack_match);
- if (ip_conntrack_module)
- __MOD_DEC_USE_COUNT(ip_conntrack_module);
}
module_init(init);
static int __init init(void)
{
- /* NULL if ip_conntrack not a module */
- if (ip_conntrack_module)
- __MOD_INC_USE_COUNT(ip_conntrack_module);
+ need_ip_conntrack();
return ipt_register_match(&helper_match);
}
static void __exit fini(void)
{
ipt_unregister_match(&helper_match);
- if (ip_conntrack_module)
- __MOD_DEC_USE_COUNT(ip_conntrack_module);
}
module_init(init);
static int __init init(void)
{
- /* NULL if ip_conntrack not a module */
- if (ip_conntrack_module)
- __MOD_INC_USE_COUNT(ip_conntrack_module);
+ need_ip_conntrack();
return ipt_register_match(&state_match);
}
static void __exit fini(void)
{
ipt_unregister_match(&state_match);
- if (ip_conntrack_module)
- __MOD_DEC_USE_COUNT(ip_conntrack_module);
}
module_init(init);
if (m->u.kernel.match->destroy)
m->u.kernel.match->destroy(m->data,
m->u.match_size - sizeof(*m));
-
- if (m->u.kernel.match->me)
- __MOD_DEC_USE_COUNT(m->u.kernel.match->me);
-
+ module_put(m->u.kernel.match->me);
return 0;
}
// duprintf("check_match: `%s' not found\n", m->u.name);
return ret;
}
- if (match->me)
- __MOD_INC_USE_COUNT(match->me);
+ if (!try_module_get(match->me)) {
+ up(&ip6t_mutex);
+ return -ENOENT;
+ }
m->u.kernel.match = match;
up(&ip6t_mutex);
&& !m->u.kernel.match->checkentry(name, ipv6, m->data,
m->u.match_size - sizeof(*m),
hookmask)) {
- if (m->u.kernel.match->me)
- __MOD_DEC_USE_COUNT(m->u.kernel.match->me);
+ module_put(m->u.kernel.match->me);
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
return -EINVAL;
duprintf("check_entry: `%s' not found\n", t->u.user.name);
goto cleanup_matches;
}
- if (target->me)
- __MOD_INC_USE_COUNT(target->me);
+ if (!try_module_get(target->me)) {
+ up(&ip6t_mutex);
+ ret = -ENOENT;
+ goto cleanup_matches;
+ }
t->u.kernel.target = target;
up(&ip6t_mutex);
-
+ if (!t->u.kernel.target) {
+ ret = -EBUSY;
+ goto cleanup_matches;
+ }
if (t->u.kernel.target == &ip6t_standard_target) {
if (!standard_check(t, size)) {
ret = -EINVAL;
t->u.target_size
- sizeof(*t),
e->comefrom)) {
- if (t->u.kernel.target->me)
- __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
+ module_put(t->u.kernel.target->me);
duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
if (t->u.kernel.target->destroy)
t->u.kernel.target->destroy(t->data,
t->u.target_size - sizeof(*t));
- if (t->u.kernel.target->me)
- __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
-
+ module_put(t->u.kernel.target->me);
return 0;
}
{
int ret;
- MOD_INC_USE_COUNT;
ret = down_interruptible(&ip6t_mutex);
- if (ret != 0) {
- MOD_DEC_USE_COUNT;
+ if (ret != 0)
return ret;
- }
+
if (!list_named_insert(&ip6t_target, target)) {
duprintf("ip6t_register_target: `%s' already in list!\n",
target->name);
ret = -EINVAL;
- MOD_DEC_USE_COUNT;
}
up(&ip6t_mutex);
return ret;
down(&ip6t_mutex);
LIST_DELETE(&ip6t_target, target);
up(&ip6t_mutex);
- MOD_DEC_USE_COUNT;
}
int
{
int ret;
- MOD_INC_USE_COUNT;
ret = down_interruptible(&ip6t_mutex);
- if (ret != 0) {
- MOD_DEC_USE_COUNT;
+ if (ret != 0)
return ret;
- }
+
if (!list_named_insert(&ip6t_match, match)) {
duprintf("ip6t_register_match: `%s' already in list!\n",
match->name);
- MOD_DEC_USE_COUNT;
ret = -EINVAL;
}
up(&ip6t_mutex);
down(&ip6t_mutex);
LIST_DELETE(&ip6t_match, match);
up(&ip6t_mutex);
- MOD_DEC_USE_COUNT;
}
int ip6t_register_table(struct ip6t_table *table)
static struct ip6t_table_info bootstrap
= { 0, 0, 0, { 0 }, { 0 }, { }, { } };
- MOD_INC_USE_COUNT;
newinfo = vmalloc(sizeof(struct ip6t_table_info)
+ SMP_ALIGN(table->table->size) * NR_CPUS);
- if (!newinfo) {
- ret = -ENOMEM;
- MOD_DEC_USE_COUNT;
- return ret;
- }
+ if (!newinfo)
+ return -ENOMEM;
+
memcpy(newinfo->entries, table->table->entries, table->table->size);
ret = translate_table(table->name, table->valid_hooks,
table->table->underflow);
if (ret != 0) {
vfree(newinfo);
- MOD_DEC_USE_COUNT;
return ret;
}
ret = down_interruptible(&ip6t_mutex);
if (ret != 0) {
vfree(newinfo);
- MOD_DEC_USE_COUNT;
return ret;
}
free_unlock:
vfree(newinfo);
- MOD_DEC_USE_COUNT;
goto unlock;
}
IP6T_ENTRY_ITERATE(table->private->entries, table->private->size,
cleanup_entry, NULL);
vfree(table->private);
- MOD_DEC_USE_COUNT;
}
/* Returns 1 if the port is matched by the range, 0 otherwise */