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#include <linux/config.h>
41#include <linux/module.h>
42#include <asm/system.h>
43#include <linux/types.h>
44#include <linux/kernel.h>
45#include <linux/skbuff.h>
46#include <linux/in.h>
47#include <linux/ip.h>
48#include <linux/init.h>
49#include <net/protocol.h>
50#include <net/tcp.h>
51
52
53#include <net/ip_masq.h>
54
55
56
57
58
59
60static int ports[MAX_MASQ_APP_PORTS] = {21};
61struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS];
62
63
64
65
66#ifdef CONFIG_IP_MASQ_DEBUG
67static int debug=0;
68MODULE_PARM(debug, "i");
69#endif
70
71MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
72
73
74static int masq_ftp_pasv;
75
76static int
77masq_ftp_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
78{
79 MOD_INC_USE_COUNT;
80 return 0;
81}
82
83static int
84masq_ftp_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
85{
86 MOD_DEC_USE_COUNT;
87 return 0;
88}
89
90int
91masq_ftp_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 *p, *data, *data_limit;
97 unsigned char p1,p2,p3,p4,p5,p6;
98 __u32 from;
99 __u16 port;
100 struct ip_masq *n_ms;
101 char buf[24];
102 unsigned buf_len;
103 int diff;
104
105 skb = *skb_p;
106 iph = skb->nh.iph;
107 th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
108 data = (char *)&th[1];
109
110 data_limit = skb->h.raw + skb->len - 18;
111 if (skb->len >= 6 && (memcmp(data, "PASV\r\n", 6) == 0 || memcmp(data, "pasv\r\n", 6) == 0))
112 ms->app_data = &masq_ftp_pasv;
113
114 while (data < data_limit)
115 {
116 if (memcmp(data,"PORT ",5) && memcmp(data,"port ",5))
117 {
118 data ++;
119 continue;
120 }
121 p = data+5;
122 p1 = simple_strtoul(data+5,&data,10);
123 if (*data!=',')
124 continue;
125 p2 = simple_strtoul(data+1,&data,10);
126 if (*data!=',')
127 continue;
128 p3 = simple_strtoul(data+1,&data,10);
129 if (*data!=',')
130 continue;
131 p4 = simple_strtoul(data+1,&data,10);
132 if (*data!=',')
133 continue;
134 p5 = simple_strtoul(data+1,&data,10);
135 if (*data!=',')
136 continue;
137 p6 = simple_strtoul(data+1,&data,10);
138 if (*data!='\r' && *data!='\n')
139 continue;
140
141 from = (p1<<24) | (p2<<16) | (p3<<8) | p4;
142 port = (p5<<8) | p6;
143
144 IP_MASQ_DEBUG(1-debug, "PORT %X:%X detected\n",from,port);
145
146
147
148
149
150 IP_MASQ_DEBUG(1-debug, "protocol %d %lX:%X %X:%X\n", iph->protocol, htonl(from), htons(port), iph->daddr, 0);
151
152 n_ms = ip_masq_out_get(iph->protocol,
153 htonl(from), htons(port),
154 iph->daddr, 0);
155 if (!n_ms) {
156 n_ms = ip_masq_new(IPPROTO_TCP,
157 maddr, 0,
158 htonl(from), htons(port),
159 iph->daddr, 0,
160 IP_MASQ_F_NO_DPORT);
161
162 if (n_ms==NULL)
163 return 0;
164 ip_masq_control_add(n_ms, ms);
165 }
166
167
168
169
170 from = ntohl(n_ms->maddr);
171 port = ntohs(n_ms->mport);
172 sprintf(buf,"%d,%d,%d,%d,%d,%d",
173 from>>24&255,from>>16&255,from>>8&255,from&255,
174 port>>8&255,port&255);
175 buf_len = strlen(buf);
176
177 IP_MASQ_DEBUG(1-debug, "new PORT %X:%X\n",from,port);
178
179
180
181
182
183 diff = buf_len - (data-p);
184
185
186
187
188
189 if (diff==0) {
190
191
192
193 memcpy(p,buf,buf_len);
194 } else {
195
196 *skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC, p, data-p, buf, buf_len);
197 }
198
199
200
201 ip_masq_listen(n_ms);
202 ip_masq_put(n_ms);
203
204 return diff;
205
206 }
207 return 0;
208
209}
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229int
230masq_ftp_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
231{
232 struct sk_buff *skb;
233 struct iphdr *iph;
234 struct tcphdr *th;
235 char *data, *data_limit;
236 unsigned char p1,p2,p3,p4,p5,p6;
237 __u32 to;
238 __u16 port;
239 struct ip_masq *n_ms;
240
241 if (ms->app_data != &masq_ftp_pasv)
242 return 0;
243
244 skb = *skb_p;
245 iph = skb->nh.iph;
246 th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
247 data = (char *)&th[1];
248 data_limit = skb->h.raw + skb->len;
249
250 while (data < data_limit && *data != ' ')
251 ++data;
252 while (data < data_limit && *data == ' ')
253 ++data;
254 data += 22;
255 if (data >= data_limit || *data != '(')
256 return 0;
257 p1 = simple_strtoul(data+1, &data, 10);
258 if (data >= data_limit || *data != ',')
259 return 0;
260 p2 = simple_strtoul(data+1, &data, 10);
261 if (data >= data_limit || *data != ',')
262 return 0;
263 p3 = simple_strtoul(data+1, &data, 10);
264 if (data >= data_limit || *data != ',')
265 return 0;
266 p4 = simple_strtoul(data+1, &data, 10);
267 if (data >= data_limit || *data != ',')
268 return 0;
269 p5 = simple_strtoul(data+1, &data, 10);
270 if (data >= data_limit || *data != ',')
271 return 0;
272 p6 = simple_strtoul(data+1, &data, 10);
273 if (data >= data_limit || *data != ')')
274 return 0;
275
276 to = (p1<<24) | (p2<<16) | (p3<<8) | p4;
277 port = (p5<<8) | p6;
278
279
280
281
282 IP_MASQ_DEBUG(1-debug, "PASV response %lX:%X %X:%X detected\n", ntohl(ms->saddr), 0, to, port);
283
284 n_ms = ip_masq_out_get(iph->protocol,
285 ms->saddr, 0,
286 htonl(to), htons(port));
287 if (!n_ms) {
288 n_ms = ip_masq_new(IPPROTO_TCP,
289 maddr, 0,
290 ms->saddr, 0,
291 htonl(to), htons(port),
292 IP_MASQ_F_NO_SPORT);
293
294 if (n_ms==NULL)
295 return 0;
296 ip_masq_control_add(n_ms, ms);
297 }
298
299#if 0
300
301
302
303
304
305 n_ms->timeout = ip_masq_expire->tcp_fin_timeout*3;
306#endif
307 ms->app_data = NULL;
308 ip_masq_put(n_ms);
309
310 return 0;
311}
312
313struct ip_masq_app ip_masq_ftp = {
314 NULL,
315 "ftp",
316 0,
317 0,
318 masq_ftp_init_1,
319 masq_ftp_done_1,
320 masq_ftp_out,
321 masq_ftp_in,
322};
323
324
325
326
327
328__initfunc(int ip_masq_ftp_init(void))
329{
330 int i, j;
331
332 for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
333 if (ports[i]) {
334 if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app),
335 GFP_KERNEL)) == NULL)
336 return -ENOMEM;
337 memcpy(masq_incarnations[i], &ip_masq_ftp, sizeof(struct ip_masq_app));
338 if ((j = register_ip_masq_app(masq_incarnations[i],
339 IPPROTO_TCP,
340 ports[i]))) {
341 return j;
342 }
343 IP_MASQ_DEBUG(1-debug, "Ftp: loaded support on port[%d] = %d\n",
344 i, ports[i]);
345 } else {
346
347 masq_incarnations[i] = NULL;
348 }
349 }
350 return 0;
351}
352
353
354
355
356
357int ip_masq_ftp_done(void)
358{
359 int i, j, k;
360
361 k=0;
362 for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
363 if (masq_incarnations[i]) {
364 if ((j = unregister_ip_masq_app(masq_incarnations[i]))) {
365 k = j;
366 } else {
367 kfree(masq_incarnations[i]);
368 masq_incarnations[i] = NULL;
369 IP_MASQ_DEBUG(1-debug, "Ftp: unloaded support on port[%d] = %d\n",
370 i, ports[i]);
371 }
372 }
373 }
374 return k;
375}
376
377#ifdef MODULE
378EXPORT_NO_SYMBOLS;
379
380int init_module(void)
381{
382 if (ip_masq_ftp_init() != 0)
383 return -EIO;
384 return 0;
385}
386
387void cleanup_module(void)
388{
389 if (ip_masq_ftp_done() != 0)
390 printk(KERN_INFO "ip_masq_ftp: can't remove module");
391}
392
393#endif
394