2 * IP_MASQ_PORTFW masquerading module
5 * $Id: ip_masq_portfw.c,v 1.3 1998/12/08 05:42:12 davem Exp $
7 * Author: Steven Clarke <steven.clarke@monmouth.demon.co.uk>
10 * Juan Jose Ciarlante : created this new file from ip_masq.c and ip_fw.c
11 * Juan Jose Ciarlante : modularized
12 * Juan Jose Ciarlante : use GFP_KERNEL
13 * Juan Jose Ciarlante : locking
17 #include <linux/config.h>
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/list.h>
24 #include <linux/ip_fw.h>
25 #include <linux/ip_masq.h>
26 #include <net/ip_masq.h>
27 #include <net/ip_masq_mod.h>
28 #include <linux/proc_fs.h>
29 #include <linux/init.h>
31 #define IP_PORTFW_PORT_MIN 1
32 #define IP_PORTFW_PORT_MAX 60999
35 struct list_head list
;
38 atomic_t pref_cnt
; /* pref "counter" down to 0 */
39 int pref
; /* user set pref */
42 static struct ip_masq_mod
*mmod_self
= NULL
;
46 #ifdef CONFIG_IP_MASQ_DEBUG
48 MODULE_PARM(debug
, "i");
55 static spinlock_t portfw_lock
= SPIN_LOCK_UNLOCKED
;
58 static struct list_head portfw_list
[2];
59 static __inline__
int portfw_idx(int protocol
)
61 return (protocol
==IPPROTO_TCP
);
66 * Delete forwarding entry(s):
67 * called from _DEL, u-space.
68 * . "relaxed" match, except for lport
72 static __inline__
int ip_portfw_del(__u16 protocol
, __u16 lport
, __u32 laddr
, __u16 rport
, __u32 raddr
)
74 int prot
= portfw_idx(protocol
);
76 struct list_head
*entry
;
77 struct list_head
*list
= &portfw_list
[prot
];
80 nent
= atomic_read(&mmod_self
->mmod_nent
);
82 write_lock_bh(&portfw_lock
);
84 for (entry
=list
->next
;entry
!= list
;entry
= entry
->next
) {
85 n
= list_entry(entry
, struct ip_portfw
, list
);
86 if (n
->lport
== lport
&&
87 (!laddr
|| n
->laddr
== laddr
) &&
88 (!raddr
|| n
->raddr
== raddr
) &&
89 (!rport
|| n
->rport
== rport
)) {
91 ip_masq_mod_dec_nent(mmod_self
);
92 kfree_s(n
, sizeof(struct ip_portfw
));
96 write_unlock_bh(&portfw_lock
);
98 return nent
==atomic_read(&mmod_self
->mmod_nent
)? ESRCH
: 0;
103 * called from _FLUSH, u-space.
105 static __inline__
void ip_portfw_flush(void)
112 write_lock_bh(&portfw_lock
);
114 for (prot
= 0; prot
< 2;prot
++) {
115 l
= &portfw_list
[prot
];
116 while((e
=l
->next
) != l
) {
117 ip_masq_mod_dec_nent(mmod_self
);
118 n
= list_entry (e
, struct ip_portfw
, list
);
120 kfree_s(n
, sizeof (*n
));
125 write_unlock_bh(&portfw_lock
);
129 * Lookup routine for lport,laddr match
130 * must be called with locked tables
132 static __inline__
struct ip_portfw
*ip_portfw_lookup(__u16 protocol
, __u16 lport
, __u32 laddr
, __u32
*daddr_p
, __u16
*dport_p
)
134 int prot
= portfw_idx(protocol
);
136 struct ip_portfw
*n
= NULL
;
137 struct list_head
*l
, *e
;
139 l
= &portfw_list
[prot
];
141 for (e
=l
->next
;e
!=l
;e
=e
->next
) {
142 n
= list_entry(e
, struct ip_portfw
, list
);
143 if (lport
== n
->lport
&& laddr
== n
->laddr
) {
144 /* Please be nice, don't pass only a NULL dport */
159 * Edit routine for lport,[laddr], [raddr], [rport] match
160 * By now, only called from u-space
162 static __inline__
int ip_portfw_edit(__u16 protocol
, __u16 lport
, __u32 laddr
, __u16 rport
, __u32 raddr
, int pref
)
164 int prot
= portfw_idx(protocol
);
166 struct ip_portfw
*n
= NULL
;
167 struct list_head
*l
, *e
;
171 read_lock_bh(&portfw_lock
);
173 l
= &portfw_list
[prot
];
175 for (e
=l
->next
;e
!=l
;e
=e
->next
) {
176 n
= list_entry(e
, struct ip_portfw
, list
);
177 if (lport
== n
->lport
&&
178 (!laddr
|| laddr
== n
->laddr
) &&
179 (!rport
|| rport
== n
->rport
) &&
180 (!raddr
|| raddr
== n
->raddr
)) {
182 atomic_set(&n
->pref_cnt
, pref
);
187 read_unlock_bh(&portfw_lock
);
194 * called from _ADD, u-space.
195 * must return 0 or +errno
197 static __inline__
int ip_portfw_add(__u16 protocol
, __u16 lport
, __u32 laddr
, __u16 rport
, __u32 raddr
, int pref
)
199 struct ip_portfw
*npf
;
200 int prot
= portfw_idx(protocol
);
205 if (ip_portfw_edit(protocol
, lport
, laddr
, rport
, raddr
, pref
)) {
213 npf
= (struct ip_portfw
*) kmalloc(sizeof(struct ip_portfw
), GFP_KERNEL
);
219 memset(npf
, 0, sizeof(*npf
));
227 atomic_set(&npf
->pref_cnt
, npf
->pref
);
228 INIT_LIST_HEAD(&npf
->list
);
230 write_lock_bh(&portfw_lock
);
235 list_add(&npf
->list
, &portfw_list
[prot
]);
237 write_unlock_bh(&portfw_lock
);
239 ip_masq_mod_inc_nent(mmod_self
);
245 static __inline__
int portfw_ctl(int optname
, struct ip_masq_ctl
*mctl
, int optlen
)
247 struct ip_portfw_user
*mm
= &mctl
->u
.portfw_user
;
249 int arglen
= optlen
- IP_MASQ_CTL_BSIZE
;
253 IP_MASQ_DEBUG(1-debug
, "ip_masq_user_ctl(len=%d/%d|%d/%d)\n",
260 * Yes, I'm a bad guy ...
262 if (arglen
!= sizeof(*mm
) && optlen
!= sizeof(*mctl
))
266 * Don't trust the lusers - plenty of error checking!
269 IP_MASQ_DEBUG(1-debug
, "ip_masq_portfw_ctl(cmd=%d)\n", cmd
);
273 case IP_MASQ_CMD_NONE
:
275 case IP_MASQ_CMD_FLUSH
:
278 if (htons(mm
->lport
) < IP_PORTFW_PORT_MIN
|| htons(mm
->lport
) > IP_PORTFW_PORT_MAX
)
281 if (mm
->protocol
!=IPPROTO_TCP
&& mm
->protocol
!=IPPROTO_UDP
)
286 case IP_MASQ_CMD_ADD
:
287 ret
= ip_portfw_add(mm
->protocol
,
288 mm
->lport
, mm
->laddr
,
289 mm
->rport
, mm
->raddr
,
293 case IP_MASQ_CMD_DEL
:
294 ret
= ip_portfw_del(mm
->protocol
,
295 mm
->lport
, mm
->laddr
,
296 mm
->rport
, mm
->raddr
);
298 case IP_MASQ_CMD_FLUSH
:
311 #ifdef CONFIG_PROC_FS
313 static int portfw_procinfo(char *buffer
, char **start
, off_t offset
,
314 int length
, int unused
)
317 struct ip_portfw
*pf
;
318 struct list_head
*l
, *e
;
326 sprintf(temp
, "Prot LAddr LPort > RAddr RPort PrCnt Pref");
327 len
= sprintf(buffer
, "%-63s\n", temp
);
331 read_lock_bh(&portfw_lock
);
333 for(ind
= 0; ind
< 2; ind
++)
335 l
= &portfw_list
[ind
];
336 for (e
=l
->next
; e
!=l
; e
=e
->next
)
338 pf
= list_entry(e
, struct ip_portfw
, list
);
345 sprintf(temp
,"%s %08lX %5u > %08lX %5u %5d %5d",
347 ntohl(pf
->laddr
), ntohs(pf
->lport
),
348 ntohl(pf
->raddr
), ntohs(pf
->rport
),
349 atomic_read(&pf
->pref_cnt
), pf
->pref
);
350 len
+= sprintf(buffer
+len
, "%-63s\n", temp
);
357 read_unlock_bh(&portfw_lock
);
359 begin
= len
- (pos
- offset
);
360 *start
= buffer
+ begin
;
367 static struct proc_dir_entry portfw_proc_entry
= {
369 0, 6, "portfw", /* Just for compatibility, for now ... */
370 S_IFREG
| S_IRUGO
, 1, 0, 0,
371 0, &proc_net_inode_operations
,
375 #define proc_ent &portfw_proc_entry
376 #else /* !CONFIG_PROC_FS */
378 #define proc_ent NULL
381 static int portfw_in_rule(const struct sk_buff
*skb
, const struct iphdr
*iph
)
383 const __u16
*portp
= (__u16
*)&(((char *)iph
)[iph
->ihl
*4]);
384 #ifdef CONFIG_IP_MASQ_DEBUG
385 struct rtable
*rt
= (struct rtable
*)skb
->dst
;
387 struct ip_portfw
*pfw
;
389 IP_MASQ_DEBUG(2, "portfw_in_rule(): skb:= dev=%s (index=%d), rt_iif=%d, rt_flags=0x%x rt_dev___=%s daddr=%d.%d.%d.%d dport=%d\n",
390 skb
->dev
->name
, skb
->dev
->ifindex
, rt
->rt_iif
, rt
->rt_flags
,
392 NIPQUAD(iph
->daddr
), ntohs(portp
[1]));
394 read_lock(&portfw_lock
);
395 pfw
= ip_portfw_lookup(iph
->protocol
, portp
[1], iph
->daddr
, NULL
, NULL
);
396 read_unlock(&portfw_lock
);
400 static struct ip_masq
* portfw_in_create(const struct sk_buff
*skb
, const struct iphdr
*iph
, __u32 maddr
)
403 * If no entry exists in the masquerading table
404 * and the port is involved
405 * in port forwarding, create a new masq entry
410 const __u16
*portp
= (__u16
*)&(((char *)iph
)[iph
->ihl
*4]);
411 struct ip_masq
*ms
= NULL
;
412 struct ip_portfw
*pf
;
417 write_lock(&portfw_lock
);
419 if ((pf
=ip_portfw_lookup(iph
->protocol
,
420 portp
[1], iph
->daddr
,
422 ms
= ip_masq_new(iph
->protocol
,
423 iph
->daddr
, portp
[1],
425 iph
->saddr
, portp
[0],
429 if (!ms
|| atomic_read(&mmod_self
->mmod_nent
) <= 1
430 /* || ip_masq_nlocks(&portfw_lock) != 1 */ )
437 * Entry created, lock==1.
438 * if pref_cnt == 0, move
440 * This is a simple load balance scheduling
443 if (atomic_dec_and_test(&pf
->pref_cnt
)) {
445 atomic_set(&pf
->pref_cnt
, pf
->pref
);
448 portfw_list
[portfw_idx(iph
->protocol
)].prev
);
453 write_unlock(&portfw_lock
);
457 #define portfw_in_update NULL
458 #define portfw_out_rule NULL
459 #define portfw_out_create NULL
460 #define portfw_out_update NULL
462 static struct ip_masq_mod portfw_mod
= {
466 ATOMIC_INIT(0), /* nent */
467 ATOMIC_INIT(0), /* refcnt */
470 NULL
, /* masq_mod_init */
471 NULL
, /* masq_mod_done */
482 __initfunc(int ip_portfw_init(void))
484 INIT_LIST_HEAD(&portfw_list
[0]);
485 INIT_LIST_HEAD(&portfw_list
[1]);
486 return register_ip_masq_mod ((mmod_self
=&portfw_mod
));
489 int ip_portfw_done(void)
491 return unregister_ip_masq_mod(&portfw_mod
);
497 int init_module(void)
499 if (ip_portfw_init() != 0)
504 void cleanup_module(void)
506 if (ip_portfw_done() != 0)
507 printk(KERN_INFO
"ip_portfw_done(): can't remove module");