2 * IP_MASQ_AUTOFW auto forwarding module
5 * $Id: ip_masq_autofw.c,v 1.3 1998/08/29 23:51:10 davem Exp $
7 * Author: Richard Lynch
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.
16 * Juan Jose Ciarlante : created this new file from ip_masq.c and ip_fw.c
17 * Juan Jose Ciarlante : modularized
18 * Juan Jose Ciarlante : use GFP_KERNEL when creating entries
19 * Juan Jose Ciarlante : call del_timer() when freeing entries (!)
25 #include <linux/config.h>
26 #include <linux/module.h>
27 #include <linux/types.h>
28 #include <linux/kernel.h>
29 #include <linux/slab.h>
30 #include <linux/errno.h>
31 #include <asm/system.h>
32 #include <linux/stat.h>
33 #include <linux/proc_fs.h>
35 #include <linux/init.h>
36 #include <linux/ip_fw.h>
37 #include <net/ip_masq.h>
38 #include <net/ip_masq_mod.h>
39 #include <linux/ip_masq.h>
41 #define IP_AUTOFW_EXPIRE 15*HZ
43 /* WARNING: bitwise equal to ip_autofw_user in linux/ip_masq.h */
45 struct ip_autofw
* next
;
57 struct timer_list timer
;
63 #ifdef CONFIG_IP_MASQ_DEBUG
65 MODULE_PARM(debug
, "i");
69 * Auto-forwarding table
72 static struct ip_autofw
* ip_autofw_hosts
= NULL
;
73 static struct ip_masq_mod
* mmod_self
= NULL
;
76 * Check if a masq entry should be created for a packet
79 static __inline__
struct ip_autofw
* ip_autofw_check_range (__u32 where
, __u16 port
, __u16 protocol
, int reqact
)
85 if (af
->type
==IP_FWD_RANGE
&&
88 protocol
==af
->protocol
&&
91 * It's ok to create masq entries after
92 * the timeout if we're in insecure mode
94 (af
->flags
& IP_AUTOFW_ACTIVE
|| !reqact
|| !(af
->flags
& IP_AUTOFW_SECURE
)) &&
95 (!(af
->flags
& IP_AUTOFW_SECURE
) || af
->lastcontact
==where
|| !reqact
))
102 static __inline__
struct ip_autofw
* ip_autofw_check_port (__u16 port
, __u16 protocol
)
104 struct ip_autofw
*af
;
109 if (af
->type
==IP_FWD_PORT
&& port
==af
->visible
&& protocol
==af
->protocol
)
116 static __inline__
struct ip_autofw
* ip_autofw_check_direct (__u16 port
, __u16 protocol
)
118 struct ip_autofw
*af
;
123 if (af
->type
==IP_FWD_DIRECT
&& af
->low
<=port
&& af
->high
>=port
)
130 static __inline__
void ip_autofw_update_out (__u32 who
, __u32 where
, __u16 port
, __u16 protocol
)
132 struct ip_autofw
*af
;
137 if (af
->type
==IP_FWD_RANGE
&& af
->ctlport
==port
&& af
->ctlproto
==protocol
)
139 if (af
->flags
& IP_AUTOFW_USETIME
)
141 mod_timer(&af
->timer
,
142 jiffies
+IP_AUTOFW_EXPIRE
);
144 af
->flags
|=IP_AUTOFW_ACTIVE
;
145 af
->lastcontact
=where
;
153 static __inline__
void ip_autofw_update_in (__u32 where
, __u16 port
, __u16 protocol
)
155 struct ip_autofw
*af
;
156 af
=ip_autofw_check_range(where
, port
,protocol
);
159 mod_timer(&af
->timer
, jiffies
+IP_AUTOFW_EXPIRE
);
165 static __inline__
void ip_autofw_expire(unsigned long data
)
167 struct ip_autofw
* af
;
168 af
=(struct ip_autofw
*) data
;
169 af
->flags
&= ~IP_AUTOFW_ACTIVE
;
172 if (af
->flags
& IP_AUTOFW_SECURE
)
178 static __inline__
int ip_autofw_add(struct ip_autofw_user
* af
)
180 struct ip_autofw
* newaf
;
181 newaf
= kmalloc( sizeof(struct ip_autofw
), GFP_KERNEL
);
182 init_timer(&newaf
->timer
);
185 printk("ip_autofw_add: malloc said no\n");
191 memcpy(newaf
, af
, sizeof(struct ip_autofw_user
));
192 newaf
->timer
.data
= (unsigned long) newaf
;
193 newaf
->timer
.function
= ip_autofw_expire
;
194 newaf
->timer
.expires
= 0;
195 newaf
->lastcontact
=0;
196 newaf
->next
=ip_autofw_hosts
;
197 ip_autofw_hosts
=newaf
;
198 ip_masq_mod_inc_nent(mmod_self
);
202 static __inline__
int ip_autofw_del(struct ip_autofw_user
* af
)
204 struct ip_autofw
** af_p
, *curr
;
206 for (af_p
=&ip_autofw_hosts
, curr
=*af_p
; (curr
=*af_p
); af_p
= &(*af_p
)->next
) {
207 if (af
->type
== curr
->type
&&
208 af
->low
== curr
->low
&&
209 af
->high
== curr
->high
&&
210 af
->hidden
== curr
->hidden
&&
211 af
->visible
== curr
->visible
&&
212 af
->protocol
== curr
->protocol
&&
213 af
->where
== curr
->where
&&
214 af
->ctlproto
== curr
->ctlproto
&&
215 af
->ctlport
== curr
->ctlport
)
217 ip_masq_mod_dec_nent(mmod_self
);
219 if (af
->flags
&IP_AUTOFW_ACTIVE
)
220 del_timer(&curr
->timer
);
221 kfree_s(curr
,sizeof(struct ip_autofw
));
230 static __inline__
int ip_autofw_flush(void)
232 struct ip_autofw
* af
;
234 while (ip_autofw_hosts
)
237 ip_masq_mod_dec_nent(mmod_self
);
238 ip_autofw_hosts
=ip_autofw_hosts
->next
;
239 if (af
->flags
&IP_AUTOFW_ACTIVE
)
240 del_timer(&af
->timer
);
241 kfree_s(af
,sizeof(struct ip_autofw
));
248 * Methods for registered object
251 static int autofw_ctl(int optname
, struct ip_masq_ctl
*mctl
, int optlen
)
253 struct ip_autofw_user
*af
= &mctl
->u
.autofw_user
;
255 switch (mctl
->m_cmd
) {
256 case IP_MASQ_CMD_ADD
:
257 case IP_MASQ_CMD_INSERT
:
258 if (optlen
<sizeof(*af
))
260 return ip_autofw_add(af
);
261 case IP_MASQ_CMD_DEL
:
262 if (optlen
<sizeof(*af
))
264 return ip_autofw_del(af
);
265 case IP_MASQ_CMD_FLUSH
:
266 return ip_autofw_flush();
273 static int autofw_out_update(const struct sk_buff
*skb
, const struct iphdr
*iph
, struct ip_masq
*ms
)
275 const __u16
*portp
= (__u16
*)&(((char *)iph
)[iph
->ihl
*4]);
277 * Update any ipautofw entries ...
280 ip_autofw_update_out(iph
->saddr
, iph
->daddr
, portp
[1], iph
->protocol
);
281 return IP_MASQ_MOD_NOP
;
284 static struct ip_masq
* autofw_out_create(const struct sk_buff
*skb
, const struct iphdr
*iph
, __u32 maddr
)
286 const __u16
*portp
= (__u16
*)&(((char *)iph
)[iph
->ihl
*4]);
288 * If the source port is supposed to match the masq port, then
292 if (ip_autofw_check_direct(portp
[1],iph
->protocol
)) {
293 return ip_masq_new(iph
->protocol
,
295 iph
->saddr
, portp
[0],
296 iph
->daddr
, portp
[1],
303 static int autofw_in_update(const struct sk_buff
*skb
, const struct iphdr
*iph
, __u16
*portp
, struct ip_masq
*ms
)
305 const __u16
*portp
= (__u16
*)&(((char *)iph
)[iph
->ihl
*4]);
306 ip_autofw_update_in(iph
->saddr
, portp
[1], iph
->protocol
);
307 return IP_MASQ_MOD_NOP
;
311 static int autofw_in_rule(const struct sk_buff
*skb
, const struct iphdr
*iph
)
313 const __u16
*portp
= (__u16
*)&(((char *)iph
)[iph
->ihl
*4]);
314 return (ip_autofw_check_range(iph
->saddr
, portp
[1], iph
->protocol
, 0)
315 || ip_autofw_check_direct(portp
[1], iph
->protocol
)
316 || ip_autofw_check_port(portp
[1], iph
->protocol
));
319 static struct ip_masq
* autofw_in_create(const struct sk_buff
*skb
, const struct iphdr
*iph
, __u32 maddr
)
321 const __u16
*portp
= (__u16
*)&(((char *)iph
)[iph
->ihl
*4]);
322 struct ip_autofw
*af
;
324 if ((af
=ip_autofw_check_range(iph
->saddr
, portp
[1], iph
->protocol
, 0))) {
325 IP_MASQ_DEBUG(1-debug
, "autofw_check_range HIT\n");
326 return ip_masq_new(iph
->protocol
,
329 iph
->saddr
, portp
[0],
332 if ((af
=ip_autofw_check_port(portp
[1], iph
->protocol
)) ) {
333 IP_MASQ_DEBUG(1-debug
, "autofw_check_port HIT\n");
334 return ip_masq_new(iph
->protocol
,
335 maddr
, htons(af
->visible
),
336 af
->where
, htons(af
->hidden
),
337 iph
->saddr
, portp
[0],
343 #ifdef CONFIG_PROC_FS
344 static int autofw_procinfo(char *buffer
, char **start
, off_t offset
,
345 int length
, int unused
)
347 off_t pos
=0, begin
=0;
348 struct ip_autofw
* af
;
351 len
=sprintf(buffer
,"Type Prot Low High Vis Hid Where Last CPto CPrt Timer Flags\n");
353 for(af
= ip_autofw_hosts
; af
; af
= af
->next
)
355 len
+=sprintf(buffer
+len
,"%4X %4X %04X-%04X/%04X %04X %08lX %08lX %04X %04X %6lu %4X\n",
363 ntohl(af
->lastcontact
),
366 (af
->timer
.expires
<jiffies
? 0 : af
->timer
.expires
-jiffies
),
375 if(pos
>offset
+length
)
378 *start
=buffer
+(offset
-begin
);
385 static struct proc_dir_entry autofw_proc_entry
= {
387 S_IFREG
| S_IRUGO
, 1, 0, 0,
388 0, &proc_net_inode_operations
,
392 #define proc_ent &autofw_proc_entry
393 #else /* !CONFIG_PROC_FS */
395 #define proc_ent NULL
399 #define autofw_in_update NULL
400 #define autofw_out_rule NULL
401 #define autofw_mod_init NULL
402 #define autofw_mod_done NULL
404 static struct ip_masq_mod autofw_mod
= {
408 ATOMIC_INIT(0), /* nent */
409 ATOMIC_INIT(0), /* refcnt */
422 __initfunc(int ip_autofw_init(void))
424 return register_ip_masq_mod ((mmod_self
=&autofw_mod
));
427 int ip_autofw_done(void)
429 return unregister_ip_masq_mod(&autofw_mod
);
435 int init_module(void)
437 if (ip_autofw_init() != 0)
442 void cleanup_module(void)
444 if (ip_autofw_done() != 0)
445 printk(KERN_INFO
"ip_autofw_done(): can't remove module");