1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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>
23#include <net/ip.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>
30
31#define IP_PORTFW_PORT_MIN 1
32#define IP_PORTFW_PORT_MAX 60999
33
34struct ip_portfw {
35 struct list_head list;
36 __u32 laddr, raddr;
37 __u16 lport, rport;
38 atomic_t pref_cnt;
39 int pref;
40};
41
42static struct ip_masq_mod *mmod_self = NULL;
43
44
45
46#ifdef CONFIG_IP_MASQ_DEBUG
47static int debug=0;
48MODULE_PARM(debug, "i");
49#endif
50
51
52
53
54#ifdef __SMP__
55static spinlock_t portfw_lock = SPIN_LOCK_UNLOCKED;
56#endif
57
58static struct list_head portfw_list[2];
59static __inline__ int portfw_idx(int protocol)
60{
61 return (protocol==IPPROTO_TCP);
62}
63
64
65
66
67
68
69
70
71
72static __inline__ int ip_portfw_del(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr)
73{
74 int prot = portfw_idx(protocol);
75 struct ip_portfw *n;
76 struct list_head *entry;
77 struct list_head *list = &portfw_list[prot];
78 int nent;
79
80 nent = atomic_read(&mmod_self->mmod_nent);
81
82 write_lock_bh(&portfw_lock);
83
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)) {
90 list_del(entry);
91 ip_masq_mod_dec_nent(mmod_self);
92 kfree_s(n, sizeof(struct ip_portfw));
93 MOD_DEC_USE_COUNT;
94 }
95 }
96 write_unlock_bh(&portfw_lock);
97
98 return nent==atomic_read(&mmod_self->mmod_nent)? ESRCH : 0;
99}
100
101
102
103
104
105static __inline__ void ip_portfw_flush(void)
106{
107 int prot;
108 struct list_head *l;
109 struct list_head *e;
110 struct ip_portfw *n;
111
112 write_lock_bh(&portfw_lock);
113
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);
119 list_del(e);
120 kfree_s(n, sizeof (*n));
121 MOD_DEC_USE_COUNT;
122 }
123 }
124
125 write_unlock_bh(&portfw_lock);
126}
127
128
129
130
131
132static __inline__ struct ip_portfw *ip_portfw_lookup(__u16 protocol, __u16 lport, __u32 laddr, __u32 *daddr_p, __u16 *dport_p)
133{
134 int prot = portfw_idx(protocol);
135
136 struct ip_portfw *n = NULL;
137 struct list_head *l, *e;
138
139 l = &portfw_list[prot];
140
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
145 if (daddr_p) {
146 *daddr_p = n->raddr;
147 *dport_p = n->rport;
148 }
149
150 goto out;
151 }
152 }
153 n = NULL;
154out:
155 return n;
156}
157
158
159
160
161
162static __inline__ int ip_portfw_edit(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr, int pref)
163{
164 int prot = portfw_idx(protocol);
165
166 struct ip_portfw *n = NULL;
167 struct list_head *l, *e;
168 int count = 0;
169
170
171 read_lock_bh(&portfw_lock);
172
173 l = &portfw_list[prot];
174
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)) {
181 n->pref = pref;
182 atomic_set(&n->pref_cnt, pref);
183 count++;
184 }
185 }
186
187 read_unlock_bh(&portfw_lock);
188
189 return count;
190}
191
192
193
194
195
196
197static __inline__ int ip_portfw_add(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr, int pref)
198{
199 struct ip_portfw *npf;
200 int prot = portfw_idx(protocol);
201
202 if (pref <= 0)
203 return EINVAL;
204
205 if (ip_portfw_edit(protocol, lport, laddr, rport, raddr, pref)) {
206
207
208
209 return 0;
210 }
211
212
213 npf = (struct ip_portfw*) kmalloc(sizeof(struct ip_portfw), GFP_KERNEL);
214
215 if (!npf)
216 return ENOMEM;
217
218 MOD_INC_USE_COUNT;
219 memset(npf, 0, sizeof(*npf));
220
221 npf->laddr = laddr;
222 npf->lport = lport;
223 npf->rport = rport;
224 npf->raddr = raddr;
225 npf->pref = pref;
226
227 atomic_set(&npf->pref_cnt, npf->pref);
228 INIT_LIST_HEAD(&npf->list);
229
230 write_lock_bh(&portfw_lock);
231
232
233
234
235 list_add(&npf->list, &portfw_list[prot]);
236
237 write_unlock_bh(&portfw_lock);
238
239 ip_masq_mod_inc_nent(mmod_self);
240 return 0;
241}
242
243
244
245static __inline__ int portfw_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
246{
247 struct ip_portfw_user *mm = &mctl->u.portfw_user;
248 int ret = EINVAL;
249 int arglen = optlen - IP_MASQ_CTL_BSIZE;
250 int cmd;
251
252
253 IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(len=%d/%d|%d/%d)\n",
254 arglen,
255 sizeof (*mm),
256 optlen,
257 sizeof (*mctl));
258
259
260
261
262 if (arglen != sizeof(*mm) && optlen != sizeof(*mctl))
263 return EINVAL;
264
265
266
267
268 cmd = mctl->m_cmd;
269 IP_MASQ_DEBUG(1-debug, "ip_masq_portfw_ctl(cmd=%d)\n", cmd);
270
271
272 switch (cmd) {
273 case IP_MASQ_CMD_NONE:
274 return 0;
275 case IP_MASQ_CMD_FLUSH:
276 break;
277 default:
278 if (htons(mm->lport) < IP_PORTFW_PORT_MIN || htons(mm->lport) > IP_PORTFW_PORT_MAX)
279 return EINVAL;
280
281 if (mm->protocol!=IPPROTO_TCP && mm->protocol!=IPPROTO_UDP)
282 return EINVAL;
283 }
284
285 switch(cmd) {
286 case IP_MASQ_CMD_ADD:
287 ret = ip_portfw_add(mm->protocol,
288 mm->lport, mm->laddr,
289 mm->rport, mm->raddr,
290 mm->pref);
291 break;
292
293 case IP_MASQ_CMD_DEL:
294 ret = ip_portfw_del(mm->protocol,
295 mm->lport, mm->laddr,
296 mm->rport, mm->raddr);
297 break;
298 case IP_MASQ_CMD_FLUSH:
299 ip_portfw_flush();
300 ret = 0;
301 break;
302 }
303
304
305 return ret;
306}
307
308
309
310
311#ifdef CONFIG_PROC_FS
312
313static int portfw_procinfo(char *buffer, char **start, off_t offset,
314 int length, int unused)
315{
316 off_t pos=0, begin;
317 struct ip_portfw *pf;
318 struct list_head *l, *e;
319 char temp[65];
320 int ind;
321 int len=0;
322
323
324 if (offset < 64)
325 {
326 sprintf(temp, "Prot LAddr LPort > RAddr RPort PrCnt Pref");
327 len = sprintf(buffer, "%-63s\n", temp);
328 }
329 pos = 64;
330
331 read_lock_bh(&portfw_lock);
332
333 for(ind = 0; ind < 2; ind++)
334 {
335 l = &portfw_list[ind];
336 for (e=l->next; e!=l; e=e->next)
337 {
338 pf = list_entry(e, struct ip_portfw, list);
339 pos += 64;
340 if (pos <= offset) {
341 len = 0;
342 continue;
343 }
344
345 sprintf(temp,"%s %08lX %5u > %08lX %5u %5d %5d",
346 ind ? "TCP" : "UDP",
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);
351
352 if (len >= length)
353 goto done;
354 }
355 }
356done:
357 read_unlock_bh(&portfw_lock);
358
359 begin = len - (pos - offset);
360 *start = buffer + begin;
361 len -= begin;
362 if(len>length)
363 len = length;
364 return len;
365}
366
367static struct proc_dir_entry portfw_proc_entry = {
368
369 0, 6, "portfw",
370 S_IFREG | S_IRUGO, 1, 0, 0,
371 0, &proc_net_inode_operations,
372 portfw_procinfo
373};
374
375#define proc_ent &portfw_proc_entry
376#else
377
378#define proc_ent NULL
379#endif
380
381static int portfw_in_rule(const struct sk_buff *skb, const struct iphdr *iph)
382{
383 const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
384#ifdef CONFIG_IP_MASQ_DEBUG
385 struct rtable *rt = (struct rtable *)skb->dst;
386#endif
387 struct ip_portfw *pfw;
388
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,
391 rt->u.dst.dev->name,
392 NIPQUAD(iph->daddr), ntohs(portp[1]));
393
394 read_lock(&portfw_lock);
395 pfw = ip_portfw_lookup(iph->protocol, portp[1], iph->daddr, NULL, NULL);
396 read_unlock(&portfw_lock);
397 return (pfw!=0);
398}
399
400static struct ip_masq * portfw_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
401{
402
403
404
405
406
407
408 __u32 raddr;
409 __u16 rport;
410 const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
411 struct ip_masq *ms = NULL;
412 struct ip_portfw *pf;
413
414
415
416
417 write_lock(&portfw_lock);
418
419 if ((pf=ip_portfw_lookup(iph->protocol,
420 portp[1], iph->daddr,
421 &raddr, &rport))) {
422 ms = ip_masq_new(iph->protocol,
423 iph->daddr, portp[1],
424 raddr, rport,
425 iph->saddr, portp[0],
426 0);
427 ip_masq_listen(ms);
428
429 if (!ms || atomic_read(&mmod_self->mmod_nent) <= 1
430 )
431
432
433
434 goto out;
435
436
437
438
439
440
441
442
443 if (atomic_dec_and_test(&pf->pref_cnt)) {
444
445 atomic_set(&pf->pref_cnt, pf->pref);
446 list_del(&pf->list);
447 list_add(&pf->list,
448 portfw_list[portfw_idx(iph->protocol)].prev);
449
450 }
451 }
452out:
453 write_unlock(&portfw_lock);
454 return ms;
455}
456
457#define portfw_in_update NULL
458#define portfw_out_rule NULL
459#define portfw_out_create NULL
460#define portfw_out_update NULL
461
462static struct ip_masq_mod portfw_mod = {
463 NULL,
464 NULL,
465 "portfw",
466 ATOMIC_INIT(0),
467 ATOMIC_INIT(0),
468 proc_ent,
469 portfw_ctl,
470 NULL,
471 NULL,
472 portfw_in_rule,
473 portfw_in_update,
474 portfw_in_create,
475 portfw_out_rule,
476 portfw_out_update,
477 portfw_out_create,
478};
479
480
481
482__initfunc(int ip_portfw_init(void))
483{
484 INIT_LIST_HEAD(&portfw_list[0]);
485 INIT_LIST_HEAD(&portfw_list[1]);
486 return register_ip_masq_mod ((mmod_self=&portfw_mod));
487}
488
489int ip_portfw_done(void)
490{
491 return unregister_ip_masq_mod(&portfw_mod);
492}
493
494#ifdef MODULE
495EXPORT_NO_SYMBOLS;
496
497int init_module(void)
498{
499 if (ip_portfw_init() != 0)
500 return -EIO;
501 return 0;
502}
503
504void cleanup_module(void)
505{
506 if (ip_portfw_done() != 0)
507 printk(KERN_INFO "ip_portfw_done(): can't remove module");
508}
509
510#endif
511