pre-2.3.4..
[davej-history.git] / net / ipv4 / ip_masq_autofw.c
blobd2a1729c5386a5ff4af8785d8d47620d55c77b0d
1 /*
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.
15 * Fixes:
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 (!)
20 * FIXME:
21 * - implement refcnt
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>
34 #include <linux/if.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 */
44 struct ip_autofw {
45 struct ip_autofw * next;
46 __u16 type;
47 __u16 low;
48 __u16 hidden;
49 __u16 high;
50 __u16 visible;
51 __u16 protocol;
52 __u32 lastcontact;
53 __u32 where;
54 __u16 ctlproto;
55 __u16 ctlport;
56 __u16 flags;
57 struct timer_list timer;
61 * Debug level
63 #ifdef CONFIG_IP_MASQ_DEBUG
64 static int debug=0;
65 MODULE_PARM(debug, "i");
66 #endif
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)
81 struct ip_autofw *af;
82 af=ip_autofw_hosts;
83 port=ntohs(port);
84 while (af) {
85 if (af->type==IP_FWD_RANGE &&
86 port>=af->low &&
87 port<=af->high &&
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))
96 return(af);
97 af=af->next;
99 return(NULL);
102 static __inline__ struct ip_autofw * ip_autofw_check_port (__u16 port, __u16 protocol)
104 struct ip_autofw *af;
105 af=ip_autofw_hosts;
106 port=ntohs(port);
107 while (af)
109 if (af->type==IP_FWD_PORT && port==af->visible && protocol==af->protocol)
110 return(af);
111 af=af->next;
113 return(NULL);
116 static __inline__ struct ip_autofw * ip_autofw_check_direct (__u16 port, __u16 protocol)
118 struct ip_autofw *af;
119 af=ip_autofw_hosts;
120 port=ntohs(port);
121 while (af)
123 if (af->type==IP_FWD_DIRECT && af->low<=port && af->high>=port)
124 return(af);
125 af=af->next;
127 return(NULL);
130 static __inline__ void ip_autofw_update_out (__u32 who, __u32 where, __u16 port, __u16 protocol)
132 struct ip_autofw *af;
133 af=ip_autofw_hosts;
134 port=ntohs(port);
135 while (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;
146 af->where=who;
148 af=af->next;
152 #if 0
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);
157 if (af)
159 mod_timer(&af->timer, jiffies+IP_AUTOFW_EXPIRE);
162 #endif
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;
170 af->timer.expires=0;
171 af->lastcontact=0;
172 if (af->flags & IP_AUTOFW_SECURE)
173 af->where=0;
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);
183 if ( newaf == NULL )
185 printk("ip_autofw_add: malloc said no\n");
186 return( ENOMEM );
189 MOD_INC_USE_COUNT;
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);
199 return(0);
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);
218 *af_p = curr->next;
219 if (af->flags&IP_AUTOFW_ACTIVE)
220 del_timer(&curr->timer);
221 kfree_s(curr,sizeof(struct ip_autofw));
222 MOD_DEC_USE_COUNT;
223 return 0;
225 curr=curr->next;
227 return EINVAL;
230 static __inline__ int ip_autofw_flush(void)
232 struct ip_autofw * af;
234 while (ip_autofw_hosts)
236 af=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));
242 MOD_DEC_USE_COUNT;
244 return(0);
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))
259 return EINVAL;
260 return ip_autofw_add(af);
261 case IP_MASQ_CMD_DEL:
262 if (optlen<sizeof(*af))
263 return EINVAL;
264 return ip_autofw_del(af);
265 case IP_MASQ_CMD_FLUSH:
266 return ip_autofw_flush();
269 return EINVAL;
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
289 * make it so
292 if (ip_autofw_check_direct(portp[1],iph->protocol)) {
293 return ip_masq_new(iph->protocol,
294 maddr, portp[0],
295 iph->saddr, portp[0],
296 iph->daddr, portp[1],
299 return NULL;
302 #if 0
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;
309 #endif
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,
327 maddr, portp[1],
328 af->where, portp[1],
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],
340 return NULL;
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;
349 int len=0;
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",
356 af->type,
357 af->protocol,
358 af->low,
359 af->high,
360 af->visible,
361 af->hidden,
362 ntohl(af->where),
363 ntohl(af->lastcontact),
364 af->ctlproto,
365 af->ctlport,
366 (af->timer.expires<jiffies ? 0 : af->timer.expires-jiffies),
367 af->flags);
369 pos=begin+len;
370 if(pos<offset)
372 len=0;
373 begin=pos;
375 if(pos>offset+length)
376 break;
378 *start=buffer+(offset-begin);
379 len-=(offset-begin);
380 if(len>length)
381 len=length;
382 return len;
385 static struct proc_dir_entry autofw_proc_entry = {
386 0, 0, NULL,
387 S_IFREG | S_IRUGO, 1, 0, 0,
388 0, &proc_net_inode_operations,
389 autofw_procinfo
392 #define proc_ent &autofw_proc_entry
393 #else /* !CONFIG_PROC_FS */
395 #define proc_ent NULL
396 #endif
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 = {
405 NULL, /* next */
406 NULL, /* next_reg */
407 "autofw", /* name */
408 ATOMIC_INIT(0), /* nent */
409 ATOMIC_INIT(0), /* refcnt */
410 proc_ent,
411 autofw_ctl,
412 autofw_mod_init,
413 autofw_mod_done,
414 autofw_in_rule,
415 autofw_in_update,
416 autofw_in_create,
417 autofw_out_rule,
418 autofw_out_update,
419 autofw_out_create,
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);
432 #ifdef MODULE
433 EXPORT_NO_SYMBOLS;
435 int init_module(void)
437 if (ip_autofw_init() != 0)
438 return -EIO;
439 return 0;
442 void cleanup_module(void)
444 if (ip_autofw_done() != 0)
445 printk(KERN_INFO "ip_autofw_done(): can't remove module");
448 #endif /* MODULE */