2 * IP_MASQ_VDOLIVE - VDO Live masquerading module
5 * Version: @(#)$Id: ip_masq_vdolive.c,v 1.4 1998/10/06 04:49:07 davem Exp $
7 * Author: Nigel Metheringham <Nigel.Metheringham@ThePLAnet.net>
10 * Fixes: Minor changes for 2.1 by
11 * Steven Clarke <Steven.Clarke@ThePlanet.Net>, Planet Online Ltd
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
19 * Thank you to VDOnet Corporation for allowing me access to
20 * a protocol description without an NDA. This means that
21 * this module can be distributed as source - a great help!
25 #include <linux/config.h>
26 #include <linux/module.h>
27 #include <linux/types.h>
28 #include <linux/kernel.h>
29 #include <asm/system.h>
30 #include <linux/skbuff.h>
33 #include <linux/init.h>
34 #include <net/protocol.h>
36 #include <net/ip_masq.h>
38 struct vdolive_priv_data
{
40 unsigned short origport
;
41 unsigned short masqport
;
47 * List of ports (up to MAX_MASQ_APP_PORTS) to be handled by helper
48 * First port is set to the default port.
50 static int ports
[MAX_MASQ_APP_PORTS
] = {7000}; /* I rely on the trailing items being set to zero */
51 struct ip_masq_app
*masq_incarnations
[MAX_MASQ_APP_PORTS
];
56 #ifdef CONFIG_IP_MASQ_DEBUG
58 MODULE_PARM(debug
, "i");
61 MODULE_PARM(ports
, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS
) "i");
64 masq_vdolive_init_1 (struct ip_masq_app
*mapp
, struct ip_masq
*ms
)
67 if ((ms
->app_data
= kmalloc(sizeof(struct vdolive_priv_data
),
69 IP_MASQ_DEBUG(1-debug
, "VDOlive: No memory for application data\n");
72 struct vdolive_priv_data
*priv
=
73 (struct vdolive_priv_data
*)ms
->app_data
;
82 masq_vdolive_done_1 (struct ip_masq_app
*mapp
, struct ip_masq
*ms
)
86 kfree_s(ms
->app_data
, sizeof(struct vdolive_priv_data
));
91 masq_vdolive_out (struct ip_masq_app
*mapp
, struct ip_masq
*ms
, struct sk_buff
**skb_p
, __u32 maddr
)
96 char *data
, *data_limit
;
97 unsigned int tagval
; /* This should be a 32 bit quantity */
99 struct vdolive_priv_data
*priv
=
100 (struct vdolive_priv_data
*)ms
->app_data
;
102 /* This doesn't work at all if no priv data was allocated on startup */
106 /* Everything running correctly already */
107 if (priv
->state
== 3)
112 th
= (struct tcphdr
*)&(((char *)iph
)[iph
->ihl
*4]);
113 data
= (char *)&th
[1];
115 data_limit
= skb
->h
.raw
+ skb
->len
;
117 if (data
+8 > data_limit
) {
118 IP_MASQ_DEBUG(1-debug
, "VDOlive: packet too short for ID %p %p\n", data
, data_limit
);
121 memcpy(&tagval
, data
+4, 4);
122 IP_MASQ_DEBUG(1-debug
, "VDOlive: packet seen, tag %ld, in initial state %d\n", ntohl(tagval
), priv
->state
);
124 /* Check for leading packet ID */
125 if ((ntohl(tagval
) != 6) && (ntohl(tagval
) != 1)) {
126 IP_MASQ_DEBUG(1-debug
, "VDOlive: unrecognised tag %ld, in initial state %d\n", ntohl(tagval
), priv
->state
);
131 /* Check packet is long enough for data - ignore if not */
132 if ((ntohl(tagval
) == 6) && (data
+36 > data_limit
)) {
133 IP_MASQ_DEBUG(1-debug
, "VDOlive: initial packet too short %p %p\n", data
, data_limit
);
135 } else if ((ntohl(tagval
) == 1) && (data
+20 > data_limit
)) {
136 IP_MASQ_DEBUG(1-debug
,"VDOlive: secondary packet too short %p %p\n", data
, data_limit
);
140 /* Adjust data pointers */
142 * I could check the complete protocol version tag
143 * in here however I am just going to look for the
144 * "VDO Live" tag in the hope that this part will
145 * remain constant even if the version changes
147 if (ntohl(tagval
) == 6) {
149 IP_MASQ_DEBUG(1-debug
, "VDOlive: initial packet found\n");
152 IP_MASQ_DEBUG(1-debug
, "VDOlive: secondary packet found\n");
155 if (memcmp(data
, "VDO Live", 8) != 0) {
156 IP_MASQ_DEBUG(1-debug
,"VDOlive: did not find tag\n");
160 * The port number is the next word after the tag.
161 * VDOlive encodes all of these values
162 * in 32 bit words, so in this case I am
163 * skipping the first 2 bytes of the next
164 * word to get to the relevant 16 bits
169 * If we have not seen the port already,
170 * set the masquerading tunnel up
172 if (!priv
->origport
) {
173 memcpy(&priv
->origport
, data
, 2);
174 IP_MASQ_DEBUG(1-debug
, "VDOlive: found port %d\n", ntohs(priv
->origport
));
176 /* Open up a tunnel */
177 n_ms
= ip_masq_new(IPPROTO_UDP
,
179 ms
->saddr
, priv
->origport
,
185 IP_MASQ_DEBUG(1-debug
, "VDOlive: unable to build UDP tunnel for %x:%x\n", ms
->saddr
, priv
->origport
);
186 /* Leave state as unset */
190 ip_masq_listen(n_ms
);
193 priv
->masqport
= n_ms
->mport
;
194 } else if (memcmp(data
, &(priv
->origport
), 2)) {
195 IP_MASQ_DEBUG(1-debug
, "VDOlive: ports do not match\n");
196 /* Write the port in anyhow!!! */
200 * Write masq port into packet
202 memcpy(data
, &(priv
->masqport
), 2);
203 IP_MASQ_DEBUG(1-debug
, "VDOlive: rewrote port %d to %d, server %08X\n", ntohs(priv
->origport
), ntohs(priv
->masqport
), ms
->saddr
);
206 * Set state bit to make which bit has been done
209 priv
->state
|= (ntohl(tagval
) == 6) ? 1 : 2;
215 struct ip_masq_app ip_masq_vdolive
= {
217 "VDOlive", /* name */
220 masq_vdolive_init_1
, /* ip_masq_init_1 */
221 masq_vdolive_done_1
, /* ip_masq_done_1 */
222 masq_vdolive_out
, /* pkt_out */
227 * ip_masq_vdolive initialization
230 __initfunc(int ip_masq_vdolive_init(void))
234 for (i
=0; (i
<MAX_MASQ_APP_PORTS
); i
++) {
236 if ((masq_incarnations
[i
] = kmalloc(sizeof(struct ip_masq_app
),
237 GFP_KERNEL
)) == NULL
)
239 memcpy(masq_incarnations
[i
], &ip_masq_vdolive
, sizeof(struct ip_masq_app
));
240 if ((j
= register_ip_masq_app(masq_incarnations
[i
],
245 IP_MASQ_DEBUG(1-debug
, "RealAudio: loaded support on port[%d] = %d\n", i
, ports
[i
]);
247 /* To be safe, force the incarnation table entry to NULL */
248 masq_incarnations
[i
] = NULL
;
255 * ip_masq_vdolive fin.
258 int ip_masq_vdolive_done(void)
263 for (i
=0; (i
<MAX_MASQ_APP_PORTS
); i
++) {
264 if (masq_incarnations
[i
]) {
265 if ((j
= unregister_ip_masq_app(masq_incarnations
[i
]))) {
268 kfree(masq_incarnations
[i
]);
269 masq_incarnations
[i
] = NULL
;
270 IP_MASQ_DEBUG(1-debug
,"VDOlive: unloaded support on port[%d] = %d\n", i
, ports
[i
]);
281 int init_module(void)
283 if (ip_masq_vdolive_init() != 0)
288 void cleanup_module(void)
290 if (ip_masq_vdolive_done() != 0)
291 IP_MASQ_DEBUG(1-debug
, "ip_masq_vdolive: can't remove module");