1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65#include <linux/config.h>
66#include <linux/module.h>
67#include <asm/system.h>
68#include <linux/types.h>
69#include <linux/ctype.h>
70#include <linux/kernel.h>
71#include <linux/skbuff.h>
72#include <linux/in.h>
73#include <linux/ip.h>
74#include <linux/init.h>
75#include <net/protocol.h>
76#include <net/tcp.h>
77#include <net/ip_masq.h>
78
79
80
81
82
83
84
85#define TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? ((c) - 'A' + 'a') : (c))
86#define ISDIGIT(c) (((c) >= '0') && ((c) <= '9'))
87
88struct raudio_priv_data {
89
90 struct ip_masq *data_conn;
91
92 struct ip_masq *error_conn;
93
94 short seen_start;
95 short is_rtsp;
96};
97
98int
99masq_rtsp_out (struct ip_masq_app *mapp,
100 struct ip_masq *ms,
101 struct sk_buff **skb_p,
102 __u32 maddr);
103
104
105
106
107
108int ports[MAX_MASQ_APP_PORTS] = {554, 7070, 0};
109struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS];
110
111
112
113
114#ifdef CONFIG_IP_MASQ_DEBUG
115static int debug=0;
116MODULE_PARM(debug, "i");
117#endif
118
119MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
120
121
122static int
123masq_raudio_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
124{
125 MOD_INC_USE_COUNT;
126 if ((ms->app_data = kmalloc(sizeof(struct raudio_priv_data),
127 GFP_ATOMIC)) == NULL)
128 printk(KERN_INFO "RealAudio: No memory for application data\n");
129 else
130 {
131 struct raudio_priv_data *priv =
132 (struct raudio_priv_data *)ms->app_data;
133 priv->seen_start = 0;
134 priv->data_conn = NULL;
135 priv->error_conn = NULL;
136 priv->is_rtsp = 0;
137 }
138 return 0;
139}
140
141static int
142masq_raudio_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
143{
144 MOD_DEC_USE_COUNT;
145 if (ms->app_data)
146 kfree_s(ms->app_data, sizeof(struct raudio_priv_data));
147 return 0;
148}
149
150int
151masq_raudio_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
152{
153 struct sk_buff *skb;
154 struct iphdr *iph;
155 struct tcphdr *th;
156 char *p, *data, *data_limit;
157 struct ip_masq *n_ms;
158 unsigned short version, msg_id, msg_len, udp_port;
159 struct raudio_priv_data *priv =
160 (struct raudio_priv_data *)ms->app_data;
161
162
163 if (priv && priv->seen_start)
164 return 0;
165
166 if(priv && priv->is_rtsp)
167 return masq_rtsp_out(mapp, ms, skb_p, maddr);
168
169 skb = *skb_p;
170 iph = skb->nh.iph;
171 th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
172 data = (char *)&th[1];
173
174 data_limit = skb->h.raw + skb->len;
175
176 if(memcmp(data, "OPTIONS", 7) == 0 ||
177 memcmp(data, "DESCRIBE", 8) == 0)
178 {
179 IP_MASQ_DEBUG(1-debug, "RealAudio: Detected RTSP connection\n");
180
181 if(priv)
182 priv->is_rtsp = 1;
183 return masq_rtsp_out(mapp, ms, skb_p, maddr);
184 }
185
186
187 if (memcmp(data, "PNA", 3)) {
188 IP_MASQ_DEBUG(1-debug, "RealAudio: not initial protocol packet - ignored\n");
189 return(0);
190 }
191 data += 3;
192 memcpy(&version, data, 2);
193
194 IP_MASQ_DEBUG(1-debug, "RealAudio: initial seen - protocol version %d\n",
195 ntohs(version));
196 if (priv)
197 priv->seen_start = 1;
198
199 if (ntohs(version) >= 256)
200 {
201 printk(KERN_INFO "RealAudio: version (%d) not supported\n",
202 ntohs(version));
203 return 0;
204 }
205
206 data += 2;
207 while (data+4 < data_limit) {
208 memcpy(&msg_id, data, 2);
209 data += 2;
210 memcpy(&msg_len, data, 2);
211 data += 2;
212 if (ntohs(msg_id) == 0) {
213
214 IP_MASQ_DEBUG(1-debug, "RealAudio: packet end tag seen\n");
215 return 0;
216 }
217 IP_MASQ_DEBUG(1-debug, "RealAudio: msg %d - %d byte\n",
218 ntohs(msg_id), ntohs(msg_len));
219 if (ntohs(msg_id) == 0) {
220
221 return 0;
222 }
223 p = data;
224 data += ntohs(msg_len);
225 if (data > data_limit)
226 {
227 printk(KERN_INFO "RealAudio: Packet too short for data\n");
228 return 0;
229 }
230 if ((ntohs(msg_id) == 1) || (ntohs(msg_id) == 7)) {
231
232
233
234
235
236
237
238
239
240
241 memcpy(&udp_port, p, 2);
242
243
244
245
246
247 if (udp_port == 0)
248 continue;
249
250
251 n_ms = ip_masq_new(IPPROTO_UDP,
252 maddr, 0,
253 ms->saddr, udp_port,
254 ms->daddr, 0,
255 IP_MASQ_F_NO_DPORT);
256
257 if (n_ms==NULL)
258 return 0;
259
260 ip_masq_listen(n_ms);
261 ip_masq_control_add(n_ms, ms);
262
263 memcpy(p, &(n_ms->mport), 2);
264 IP_MASQ_DEBUG(1-debug, "RealAudio: rewrote UDP port %d -> %d in msg %d\n",
265 ntohs(udp_port), ntohs(n_ms->mport), ntohs(msg_id));
266
267
268 if (priv) {
269 if (ntohs(msg_id) == 1)
270 priv->data_conn = n_ms;
271 else
272 priv->error_conn = n_ms;
273 }
274
275 ip_masq_put(n_ms);
276 }
277 }
278 return 0;
279}
280
281
282
283
284
285
286int
287masq_rtsp_out (struct ip_masq_app *mapp,
288 struct ip_masq *ms,
289 struct sk_buff **skb_p,
290 __u32 maddr)
291{
292 struct sk_buff *skb;
293 struct iphdr *iph;
294 struct tcphdr *th;
295 char *data, *data_limit;
296 struct ip_masq *n_ms, *n_ms2;
297 unsigned short udp_port;
298 struct raudio_priv_data *priv =
299 (struct raudio_priv_data *)ms->app_data;
300 const char* srch = "transport:";
301 const char* srchpos = srch;
302 const char* srchend = srch + strlen(srch);
303 int state = 0;
304 char firstport[6];
305 int firstportpos = 0;
306 char secondport[6];
307 int secondportpos = 0;
308 char *portstart = NULL, *portend = NULL;
309 int diff;
310
311
312 if (priv && priv->seen_start)
313 return 0;
314
315 skb = *skb_p;
316 iph = skb->nh.iph;
317 th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
318 data = (char *)&th[1];
319
320 data_limit = skb->h.raw + skb->len;
321
322 firstport[0] = 0;
323 secondport[0] = 0;
324
325 while(data < data_limit && state >= 0)
326 {
327 switch(state)
328 {
329 case 0:
330 case 1:
331 if(TOLOWER(*data) == *srchpos)
332 {
333 srchpos++;
334 if(srchpos == srchend)
335 {
336 IP_MASQ_DEBUG(1-debug, "Found string %s in message\n",
337 srch);
338 state++;
339 if(state == 1)
340 {
341 srch = "client_port";
342 srchpos = srch;
343 srchend = srch + strlen(srch);
344 }
345 }
346 }
347 else
348 {
349 srchpos = srch;
350 }
351 break;
352 case 2:
353 if(*data == '=')
354 state = 3;
355 break;
356 case 3:
357 if(ISDIGIT(*data))
358 {
359 portstart = data;
360 firstportpos = 0;
361 firstport[firstportpos++] = *data;
362 state = 4;
363 }
364 break;
365 case 4:
366 if(*data == '-')
367 {
368 state = 5;
369 }
370 else if(*data == ';')
371 {
372 portend = data - 1;
373 firstport[firstportpos] = 0;
374 state = -1;
375 }
376 else if(ISDIGIT(*data))
377 {
378 firstport[firstportpos++] = *data;
379 }
380 else if(*data != ' ' && *data != '\t')
381 {
382
383 IP_MASQ_DEBUG(1-debug, "Badly formed RTSP Message\n");
384 return 0;
385 }
386 break;
387 case 5:
388 if(ISDIGIT(*data))
389 {
390 secondportpos = 0;
391 secondport[secondportpos++] = *data;
392 state = 6;
393 }
394 else if(*data == ';')
395 {
396 portend = data - 1;
397 secondport[secondportpos] = 0;
398 state = -1;
399 }
400 break;
401 case 6:
402 if(*data == ';')
403 {
404 portend = data - 1;
405 secondport[secondportpos] = 0;
406 state = -1;
407 }
408 else if(ISDIGIT(*data))
409 {
410 secondport[secondportpos++] = *data;
411 }
412 else if(*data != ' ' && *data != '\t')
413 {
414
415 IP_MASQ_DEBUG(1-debug, "Badly formed RTSP Message\n");
416 return 0;
417 }
418 break;
419 }
420 data++;
421 }
422
423 if(state >= 0)
424 return 0;
425
426 if(firstportpos > 0)
427 {
428 char newbuf[12];
429 char* tmpptr;
430
431 udp_port = htons(simple_strtoul(firstport, &tmpptr, 10));
432 n_ms = ip_masq_new(IPPROTO_UDP,
433 maddr, 0,
434 ms->saddr, udp_port,
435 ms->daddr, 0,
436 IP_MASQ_F_NO_DPORT);
437 if (n_ms==NULL)
438 return 0;
439
440 ip_masq_listen(n_ms);
441 ip_masq_control_add(n_ms, ms);
442
443 if(secondportpos > 0)
444 {
445 udp_port = htons(simple_strtoul(secondport, &tmpptr, 10));
446 n_ms2 = ip_masq_new(IPPROTO_UDP,
447 maddr, 0,
448 ms->saddr, udp_port,
449 ms->daddr, 0,
450 IP_MASQ_F_NO_DPORT);
451 if (n_ms2==NULL) {
452 ip_masq_put(n_ms);
453 return 0;
454 }
455
456 ip_masq_listen(n_ms2);
457 ip_masq_control_add(n_ms2, ms);
458 sprintf(newbuf, "%d-%d", ntohs(n_ms->mport),
459 ntohs(n_ms2->mport));
460 }
461 else
462 {
463 sprintf(newbuf, "%d", ntohs(n_ms->mport));
464 n_ms2 = NULL;
465 }
466 *skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC,
467 portstart, portend - portstart + 1,
468 newbuf, strlen(newbuf));
469 IP_MASQ_DEBUG(1-debug, "RTSP: rewrote client_port to %s\n", newbuf);
470 diff = strlen(newbuf) - (portend - portstart);
471 }
472 else
473 {
474 return 0;
475 }
476
477 if(priv)
478 {
479 priv->seen_start = 1;
480 if(n_ms)
481 priv->data_conn = n_ms;
482 if(n_ms2)
483 priv->error_conn = n_ms2;
484 }
485
486
487
488
489 if (n_ms)
490 ip_masq_put(n_ms);
491
492 if (n_ms2)
493 ip_masq_put(n_ms2);
494
495 return diff;
496}
497
498struct ip_masq_app ip_masq_raudio = {
499 NULL,
500 "RealAudio",
501 0,
502 0,
503 masq_raudio_init_1,
504 masq_raudio_done_1,
505 masq_raudio_out,
506 NULL
507};
508
509
510
511
512
513__initfunc(int ip_masq_raudio_init(void))
514{
515 int i, j;
516
517 for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
518 if (ports[i]) {
519 if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app),
520 GFP_KERNEL)) == NULL)
521 return -ENOMEM;
522 memcpy(masq_incarnations[i], &ip_masq_raudio, sizeof(struct ip_masq_app));
523 if ((j = register_ip_masq_app(masq_incarnations[i],
524 IPPROTO_TCP,
525 ports[i]))) {
526 return j;
527 }
528 IP_MASQ_DEBUG(1-debug, "RealAudio: loaded support on port[%d] = %d\n",
529 i, ports[i]);
530 } else {
531
532 masq_incarnations[i] = NULL;
533 }
534 }
535 return 0;
536}
537
538
539
540
541
542int ip_masq_raudio_done(void)
543{
544 int i, j, k;
545
546 k=0;
547 for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
548 if (masq_incarnations[i]) {
549 if ((j = unregister_ip_masq_app(masq_incarnations[i]))) {
550 k = j;
551 } else {
552 kfree(masq_incarnations[i]);
553 masq_incarnations[i] = NULL;
554 IP_MASQ_DEBUG(1-debug, "RealAudio: unloaded support on port[%d] = %d\n",
555 i, ports[i]);
556 }
557 }
558 }
559 return k;
560}
561
562#ifdef MODULE
563EXPORT_NO_SYMBOLS;
564
565int init_module(void)
566{
567 if (ip_masq_raudio_init() != 0)
568 return -EIO;
569 return 0;
570}
571
572void cleanup_module(void)
573{
574 if (ip_masq_raudio_done() != 0)
575 printk(KERN_INFO "ip_masq_raudio: can't remove module");
576}
577
578#endif
579