2 * IP_MASQ_MOD masq modules support
5 * Author: Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
7 * $Id: ip_masq_mod.c,v 1.5 1998/08/29 23:51:09 davem Exp $
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
15 * Cyrus Durgin: fixed kerneld stuff for kmod.
18 #include <linux/config.h>
19 #include <linux/module.h>
20 #include <linux/types.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <net/ip_masq.h>
24 #include <net/ip_masq_mod.h>
26 #include <linux/ip_masq.h>
28 #include <linux/kmod.h>
31 EXPORT_SYMBOL(register_ip_masq_mod
);
32 EXPORT_SYMBOL(unregister_ip_masq_mod
);
33 EXPORT_SYMBOL(ip_masq_mod_lkp_link
);
34 EXPORT_SYMBOL(ip_masq_mod_lkp_unlink
);
37 static spinlock_t masq_mod_lock
= SPIN_LOCK_UNLOCKED
;
41 * Base pointer for registered modules
43 struct ip_masq_mod
* ip_masq_mod_reg_base
= NULL
;
46 * Base pointer for lookup (subset of above, a module could be
47 * registered, but it could have no active rule); will avoid
48 * unnecessary lookups.
50 struct ip_masq_mod
* ip_masq_mod_lkp_base
= NULL
;
52 int ip_masq_mod_register_proc(struct ip_masq_mod
*mmod
)
57 struct proc_dir_entry
*ent
= mmod
->mmod_proc_ent
;
62 ent
->name
= mmod
->mmod_name
;
63 ent
->namelen
= strlen (mmod
->mmod_name
);
65 ret
= ip_masq_proc_register(ent
);
66 if (ret
) mmod
->mmod_proc_ent
= NULL
;
74 void ip_masq_mod_unregister_proc(struct ip_masq_mod
*mmod
)
77 struct proc_dir_entry
*ent
= mmod
->mmod_proc_ent
;
80 ip_masq_proc_unregister(ent
);
85 * Link/unlink object for lookups
88 int ip_masq_mod_lkp_unlink(struct ip_masq_mod
*mmod
)
90 struct ip_masq_mod
**mmod_p
;
92 write_lock_bh(&masq_mod_lock
);
94 for (mmod_p
= &ip_masq_mod_lkp_base
; *mmod_p
; mmod_p
= &(*mmod_p
)->next
)
95 if (mmod
== (*mmod_p
)) {
98 write_unlock_bh(&masq_mod_lock
);
102 write_unlock_bh(&masq_mod_lock
);
106 int ip_masq_mod_lkp_link(struct ip_masq_mod
*mmod
)
108 write_lock_bh(&masq_mod_lock
);
110 mmod
->next
= ip_masq_mod_lkp_base
;
111 ip_masq_mod_lkp_base
=mmod
;
113 write_unlock_bh(&masq_mod_lock
);
117 int register_ip_masq_mod(struct ip_masq_mod
*mmod
)
120 IP_MASQ_ERR("register_ip_masq_mod(): NULL arg\n");
123 if (!mmod
->mmod_name
) {
124 IP_MASQ_ERR("register_ip_masq_mod(): NULL mmod_name\n");
127 ip_masq_mod_register_proc(mmod
);
129 mmod
->next_reg
= ip_masq_mod_reg_base
;
130 ip_masq_mod_reg_base
=mmod
;
135 int unregister_ip_masq_mod(struct ip_masq_mod
*mmod
)
137 struct ip_masq_mod
**mmod_p
;
140 IP_MASQ_ERR( "unregister_ip_masq_mod(): NULL arg\n");
145 * Only allow unregistration if it is not referenced
147 if (atomic_read(&mmod
->refcnt
)) {
148 IP_MASQ_ERR( "unregister_ip_masq_mod(): is in use by %d guys. failed\n",
149 atomic_read(&mmod
->refcnt
));
154 * Must be already unlinked from lookup list
157 IP_MASQ_WARNING("MASQ: unregistering \"%s\" while in lookup list.fixed.",
159 ip_masq_mod_lkp_unlink(mmod
);
162 for (mmod_p
= &ip_masq_mod_reg_base
; *mmod_p
; mmod_p
= &(*mmod_p
)->next_reg
)
163 if (mmod
== (*mmod_p
)) {
164 ip_masq_mod_unregister_proc(mmod
);
165 *mmod_p
= mmod
->next_reg
;
169 IP_MASQ_ERR("unregister_ip_masq_mod(%s): not linked \n", mmod
->mmod_name
);
173 int ip_masq_mod_in_rule(const struct sk_buff
*skb
, const struct iphdr
*iph
)
175 struct ip_masq_mod
*mmod
;
176 int ret
= IP_MASQ_MOD_NOP
;
178 for (mmod
=ip_masq_mod_lkp_base
;mmod
;mmod
=mmod
->next
) {
179 if (!mmod
->mmod_in_rule
) continue;
180 switch (ret
=mmod
->mmod_in_rule(skb
, iph
)) {
181 case IP_MASQ_MOD_NOP
:
183 case IP_MASQ_MOD_ACCEPT
:
184 case IP_MASQ_MOD_REJECT
:
192 int ip_masq_mod_out_rule(const struct sk_buff
*skb
, const struct iphdr
*iph
)
194 struct ip_masq_mod
*mmod
;
195 int ret
= IP_MASQ_MOD_NOP
;
197 for (mmod
=ip_masq_mod_lkp_base
;mmod
;mmod
=mmod
->next
) {
198 if (!mmod
->mmod_out_rule
) continue;
199 switch (ret
=mmod
->mmod_out_rule(skb
, iph
)) {
200 case IP_MASQ_MOD_NOP
:
202 case IP_MASQ_MOD_ACCEPT
:
203 case IP_MASQ_MOD_REJECT
:
211 struct ip_masq
* ip_masq_mod_in_create(const struct sk_buff
*skb
, const struct iphdr
*iph
, __u32 maddr
)
213 struct ip_masq_mod
*mmod
;
214 struct ip_masq
*ms
= NULL
;
216 for (mmod
=ip_masq_mod_lkp_base
;mmod
;mmod
=mmod
->next
) {
217 if (!mmod
->mmod_in_create
) continue;
218 if ((ms
=mmod
->mmod_in_create(skb
, iph
, maddr
))) {
226 struct ip_masq
* ip_masq_mod_out_create(const struct sk_buff
*skb
, const struct iphdr
*iph
, __u32 maddr
)
228 struct ip_masq_mod
*mmod
;
229 struct ip_masq
*ms
= NULL
;
231 for (mmod
=ip_masq_mod_lkp_base
;mmod
;mmod
=mmod
->next
) {
232 if (!mmod
->mmod_out_create
) continue;
233 if ((ms
=mmod
->mmod_out_create(skb
, iph
, maddr
))) {
241 int ip_masq_mod_in_update(const struct sk_buff
*skb
, const struct iphdr
*iph
, struct ip_masq
*ms
)
243 struct ip_masq_mod
*mmod
;
244 int ret
= IP_MASQ_MOD_NOP
;
246 for (mmod
=ip_masq_mod_lkp_base
;mmod
;mmod
=mmod
->next
) {
247 if (!mmod
->mmod_in_update
) continue;
248 switch (ret
=mmod
->mmod_in_update(skb
, iph
, ms
)) {
249 case IP_MASQ_MOD_NOP
:
251 case IP_MASQ_MOD_ACCEPT
:
252 case IP_MASQ_MOD_REJECT
:
260 int ip_masq_mod_out_update(const struct sk_buff
*skb
, const struct iphdr
*iph
, struct ip_masq
*ms
)
262 struct ip_masq_mod
*mmod
;
263 int ret
= IP_MASQ_MOD_NOP
;
265 for (mmod
=ip_masq_mod_lkp_base
;mmod
;mmod
=mmod
->next
) {
266 if (!mmod
->mmod_out_update
) continue;
267 switch (ret
=mmod
->mmod_out_update(skb
, iph
, ms
)) {
268 case IP_MASQ_MOD_NOP
:
270 case IP_MASQ_MOD_ACCEPT
:
271 case IP_MASQ_MOD_REJECT
:
279 struct ip_masq_mod
* ip_masq_mod_getbyname(const char *mmod_name
)
281 struct ip_masq_mod
* mmod
;
283 IP_MASQ_DEBUG(1, "searching mmod_name \"%s\"\n", mmod_name
);
285 for (mmod
=ip_masq_mod_reg_base
; mmod
; mmod
=mmod
->next_reg
) {
286 if (mmod
->mmod_ctl
&& *(mmod_name
)
287 && (strcmp(mmod_name
, mmod
->mmod_name
)==0)) {
296 * Module control entry
298 int ip_masq_mod_ctl(int optname
, struct ip_masq_ctl
*mctl
, int optlen
)
300 struct ip_masq_mod
* mmod
;
302 char kmod_name
[IP_MASQ_TNAME_MAX
+8];
305 mctl
->m_tname
[IP_MASQ_TNAME_MAX
-1] = 0;
307 mmod
= ip_masq_mod_getbyname(mctl
->m_tname
);
309 return mmod
->mmod_ctl(optname
, mctl
, optlen
);
311 sprintf(kmod_name
,"ip_masq_%s", mctl
->m_tname
);
313 IP_MASQ_DEBUG(1, "About to request \"%s\" module\n", kmod_name
);
316 * Let sleep for a while ...
318 request_module(kmod_name
);
319 mmod
= ip_masq_mod_getbyname(mctl
->m_tname
);
321 return mmod
->mmod_ctl(optname
, mctl
, optlen
);