2 * IP_MASQ_RAUDIO - Real Audio masquerading module
5 * Version: @(#)$Id: ip_masq_raudio.c,v 1.11 1998/10/06 04:49:04 davem Exp $
7 * Author: Nigel Metheringham
8 * Real Time Streaming code by Progressive Networks
9 * [strongly based on ftp module by Juan Jose Ciarlante & Wouter Gadeyne]
10 * [Real Audio information taken from Progressive Networks firewall docs]
11 * [Kudos to Progressive Networks for making the protocol specs available]
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
23 * The IP Masquerading proxies at present do not have access to a processed
24 * data stream. Hence for a protocol like the Real Audio control protocol,
25 * which depends on knowing where you are in the data stream, you either
26 * to keep a *lot* of state in your proxy, or you cheat and simplify the
27 * problem [needless to say I did the latter].
29 * This proxy only handles data in the first packet. Everything else is
30 * passed transparently. This means it should work under all normal
31 * circumstances, but it could be fooled by new data formats or a
32 * malicious application!
34 * At present the "first packet" is defined as a packet starting with
35 * the protocol ID string - "PNA".
36 * When the link is up there appears to be enough control data
37 * crossing the control link to keep it open even if a long audio
40 * The Robust UDP support added in RealAudio 3.0 is supported, but due
41 * to servers/clients not making great use of this has not been greatly
42 * tested. RealVideo (as used in the Real client version 4.0beta1) is
43 * supported but again is not greatly tested (bandwidth requirements
44 * appear to exceed that available at the sites supporting the protocol).
46 * Multiple Port Support
47 * The helper can be made to handle up to MAX_MASQ_APP_PORTS (normally 12)
48 * with the port numbers being defined at module load time. The module
49 * uses the symbol "ports" to define a list of monitored ports, which can
50 * be specified on the insmod command line as
52 * where x[n] are integer port numbers. This option can be put into
53 * /etc/conf.modules (or /etc/modules.conf depending on your config)
54 * where modload will pick it up should you use modload to load your
58 * Juan Jose Ciarlante : Use control_add() for control chan
59 * 10/15/97 - Modifications to allow masquerading of RTSP connections as
60 * well as PNA, which can potentially exist on the same port.
61 * Joe Rumsey <ogre@real.com>
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>
74 #include <linux/init.h>
75 #include <net/protocol.h>
77 #include <net/ip_masq.h>
80 #ifndef DEBUG_CONFIG_IP_MASQ_RAUDIO
81 #define DEBUG_CONFIG_IP_MASQ_RAUDIO 0
85 #define TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? ((c) - 'A' + 'a') : (c))
86 #define ISDIGIT(c) (((c) >= '0') && ((c) <= '9'))
88 struct raudio_priv_data
{
89 /* Associated data connection - setup but not used at present */
90 struct ip_masq
*data_conn
;
91 /* UDP Error correction connection - setup but not used at present */
92 struct ip_masq
*error_conn
;
93 /* Have we seen and performed setup */
99 masq_rtsp_out (struct ip_masq_app
*mapp
,
101 struct sk_buff
**skb_p
,
105 * List of ports (up to MAX_MASQ_APP_PORTS) to be handled by helper
106 * First port is set to the default port.
108 int ports
[MAX_MASQ_APP_PORTS
] = {554, 7070, 0}; /* I rely on the trailing items being set to zero */
109 struct ip_masq_app
*masq_incarnations
[MAX_MASQ_APP_PORTS
];
114 #ifdef CONFIG_IP_MASQ_DEBUG
116 MODULE_PARM(debug
, "i");
119 MODULE_PARM(ports
, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS
) "i");
123 masq_raudio_init_1 (struct ip_masq_app
*mapp
, struct ip_masq
*ms
)
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");
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
;
142 masq_raudio_done_1 (struct ip_masq_app
*mapp
, struct ip_masq
*ms
)
146 kfree_s(ms
->app_data
, sizeof(struct raudio_priv_data
));
151 masq_raudio_out (struct ip_masq_app
*mapp
, struct ip_masq
*ms
, struct sk_buff
**skb_p
, __u32 maddr
)
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
;
162 /* Everything running correctly already */
163 if (priv
&& priv
->seen_start
)
166 if(priv
&& priv
->is_rtsp
)
167 return masq_rtsp_out(mapp
, ms
, skb_p
, maddr
);
171 th
= (struct tcphdr
*)&(((char *)iph
)[iph
->ihl
*4]);
172 data
= (char *)&th
[1];
174 data_limit
= skb
->h
.raw
+ skb
->len
;
176 if(memcmp(data
, "OPTIONS", 7) == 0 ||
177 memcmp(data
, "DESCRIBE", 8) == 0)
179 IP_MASQ_DEBUG(1-debug
, "RealAudio: Detected RTSP connection\n");
180 /* This is an RTSP client */
183 return masq_rtsp_out(mapp
, ms
, skb_p
, maddr
);
186 /* Check to see if this is the first packet with protocol ID */
187 if (memcmp(data
, "PNA", 3)) {
188 IP_MASQ_DEBUG(1-debug
, "RealAudio: not initial protocol packet - ignored\n");
192 memcpy(&version
, data
, 2);
194 IP_MASQ_DEBUG(1-debug
, "RealAudio: initial seen - protocol version %d\n",
197 priv
->seen_start
= 1;
199 if (ntohs(version
) >= 256)
201 printk(KERN_INFO
"RealAudio: version (%d) not supported\n",
207 while (data
+4 < data_limit
) {
208 memcpy(&msg_id
, data
, 2);
210 memcpy(&msg_len
, data
, 2);
212 if (ntohs(msg_id
) == 0) {
213 /* The zero tag indicates the end of options */
214 IP_MASQ_DEBUG(1-debug
, "RealAudio: packet end tag seen\n");
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 /* The zero tag indicates the end of options */
224 data
+= ntohs(msg_len
);
225 if (data
> data_limit
)
227 printk(KERN_INFO
"RealAudio: Packet too short for data\n");
230 if ((ntohs(msg_id
) == 1) || (ntohs(msg_id
) == 7)) {
233 * Audio UDP data port on client
236 * Robust UDP error correction port number on client
238 * Since these messages are treated just the same, they
239 * are bundled together here....
241 memcpy(&udp_port
, p
, 2);
244 * Sometimes a server sends a message 7 with a zero UDP port
245 * Rather than do anything with this, just ignore it!
251 n_ms
= ip_masq_new(IPPROTO_UDP
,
260 ip_masq_listen(n_ms
);
261 ip_masq_control_add(n_ms
, ms
);
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
));
267 /* Make ref in application data to data connection */
269 if (ntohs(msg_id
) == 1)
270 priv
->data_conn
= n_ms
;
272 priv
->error_conn
= n_ms
;
287 masq_rtsp_out (struct ip_masq_app
*mapp
,
289 struct sk_buff
**skb_p
,
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
);
305 int firstportpos
= 0;
307 int secondportpos
= 0;
308 char *portstart
= NULL
, *portend
= NULL
;
311 /* Everything running correctly already */
312 if (priv
&& priv
->seen_start
)
317 th
= (struct tcphdr
*)&(((char *)iph
)[iph
->ihl
*4]);
318 data
= (char *)&th
[1];
320 data_limit
= skb
->h
.raw
+ skb
->len
;
325 while(data
< data_limit
&& state
>= 0)
331 if(TOLOWER(*data
) == *srchpos
)
334 if(srchpos
== srchend
)
336 IP_MASQ_DEBUG(1-debug
, "Found string %s in message\n",
341 srch
= "client_port";
343 srchend
= srch
+ strlen(srch
);
361 firstport
[firstportpos
++] = *data
;
370 else if(*data
== ';')
373 firstport
[firstportpos
] = 0;
376 else if(ISDIGIT(*data
))
378 firstport
[firstportpos
++] = *data
;
380 else if(*data
!= ' ' && *data
!= '\t')
382 /* This is a badly formed RTSP message, let's bail out */
383 IP_MASQ_DEBUG(1-debug
, "Badly formed RTSP Message\n");
391 secondport
[secondportpos
++] = *data
;
394 else if(*data
== ';')
397 secondport
[secondportpos
] = 0;
405 secondport
[secondportpos
] = 0;
408 else if(ISDIGIT(*data
))
410 secondport
[secondportpos
++] = *data
;
412 else if(*data
!= ' ' && *data
!= '\t')
414 /* This is a badly formed RTSP message, let's bail out */
415 IP_MASQ_DEBUG(1-debug
, "Badly formed RTSP Message\n");
428 char newbuf
[12]; /* xxxxx-xxxxx\0 */
431 udp_port
= htons(simple_strtoul(firstport
, &tmpptr
, 10));
432 n_ms
= ip_masq_new(IPPROTO_UDP
,
440 ip_masq_listen(n_ms
);
441 ip_masq_control_add(n_ms
, ms
);
443 if(secondportpos
> 0)
445 udp_port
= htons(simple_strtoul(secondport
, &tmpptr
, 10));
446 n_ms2
= ip_masq_new(IPPROTO_UDP
,
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
));
463 sprintf(newbuf
, "%d", ntohs(n_ms
->mport
));
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
);
479 priv
->seen_start
= 1;
481 priv
->data_conn
= n_ms
;
483 priv
->error_conn
= n_ms2
;
498 struct ip_masq_app ip_masq_raudio
= {
500 "RealAudio", /* name */
503 masq_raudio_init_1
, /* ip_masq_init_1 */
504 masq_raudio_done_1
, /* ip_masq_done_1 */
505 masq_raudio_out
, /* pkt_out */
510 * ip_masq_raudio initialization
513 __initfunc(int ip_masq_raudio_init(void))
517 for (i
=0; (i
<MAX_MASQ_APP_PORTS
); i
++) {
519 if ((masq_incarnations
[i
] = kmalloc(sizeof(struct ip_masq_app
),
520 GFP_KERNEL
)) == NULL
)
522 memcpy(masq_incarnations
[i
], &ip_masq_raudio
, sizeof(struct ip_masq_app
));
523 if ((j
= register_ip_masq_app(masq_incarnations
[i
],
528 IP_MASQ_DEBUG(1-debug
, "RealAudio: loaded support on port[%d] = %d\n",
531 /* To be safe, force the incarnation table entry to NULL */
532 masq_incarnations
[i
] = NULL
;
539 * ip_masq_raudio fin.
542 int ip_masq_raudio_done(void)
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
]))) {
552 kfree(masq_incarnations
[i
]);
553 masq_incarnations
[i
] = NULL
;
554 IP_MASQ_DEBUG(1-debug
, "RealAudio: unloaded support on port[%d] = %d\n",
565 int init_module(void)
567 if (ip_masq_raudio_init() != 0)
572 void cleanup_module(void)
574 if (ip_masq_raudio_done() != 0)
575 printk(KERN_INFO
"ip_masq_raudio: can't remove module");