This source file includes following definitions.
- masq_proto_name
- register_ip_masq_app
- unregister_ip_masq_app
- ip_masq_app_get
- ip_masq_app_bind_chg
- ip_masq_bind_app
- ip_masq_unbind_app
- masq_fix_seq
- masq_fix_ack_seq
- masq_seq_update
- ip_masq_app_pkt_out
- ip_masq_app_pkt_in
- ip_masq_app_getinfo
- ip_masq_app_init
- skb_replace
- ip_masq_skb_replace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <linux/module.h>
25 #include <linux/types.h>
26 #include <linux/kernel.h>
27 #include <linux/errno.h>
28 #include <linux/skbuff.h>
29 #include <linux/in.h>
30 #include <linux/ip.h>
31 #include <net/protocol.h>
32 #include <net/tcp.h>
33 #include <net/udp.h>
34 #include <asm/system.h>
35 #include <linux/stat.h>
36 #include <linux/proc_fs.h>
37 #include <net/ip_masq.h>
38
39 static const char *strProt[] = {"UDP","TCP"};
40
41 static __inline__ const char * masq_proto_name(unsigned proto)
42 {
43 return strProt[proto==IPPROTO_TCP];
44 }
45
46 #define IP_MASQ_APP_TAB_SIZE 16
47
48 #define IP_MASQ_APP_HASH(proto, port) ((port^proto) & (IP_MASQ_APP_TAB_SIZE-1))
49 #define IP_MASQ_APP_TYPE(proto, port) ( proto<<16 | port )
50 #define IP_MASQ_APP_PORT(type) ( type & 0xffff )
51 #define IP_MASQ_APP_PROTO(type) ( (type>>16) & 0x00ff )
52
53
54 static struct symbol_table ip_masq_app_syms = {
55 #include <linux/symtab_begin.h>
56 X(register_ip_masq_app),
57 X(unregister_ip_masq_app),
58 X(ip_masq_skb_replace),
59 #include <linux/symtab_end.h>
60 };
61
62
63
64
65
66 struct ip_masq_app *ip_masq_app_base[IP_MASQ_APP_TAB_SIZE];
67
68
69
70
71
72
73 int register_ip_masq_app(struct ip_masq_app *mapp, unsigned short proto, __u16 port)
74 {
75 unsigned long flags;
76 unsigned hash;
77 if (!mapp) {
78 printk("register_ip_masq_app(): NULL arg\n");
79 return -EINVAL;
80 }
81 mapp->type = IP_MASQ_APP_TYPE(proto, port);
82 mapp->n_attach = 0;
83 hash = IP_MASQ_APP_HASH(proto, port);
84
85 save_flags(flags);
86 cli();
87 mapp->next = ip_masq_app_base[hash];
88 ip_masq_app_base[hash] = mapp;
89 restore_flags(flags);
90
91 return 0;
92 }
93
94
95
96
97
98 int unregister_ip_masq_app(struct ip_masq_app *mapp)
99 {
100 struct ip_masq_app **mapp_p;
101 unsigned hash;
102 unsigned long flags;
103 if (!mapp) {
104 printk("unregister_ip_masq_app(): NULL arg\n");
105 return -EINVAL;
106 }
107
108
109
110 if (mapp->n_attach) {
111 printk("unregister_ip_masq_app(): has %d attachments. failed\n",
112 mapp->n_attach);
113 return -EINVAL;
114 }
115 hash = IP_MASQ_APP_HASH(IP_MASQ_APP_PROTO(mapp->type), IP_MASQ_APP_PORT(mapp->type));
116
117 save_flags(flags);
118 cli();
119 for (mapp_p = &ip_masq_app_base[hash]; *mapp_p ; mapp_p = &(*mapp_p)->next)
120 if (mapp == (*mapp_p)) {
121 *mapp_p = mapp->next;
122 restore_flags(flags);
123 return 0;
124 }
125
126 restore_flags(flags);
127 printk("unregister_ip_masq_app(proto=%s,port=%u): not hashed!\n",
128 masq_proto_name(IP_MASQ_APP_PROTO(mapp->type)), IP_MASQ_APP_PORT(mapp->type));
129 return -EINVAL;
130 }
131
132
133
134
135
136 struct ip_masq_app * ip_masq_app_get(unsigned short proto, __u16 port)
137 {
138 struct ip_masq_app *mapp;
139 unsigned hash;
140 unsigned type;
141
142 port = ntohs(port);
143 type = IP_MASQ_APP_TYPE(proto,port);
144 hash = IP_MASQ_APP_HASH(proto,port);
145 for(mapp = ip_masq_app_base[hash]; mapp ; mapp = mapp->next) {
146 if (type == mapp->type) return mapp;
147 }
148 return NULL;
149 }
150
151
152
153
154
155
156
157
158
159 static __inline__ int ip_masq_app_bind_chg(struct ip_masq_app *mapp, int delta)
160 {
161 unsigned long flags;
162 int n_at;
163 if (!mapp) return -1;
164 save_flags(flags);
165 cli();
166 n_at = mapp->n_attach + delta;
167 if (n_at < 0) {
168 restore_flags(flags);
169 printk("ip_masq_app: tried to set n_attach < 0 for (proto=%s,port==%d) ip_masq_app object.\n",
170 masq_proto_name(IP_MASQ_APP_PROTO(mapp->type)),
171 IP_MASQ_APP_PORT(mapp->type));
172 return -1;
173 }
174 mapp->n_attach = n_at;
175 restore_flags(flags);
176 return 0;
177 }
178
179
180
181
182
183
184 struct ip_masq_app * ip_masq_bind_app(struct ip_masq *ms)
185 {
186 struct ip_masq_app * mapp;
187 mapp = ip_masq_app_get(ms->protocol, ms->dport);
188 if (mapp != NULL) {
189
190
191
192
193 if (ms->app != NULL) {
194 printk("ip_masq_bind_app() called for already bound object.\n");
195 return ms->app;
196 }
197
198 ms->app = mapp;
199 if (mapp->masq_init_1) mapp->masq_init_1(mapp, ms);
200 ip_masq_app_bind_chg(mapp, +1);
201 }
202 return mapp;
203 }
204
205
206
207
208
209 int ip_masq_unbind_app(struct ip_masq *ms)
210 {
211 struct ip_masq_app * mapp;
212 mapp = ms->app;
213 if (mapp != NULL) {
214 if (mapp->masq_done_1) mapp->masq_done_1(mapp, ms);
215 ms->app = NULL;
216 ip_masq_app_bind_chg(mapp, -1);
217 }
218 return (mapp != NULL);
219 }
220
221
222
223
224
225 static __inline__ void masq_fix_seq(const struct ip_masq_seq *ms_seq, struct tcphdr *th)
226 {
227 __u32 seq;
228
229 seq = ntohl(th->seq);
230
231
232
233
234
235
236
237 if (ms_seq->delta || ms_seq->previous_delta) {
238 if(after(seq,ms_seq->init_seq) ) {
239 th->seq = htonl(seq + ms_seq->delta);
240 #if DEBUG_CONFIG_IP_MASQ_APP
241 printk("masq_fix_seq() : added delta (%d) to seq\n",ms_seq->delta);
242 #endif
243 } else {
244 th->seq = htonl(seq + ms_seq->previous_delta);
245 #if DEBUG_CONFIG_IP_MASQ_APP
246 printk("masq_fix_seq() : added previous_delta (%d) to seq\n",ms_seq->previous_delta);
247 #endif
248 }
249 }
250
251
252 }
253
254
255
256
257
258 static __inline__ void masq_fix_ack_seq(const struct ip_masq_seq *ms_seq, struct tcphdr *th)
259 {
260 __u32 ack_seq;
261
262 ack_seq=ntohl(th->ack_seq);
263
264
265
266
267
268
269
270 if (ms_seq->delta || ms_seq->previous_delta) {
271 if(after(ack_seq,ms_seq->init_seq)) {
272 th->ack_seq = htonl(ack_seq-ms_seq->delta);
273 #if DEBUG_CONFIG_IP_MASQ_APP
274 printk("masq_fix_ack_seq() : subtracted delta (%d) from ack_seq\n",ms_seq->delta);
275 #endif
276 } else {
277 th->ack_seq = htonl(ack_seq-ms_seq->previous_delta);
278 #if DEBUG_CONFIG_IP_MASQ_APP
279 printk("masq_fix_ack_seq() : subtracted previous_delta (%d) from ack_seq\n",ms_seq->previous_delta);
280 #endif
281 }
282 }
283
284 }
285
286
287
288
289
290
291 static __inline__ void masq_seq_update(struct ip_masq *ms, struct ip_masq_seq *ms_seq, unsigned mflag, __u32 seq, int diff)
292 {
293
294
295 if ( !(ms->flags & mflag) || after(seq, ms_seq->init_seq))
296 {
297 ms_seq->previous_delta=ms_seq->delta;
298 ms_seq->delta+=diff;
299 ms_seq->init_seq=seq;
300 ms->flags |= mflag;
301 }
302 }
303
304
305
306
307
308
309
310 int ip_masq_app_pkt_out(struct ip_masq *ms, struct sk_buff **skb_p, struct device *dev)
311 {
312 struct ip_masq_app * mapp;
313 struct iphdr *iph;
314 struct tcphdr *th;
315 int diff;
316 __u32 seq;
317
318
319
320
321
322
323
324
325 if ( (mapp = ms->app) == NULL)
326 return 0;
327
328 iph = (*skb_p)->h.iph;
329 th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
330
331
332
333
334
335 seq = ntohl(th->seq);
336
337
338
339
340
341 if (ms->protocol == IPPROTO_TCP) {
342 if (ms->flags & IP_MASQ_F_OUT_SEQ)
343 masq_fix_seq(&ms->out_seq, th);
344 if (ms->flags & IP_MASQ_F_IN_SEQ)
345 masq_fix_ack_seq(&ms->in_seq, th);
346 }
347
348
349
350
351
352 if ( mapp->pkt_out == NULL )
353 return 0;
354
355 diff = mapp->pkt_out(mapp, ms, skb_p, dev);
356
357
358
359
360
361 if (diff != 0 && ms->protocol == IPPROTO_TCP)
362 masq_seq_update(ms, &ms->out_seq, IP_MASQ_F_OUT_SEQ, seq, diff);
363
364 return diff;
365 }
366
367
368
369
370
371
372
373 int ip_masq_app_pkt_in(struct ip_masq *ms, struct sk_buff **skb_p, struct device *dev)
374 {
375 struct ip_masq_app * mapp;
376 struct iphdr *iph;
377 struct tcphdr *th;
378 int diff;
379 __u32 seq;
380
381
382
383
384
385
386
387
388 if ( (mapp = ms->app) == NULL)
389 return 0;
390
391 iph = (*skb_p)->h.iph;
392 th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
393
394
395
396
397
398 seq = ntohl(th->seq);
399
400
401
402
403
404 if (ms->protocol == IPPROTO_TCP) {
405 if (ms->flags & IP_MASQ_F_IN_SEQ)
406 masq_fix_seq(&ms->in_seq, th);
407 if (ms->flags & IP_MASQ_F_OUT_SEQ)
408 masq_fix_ack_seq(&ms->out_seq, th);
409 }
410
411
412
413
414
415 if ( mapp->pkt_in == NULL )
416 return 0;
417
418 diff = mapp->pkt_in(mapp, ms, skb_p, dev);
419
420
421
422
423
424 if (diff != 0 && ms->protocol == IPPROTO_TCP)
425 masq_seq_update(ms, &ms->in_seq, IP_MASQ_F_IN_SEQ, seq, diff);
426
427 return diff;
428 }
429
430
431
432
433
434 int ip_masq_app_getinfo(char *buffer, char **start, off_t offset, int length, int dummy)
435 {
436 off_t pos=0, begin=0;
437 int len=0;
438 struct ip_masq_app * mapp;
439 unsigned idx;
440
441 if (offset < 22)
442 len=sprintf(buffer,"%-21s\n", "prot port n_attach");
443 pos = 22;
444
445 for (idx=0 ; idx < IP_MASQ_APP_TAB_SIZE; idx++)
446 for (mapp = ip_masq_app_base[idx]; mapp ; mapp = mapp->next) {
447
448
449
450
451
452 pos += 22;
453 if (pos < offset)
454 continue;
455
456 len += sprintf(buffer+len, "%-3s %-7u %-7d \n",
457 masq_proto_name(IP_MASQ_APP_PROTO(mapp->type)),
458 IP_MASQ_APP_PORT(mapp->type), mapp->n_attach);
459
460 if(len >= length)
461 goto done;
462 }
463 done:
464 begin = len - (pos - offset);
465 *start = buffer + begin;
466 len -= begin;
467 if (len > length)
468 len = length;
469 return len;
470 }
471
472
473
474
475
476
477 int ip_masq_app_init(void)
478 {
479
480 register_symtab (&ip_masq_app_syms);
481
482 proc_net_register(&(struct proc_dir_entry) {
483 PROC_NET_IP_MASQ_APP, 11, "ip_masq_app",
484 S_IFREG | S_IRUGO, 1, 0, 0,
485 0, &proc_net_inode_operations,
486 ip_masq_app_getinfo
487 });
488
489 return 0;
490 }
491
492
493
494
495
496
497
498
499 static struct sk_buff * skb_replace(struct sk_buff *skb, int pri, char *o_buf, int o_len, char *n_buf, int n_len)
500 {
501 int maxsize, diff, o_offset;
502 struct sk_buff *n_skb;
503
504 maxsize = skb->truesize - sizeof(struct sk_buff);
505
506 diff = n_len - o_len;
507 o_offset = o_buf - (char*) skb->data;
508
509 if (maxsize <= n_len) {
510 if (diff != 0) {
511 memcpy(skb->data + o_offset + n_len,o_buf + o_len,
512 skb->len - (o_offset + o_len));
513 }
514
515 memcpy(skb->data + o_offset, n_buf, n_len);
516
517 n_skb = skb;
518 skb->len = n_len;
519 skb->end = skb->head+n_len;
520 } else {
521
522
523
524
525 n_skb = alloc_skb(MAX_HEADER + skb->len + diff, pri);
526 if (n_skb == NULL) {
527 printk("skb_replace(): no room left (from %p)\n",
528 __builtin_return_address(0));
529 return skb;
530
531 }
532 n_skb->free = skb->free;
533 skb_reserve(n_skb, MAX_HEADER);
534 skb_put(n_skb, skb->len + diff);
535 n_skb->h.raw = n_skb->data + (skb->h.raw - skb->data);
536
537
538
539
540
541 memcpy(n_skb->data, skb->data, o_offset);
542 memcpy(n_skb->data + o_offset, n_buf, n_len);
543 memcpy(n_skb->data + o_offset + n_len, o_buf + o_len,
544 skb->len - (o_offset + o_len) );
545
546
547
548
549
550
551 kfree_skb(skb, FREE_WRITE);
552 }
553 return n_skb;
554 }
555
556
557
558
559
560 struct sk_buff * ip_masq_skb_replace(struct sk_buff *skb, int pri, char *o_buf, int o_len, char *n_buf, int n_len)
561 {
562 int diff;
563 struct sk_buff *n_skb;
564 unsigned skb_len;
565
566 diff = n_len - o_len;
567 n_skb = skb_replace(skb, pri, o_buf, o_len, n_buf, n_len);
568 skb_len = skb->len;
569
570 if (diff)
571 {
572 struct iphdr *iph;
573 #if DEBUG_CONFIG_IP_MASQ_APP
574 printk("masq_skb_replace(): pkt resized for %d bytes (len=%ld)\n", diff, skb->len);
575 #endif
576
577
578
579 iph = n_skb->h.iph;
580 iph->check = 0;
581 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
582 iph->tot_len = htons(skb_len + diff);
583 }
584 return n_skb;
585 }