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#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>
31#include <linux/in.h>
32#include <linux/ip.h>
33#include <linux/init.h>
34#include <net/protocol.h>
35#include <net/tcp.h>
36#include <net/ip_masq.h>
37
38struct vdolive_priv_data {
39
40 unsigned short origport;
41 unsigned short masqport;
42
43 unsigned short state;
44};
45
46
47
48
49
50static int ports[MAX_MASQ_APP_PORTS] = {7000};
51struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS];
52
53
54
55
56#ifdef CONFIG_IP_MASQ_DEBUG
57static int debug=0;
58MODULE_PARM(debug, "i");
59#endif
60
61MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
62
63static int
64masq_vdolive_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
65{
66 MOD_INC_USE_COUNT;
67 if ((ms->app_data = kmalloc(sizeof(struct vdolive_priv_data),
68 GFP_ATOMIC)) == NULL)
69 IP_MASQ_DEBUG(1-debug, "VDOlive: No memory for application data\n");
70 else
71 {
72 struct vdolive_priv_data *priv =
73 (struct vdolive_priv_data *)ms->app_data;
74 priv->origport = 0;
75 priv->masqport = 0;
76 priv->state = 0;
77 }
78 return 0;
79}
80
81static int
82masq_vdolive_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
83{
84 MOD_DEC_USE_COUNT;
85 if (ms->app_data)
86 kfree_s(ms->app_data, sizeof(struct vdolive_priv_data));
87 return 0;
88}
89
90int
91masq_vdolive_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
92{
93 struct sk_buff *skb;
94 struct iphdr *iph;
95 struct tcphdr *th;
96 char *data, *data_limit;
97 unsigned int tagval;
98 struct ip_masq *n_ms;
99 struct vdolive_priv_data *priv =
100 (struct vdolive_priv_data *)ms->app_data;
101
102
103 if (!priv)
104 return 0;
105
106
107 if (priv->state == 3)
108 return 0;
109
110 skb = *skb_p;
111 iph = skb->nh.iph;
112 th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
113 data = (char *)&th[1];
114
115 data_limit = skb->h.raw + skb->len;
116
117 if (data+8 > data_limit) {
118 IP_MASQ_DEBUG(1-debug, "VDOlive: packet too short for ID %p %p\n", data, data_limit);
119 return 0;
120 }
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);
123
124
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);
127 return 0;
128 }
129
130
131
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);
134 return 0;
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);
137 return 0;
138 }
139
140
141
142
143
144
145
146
147 if (ntohl(tagval) == 6) {
148 data += 24;
149 IP_MASQ_DEBUG(1-debug, "VDOlive: initial packet found\n");
150 } else {
151 data += 8;
152 IP_MASQ_DEBUG(1-debug, "VDOlive: secondary packet found\n");
153 }
154
155 if (memcmp(data, "VDO Live", 8) != 0) {
156 IP_MASQ_DEBUG(1-debug,"VDOlive: did not find tag\n");
157 return 0;
158 }
159
160
161
162
163
164
165
166 data += 10;
167
168
169
170
171
172 if (!priv->origport) {
173 memcpy(&priv->origport, data, 2);
174 IP_MASQ_DEBUG(1-debug, "VDOlive: found port %d\n", ntohs(priv->origport));
175
176
177 n_ms = ip_masq_new(IPPROTO_UDP,
178 maddr, 0,
179 ms->saddr, priv->origport,
180 ms->daddr, 0,
181 IP_MASQ_F_NO_DPORT);
182
183 if (n_ms==NULL) {
184 ip_masq_put(n_ms);
185 IP_MASQ_DEBUG(1-debug, "VDOlive: unable to build UDP tunnel for %x:%x\n", ms->saddr, priv->origport);
186
187 priv->origport = 0;
188 return 0;
189 }
190 ip_masq_listen(n_ms);
191
192 ip_masq_put(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
197 }
198
199
200
201
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);
204
205
206
207
208
209 priv->state |= (ntohl(tagval) == 6) ? 1 : 2;
210
211 return 0;
212}
213
214
215struct ip_masq_app ip_masq_vdolive = {
216 NULL,
217 "VDOlive",
218 0,
219 0,
220 masq_vdolive_init_1,
221 masq_vdolive_done_1,
222 masq_vdolive_out,
223 NULL
224};
225
226
227
228
229
230__initfunc(int ip_masq_vdolive_init(void))
231{
232 int i, j;
233
234 for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
235 if (ports[i]) {
236 if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app),
237 GFP_KERNEL)) == NULL)
238 return -ENOMEM;
239 memcpy(masq_incarnations[i], &ip_masq_vdolive, sizeof(struct ip_masq_app));
240 if ((j = register_ip_masq_app(masq_incarnations[i],
241 IPPROTO_TCP,
242 ports[i]))) {
243 return j;
244 }
245 IP_MASQ_DEBUG(1-debug, "RealAudio: loaded support on port[%d] = %d\n", i, ports[i]);
246 } else {
247
248 masq_incarnations[i] = NULL;
249 }
250 }
251 return 0;
252}
253
254
255
256
257
258int ip_masq_vdolive_done(void)
259{
260 int i, j, k;
261
262 k=0;
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]))) {
266 k = j;
267 } else {
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]);
271 }
272 }
273 }
274 return k;
275}
276
277
278#ifdef MODULE
279EXPORT_NO_SYMBOLS;
280
281int init_module(void)
282{
283 if (ip_masq_vdolive_init() != 0)
284 return -EIO;
285 return 0;
286}
287
288void cleanup_module(void)
289{
290 if (ip_masq_vdolive_done() != 0)
291 IP_MASQ_DEBUG(1-debug, "ip_masq_vdolive: can't remove module");
292}
293
294#endif
295