Linux 2.2.0
[davej-history.git] / net / ipv4 / ip_masq_raudio.c
blobee3e276b9d8bd2c8e01a48cc566867244f7307c4
1 /*
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.
22 * Limitations
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
38 * piece is playing.
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
51 * ports=x1,x2,x3...
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
55 * modules.
57 * Fixes:
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>
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>
80 #ifndef DEBUG_CONFIG_IP_MASQ_RAUDIO
81 #define DEBUG_CONFIG_IP_MASQ_RAUDIO 0
82 #endif
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 */
94 short seen_start;
95 short is_rtsp;
98 int
99 masq_rtsp_out (struct ip_masq_app *mapp,
100 struct ip_masq *ms,
101 struct sk_buff **skb_p,
102 __u32 maddr);
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];
112 * Debug level
114 #ifdef CONFIG_IP_MASQ_DEBUG
115 static int debug=0;
116 MODULE_PARM(debug, "i");
117 #endif
119 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
122 static int
123 masq_raudio_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
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
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;
138 return 0;
141 static int
142 masq_raudio_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
144 MOD_DEC_USE_COUNT;
145 if (ms->app_data)
146 kfree_s(ms->app_data, sizeof(struct raudio_priv_data));
147 return 0;
151 masq_raudio_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
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;
162 /* Everything running correctly already */
163 if (priv && priv->seen_start)
164 return 0;
166 if(priv && priv->is_rtsp)
167 return masq_rtsp_out(mapp, ms, skb_p, maddr);
169 skb = *skb_p;
170 iph = skb->nh.iph;
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 */
181 if(priv)
182 priv->is_rtsp = 1;
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");
189 return(0);
191 data += 3;
192 memcpy(&version, data, 2);
194 IP_MASQ_DEBUG(1-debug, "RealAudio: initial seen - protocol version %d\n",
195 ntohs(version));
196 if (priv)
197 priv->seen_start = 1;
199 if (ntohs(version) >= 256)
201 printk(KERN_INFO "RealAudio: version (%d) not supported\n",
202 ntohs(version));
203 return 0;
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 /* The zero tag indicates the end of options */
214 IP_MASQ_DEBUG(1-debug, "RealAudio: packet end tag seen\n");
215 return 0;
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 */
221 return 0;
223 p = data;
224 data += ntohs(msg_len);
225 if (data > data_limit)
227 printk(KERN_INFO "RealAudio: Packet too short for data\n");
228 return 0;
230 if ((ntohs(msg_id) == 1) || (ntohs(msg_id) == 7)) {
232 * MsgId == 1
233 * Audio UDP data port on client
235 * MsgId == 7
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!
247 if (udp_port == 0)
248 continue;
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);
257 if (n_ms==NULL)
258 return 0;
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 */
268 if (priv) {
269 if (ntohs(msg_id) == 1)
270 priv->data_conn = n_ms;
271 else
272 priv->error_conn = n_ms;
275 ip_masq_put(n_ms);
278 return 0;
282 * masq_rtsp_out
287 masq_rtsp_out (struct ip_masq_app *mapp,
288 struct ip_masq *ms,
289 struct sk_buff **skb_p,
290 __u32 maddr)
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;
311 /* Everything running correctly already */
312 if (priv && priv->seen_start)
313 return 0;
315 skb = *skb_p;
316 iph = skb->nh.iph;
317 th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
318 data = (char *)&th[1];
320 data_limit = skb->h.raw + skb->len;
322 firstport[0] = 0;
323 secondport[0] = 0;
325 while(data < data_limit && state >= 0)
327 switch(state)
329 case 0:
330 case 1:
331 if(TOLOWER(*data) == *srchpos)
333 srchpos++;
334 if(srchpos == srchend)
336 IP_MASQ_DEBUG(1-debug, "Found string %s in message\n",
337 srch);
338 state++;
339 if(state == 1)
341 srch = "client_port";
342 srchpos = srch;
343 srchend = srch + strlen(srch);
347 else
349 srchpos = srch;
351 break;
352 case 2:
353 if(*data == '=')
354 state = 3;
355 break;
356 case 3:
357 if(ISDIGIT(*data))
359 portstart = data;
360 firstportpos = 0;
361 firstport[firstportpos++] = *data;
362 state = 4;
364 break;
365 case 4:
366 if(*data == '-')
368 state = 5;
370 else if(*data == ';')
372 portend = data - 1;
373 firstport[firstportpos] = 0;
374 state = -1;
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");
384 return 0;
386 break;
387 case 5:
388 if(ISDIGIT(*data))
390 secondportpos = 0;
391 secondport[secondportpos++] = *data;
392 state = 6;
394 else if(*data == ';')
396 portend = data - 1;
397 secondport[secondportpos] = 0;
398 state = -1;
400 break;
401 case 6:
402 if(*data == ';')
404 portend = data - 1;
405 secondport[secondportpos] = 0;
406 state = -1;
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");
416 return 0;
418 break;
420 data++;
423 if(state >= 0)
424 return 0;
426 if(firstportpos > 0)
428 char newbuf[12]; /* xxxxx-xxxxx\0 */
429 char* tmpptr;
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;
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,
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;
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));
461 else
463 sprintf(newbuf, "%d", ntohs(n_ms->mport));
464 n_ms2 = NULL;
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);
472 else
474 return 0;
477 if(priv)
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;
486 * Release tunnels
489 if (n_ms)
490 ip_masq_put(n_ms);
492 if (n_ms2)
493 ip_masq_put(n_ms2);
495 return diff;
498 struct ip_masq_app ip_masq_raudio = {
499 NULL, /* next */
500 "RealAudio", /* name */
501 0, /* type */
502 0, /* n_attach */
503 masq_raudio_init_1, /* ip_masq_init_1 */
504 masq_raudio_done_1, /* ip_masq_done_1 */
505 masq_raudio_out, /* pkt_out */
506 NULL /* pkt_in */
510 * ip_masq_raudio initialization
513 __initfunc(int ip_masq_raudio_init(void))
515 int i, j;
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;
528 IP_MASQ_DEBUG(1-debug, "RealAudio: loaded support on port[%d] = %d\n",
529 i, ports[i]);
530 } else {
531 /* To be safe, force the incarnation table entry to NULL */
532 masq_incarnations[i] = NULL;
535 return 0;
539 * ip_masq_raudio fin.
542 int ip_masq_raudio_done(void)
544 int i, j, k;
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]);
559 return k;
562 #ifdef MODULE
563 EXPORT_NO_SYMBOLS;
565 int init_module(void)
567 if (ip_masq_raudio_init() != 0)
568 return -EIO;
569 return 0;
572 void cleanup_module(void)
574 if (ip_masq_raudio_done() != 0)
575 printk(KERN_INFO "ip_masq_raudio: can't remove module");
578 #endif /* MODULE */