Deleted Added
full compact
alias_ftp.c (124621) alias_ftp.c (127094)
1/*-
2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_ftp.c 124621 2004-01-17 10:52:21Z phk $");
28__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_ftp.c 127094 2004-03-16 21:30:41Z des $");
29
30/*
31 Alias_ftp.c performs special processing for FTP sessions under
32 TCP. Specifically, when a PORT/EPRT command from the client
33 side or 227/229 reply from the server is sent, it is intercepted
34 and modified. The address is changed to the gateway machine
35 and an aliasing port is used.
36

--- 45 unchanged lines hidden (view full) ---

82
83#define FTP_CONTROL_PORT_NUMBER 21
84#define MAX_MESSAGE_SIZE 128
85
86/* FTP protocol flags. */
87#define WAIT_CRLF 0x01
88
89enum ftp_message_type {
29
30/*
31 Alias_ftp.c performs special processing for FTP sessions under
32 TCP. Specifically, when a PORT/EPRT command from the client
33 side or 227/229 reply from the server is sent, it is intercepted
34 and modified. The address is changed to the gateway machine
35 and an aliasing port is used.
36

--- 45 unchanged lines hidden (view full) ---

82
83#define FTP_CONTROL_PORT_NUMBER 21
84#define MAX_MESSAGE_SIZE 128
85
86/* FTP protocol flags. */
87#define WAIT_CRLF 0x01
88
89enum ftp_message_type {
90 FTP_PORT_COMMAND,
91 FTP_EPRT_COMMAND,
92 FTP_227_REPLY,
93 FTP_229_REPLY,
94 FTP_UNKNOWN_MESSAGE
90 FTP_PORT_COMMAND,
91 FTP_EPRT_COMMAND,
92 FTP_227_REPLY,
93 FTP_229_REPLY,
94 FTP_UNKNOWN_MESSAGE
95};
96
95};
96
97static int ParseFtpPortCommand(struct libalias *la, char *, int);
98static int ParseFtpEprtCommand(struct libalias *la, char *, int);
99static int ParseFtp227Reply(struct libalias *la, char *, int);
100static int ParseFtp229Reply(struct libalias *la, char *, int);
101static void NewFtpMessage(struct libalias *la, struct ip *, struct alias_link *, int, int);
97static int ParseFtpPortCommand(struct libalias *la, char *, int);
98static int ParseFtpEprtCommand(struct libalias *la, char *, int);
99static int ParseFtp227Reply(struct libalias *la, char *, int);
100static int ParseFtp229Reply(struct libalias *la, char *, int);
101static void NewFtpMessage(struct libalias *la, struct ip *, struct alias_link *, int, int);
102
103void
104AliasHandleFtpOut(
102
103void
104AliasHandleFtpOut(
105struct libalias *la,
106struct ip *pip, /* IP packet to examine/patch */
107struct alias_link *link, /* The link to go through (aliased port) */
108int maxpacketsize /* The maximum size this packet can grow to (including headers) */)
105 struct libalias *la,
106 struct ip *pip, /* IP packet to examine/patch */
107 struct alias_link *link, /* The link to go through (aliased port) */
108 int maxpacketsize /* The maximum size this packet can grow to
109 (including headers) */ )
109{
110{
110 int hlen, tlen, dlen, pflags;
111 char *sptr;
112 struct tcphdr *tc;
113 int ftp_message_type;
111 int hlen, tlen, dlen, pflags;
112 char *sptr;
113 struct tcphdr *tc;
114 int ftp_message_type;
114
115/* Calculate data length of TCP packet */
115
116/* Calculate data length of TCP packet */
116 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
117 hlen = (pip->ip_hl + tc->th_off) << 2;
118 tlen = ntohs(pip->ip_len);
119 dlen = tlen - hlen;
117 tc = (struct tcphdr *)((char *)pip + (pip->ip_hl << 2));
118 hlen = (pip->ip_hl + tc->th_off) << 2;
119 tlen = ntohs(pip->ip_len);
120 dlen = tlen - hlen;
120
121/* Place string pointer and beginning of data */
121
122/* Place string pointer and beginning of data */
122 sptr = (char *) pip;
123 sptr += hlen;
123 sptr = (char *)pip;
124 sptr += hlen;
124
125/*
126 * Check that data length is not too long and previous message was
127 * properly terminated with CRLF.
128 */
125
126/*
127 * Check that data length is not too long and previous message was
128 * properly terminated with CRLF.
129 */
129 pflags = GetProtocolFlags(link);
130 if (dlen <= MAX_MESSAGE_SIZE && !(pflags & WAIT_CRLF)) {
131 ftp_message_type = FTP_UNKNOWN_MESSAGE;
130 pflags = GetProtocolFlags(link);
131 if (dlen <= MAX_MESSAGE_SIZE && !(pflags & WAIT_CRLF)) {
132 ftp_message_type = FTP_UNKNOWN_MESSAGE;
132
133
133 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER) {
134 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER) {
134/*
135 * When aliasing a client, check for the PORT/EPRT command.
136 */
135/*
136 * When aliasing a client, check for the PORT/EPRT command.
137 */
137 if (ParseFtpPortCommand(la, sptr, dlen))
138 ftp_message_type = FTP_PORT_COMMAND;
139 else if (ParseFtpEprtCommand(la, sptr, dlen))
140 ftp_message_type = FTP_EPRT_COMMAND;
141 } else {
138 if (ParseFtpPortCommand(la, sptr, dlen))
139 ftp_message_type = FTP_PORT_COMMAND;
140 else if (ParseFtpEprtCommand(la, sptr, dlen))
141 ftp_message_type = FTP_EPRT_COMMAND;
142 } else {
142/*
143 * When aliasing a server, check for the 227/229 reply.
144 */
143/*
144 * When aliasing a server, check for the 227/229 reply.
145 */
145 if (ParseFtp227Reply(la, sptr, dlen))
146 ftp_message_type = FTP_227_REPLY;
147 else if (ParseFtp229Reply(la, sptr, dlen)) {
148 ftp_message_type = FTP_229_REPLY;
149 la->true_addr.s_addr = pip->ip_src.s_addr;
150 }
151 }
146 if (ParseFtp227Reply(la, sptr, dlen))
147 ftp_message_type = FTP_227_REPLY;
148 else if (ParseFtp229Reply(la, sptr, dlen)) {
149 ftp_message_type = FTP_229_REPLY;
150 la->true_addr.s_addr = pip->ip_src.s_addr;
151 }
152 }
152
153
153 if (ftp_message_type != FTP_UNKNOWN_MESSAGE)
154 NewFtpMessage(la, pip, link, maxpacketsize, ftp_message_type);
155 }
156
154 if (ftp_message_type != FTP_UNKNOWN_MESSAGE)
155 NewFtpMessage(la, pip, link, maxpacketsize, ftp_message_type);
156 }
157/* Track the msgs which are CRLF term'd for PORT/PASV FW breach */
158
157/* Track the msgs which are CRLF term'd for PORT/PASV FW breach */
158
159 if (dlen) { /* only if there's data */
160 sptr = (char *) pip; /* start over at beginning */
161 tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may have grown */
162 if (sptr[tlen-2] == '\r' && sptr[tlen-1] == '\n')
163 pflags &= ~WAIT_CRLF;
164 else
165 pflags |= WAIT_CRLF;
166 SetProtocolFlags(link, pflags);
167 }
159 if (dlen) { /* only if there's data */
160 sptr = (char *)pip; /* start over at beginning */
161 tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may
162 * have grown */
163 if (sptr[tlen - 2] == '\r' && sptr[tlen - 1] == '\n')
164 pflags &= ~WAIT_CRLF;
165 else
166 pflags |= WAIT_CRLF;
167 SetProtocolFlags(link, pflags);
168 }
168}
169
170static int
171ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen)
172{
169}
170
171static int
172ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen)
173{
173 char ch;
174 int i, state;
175 u_int32_t addr;
176 u_short port;
177 u_int8_t octet;
174 char ch;
175 int i, state;
176 u_int32_t addr;
177 u_short port;
178 u_int8_t octet;
178
179
179 /* Format: "PORT A,D,D,R,PO,RT". */
180 /* Format: "PORT A,D,D,R,PO,RT". */
180
181
181 /* Return if data length is too short. */
182 if (dlen < 18)
183 return 0;
182 /* Return if data length is too short. */
183 if (dlen < 18)
184 return 0;
184
185
185 addr = port = octet = 0;
186 state = -4;
187 for (i = 0; i < dlen; i++) {
188 ch = sptr[i];
189 switch (state) {
190 case -4: if (ch == 'P') state++; else return 0; break;
191 case -3: if (ch == 'O') state++; else return 0; break;
192 case -2: if (ch == 'R') state++; else return 0; break;
193 case -1: if (ch == 'T') state++; else return 0; break;
186 addr = port = octet = 0;
187 state = -4;
188 for (i = 0; i < dlen; i++) {
189 ch = sptr[i];
190 switch (state) {
191 case -4:
192 if (ch == 'P')
193 state++;
194 else
195 return 0;
196 break;
197 case -3:
198 if (ch == 'O')
199 state++;
200 else
201 return 0;
202 break;
203 case -2:
204 if (ch == 'R')
205 state++;
206 else
207 return 0;
208 break;
209 case -1:
210 if (ch == 'T')
211 state++;
212 else
213 return 0;
214 break;
194
215
195 case 0:
196 if (isspace(ch))
197 break;
198 else
199 state++;
200 case 1: case 3: case 5: case 7: case 9: case 11:
201 if (isdigit(ch)) {
202 octet = ch - '0';
203 state++;
204 } else
205 return 0;
206 break;
207 case 2: case 4: case 6: case 8:
208 if (isdigit(ch))
209 octet = 10 * octet + ch - '0';
210 else if (ch == ',') {
211 addr = (addr << 8) + octet;
212 state++;
213 } else
214 return 0;
215 break;
216 case 10: case 12:
217 if (isdigit(ch))
218 octet = 10 * octet + ch - '0';
219 else if (ch == ',' || state == 12) {
220 port = (port << 8) + octet;
221 state++;
222 } else
223 return 0;
224 break;
216 case 0:
217 if (isspace(ch))
218 break;
219 else
220 state++;
221 case 1:
222 case 3:
223 case 5:
224 case 7:
225 case 9:
226 case 11:
227 if (isdigit(ch)) {
228 octet = ch - '0';
229 state++;
230 } else
231 return 0;
232 break;
233 case 2:
234 case 4:
235 case 6:
236 case 8:
237 if (isdigit(ch))
238 octet = 10 * octet + ch - '0';
239 else if (ch == ',') {
240 addr = (addr << 8) + octet;
241 state++;
242 } else
243 return 0;
244 break;
245 case 10:
246 case 12:
247 if (isdigit(ch))
248 octet = 10 * octet + ch - '0';
249 else if (ch == ',' || state == 12) {
250 port = (port << 8) + octet;
251 state++;
252 } else
253 return 0;
254 break;
255 }
225 }
256 }
226 }
227
257
228 if (state == 13) {
229 la->true_addr.s_addr = htonl(addr);
230 la->true_port = port;
231 return 1;
232 } else
233 return 0;
258 if (state == 13) {
259 la->true_addr.s_addr = htonl(addr);
260 la->true_port = port;
261 return 1;
262 } else
263 return 0;
234}
235
236static int
237ParseFtpEprtCommand(struct libalias *la, char *sptr, int dlen)
238{
264}
265
266static int
267ParseFtpEprtCommand(struct libalias *la, char *sptr, int dlen)
268{
239 char ch, delim;
240 int i, state;
241 u_int32_t addr;
242 u_short port;
243 u_int8_t octet;
269 char ch, delim;
270 int i, state;
271 u_int32_t addr;
272 u_short port;
273 u_int8_t octet;
244
274
245 /* Format: "EPRT |1|A.D.D.R|PORT|". */
275 /* Format: "EPRT |1|A.D.D.R|PORT|". */
246
276
247 /* Return if data length is too short. */
248 if (dlen < 18)
249 return 0;
277 /* Return if data length is too short. */
278 if (dlen < 18)
279 return 0;
250
280
251 addr = port = octet = 0;
252 delim = '|'; /* XXX gcc -Wuninitialized */
253 state = -4;
254 for (i = 0; i < dlen; i++) {
255 ch = sptr[i];
256 switch (state)
257 {
258 case -4: if (ch == 'E') state++; else return 0; break;
259 case -3: if (ch == 'P') state++; else return 0; break;
260 case -2: if (ch == 'R') state++; else return 0; break;
261 case -1: if (ch == 'T') state++; else return 0; break;
281 addr = port = octet = 0;
282 delim = '|'; /* XXX gcc -Wuninitialized */
283 state = -4;
284 for (i = 0; i < dlen; i++) {
285 ch = sptr[i];
286 switch (state) {
287 case -4:
288 if (ch == 'E')
289 state++;
290 else
291 return 0;
292 break;
293 case -3:
294 if (ch == 'P')
295 state++;
296 else
297 return 0;
298 break;
299 case -2:
300 if (ch == 'R')
301 state++;
302 else
303 return 0;
304 break;
305 case -1:
306 if (ch == 'T')
307 state++;
308 else
309 return 0;
310 break;
262
311
263 case 0:
264 if (!isspace(ch)) {
265 delim = ch;
266 state++;
267 }
268 break;
269 case 1:
270 if (ch == '1') /* IPv4 address */
271 state++;
272 else
273 return 0;
274 break;
275 case 2:
276 if (ch == delim)
277 state++;
278 else
279 return 0;
280 break;
281 case 3: case 5: case 7: case 9:
282 if (isdigit(ch)) {
283 octet = ch - '0';
284 state++;
285 } else
286 return 0;
287 break;
288 case 4: case 6: case 8: case 10:
289 if (isdigit(ch))
290 octet = 10 * octet + ch - '0';
291 else if (ch == '.' || state == 10) {
292 addr = (addr << 8) + octet;
293 state++;
294 } else
295 return 0;
296 break;
297 case 11:
298 if (isdigit(ch)) {
299 port = ch - '0';
300 state++;
301 } else
302 return 0;
303 break;
304 case 12:
305 if (isdigit(ch))
306 port = 10 * port + ch - '0';
307 else if (ch == delim)
308 state++;
309 else
310 return 0;
311 break;
312 case 0:
313 if (!isspace(ch)) {
314 delim = ch;
315 state++;
316 }
317 break;
318 case 1:
319 if (ch == '1') /* IPv4 address */
320 state++;
321 else
322 return 0;
323 break;
324 case 2:
325 if (ch == delim)
326 state++;
327 else
328 return 0;
329 break;
330 case 3:
331 case 5:
332 case 7:
333 case 9:
334 if (isdigit(ch)) {
335 octet = ch - '0';
336 state++;
337 } else
338 return 0;
339 break;
340 case 4:
341 case 6:
342 case 8:
343 case 10:
344 if (isdigit(ch))
345 octet = 10 * octet + ch - '0';
346 else if (ch == '.' || state == 10) {
347 addr = (addr << 8) + octet;
348 state++;
349 } else
350 return 0;
351 break;
352 case 11:
353 if (isdigit(ch)) {
354 port = ch - '0';
355 state++;
356 } else
357 return 0;
358 break;
359 case 12:
360 if (isdigit(ch))
361 port = 10 * port + ch - '0';
362 else if (ch == delim)
363 state++;
364 else
365 return 0;
366 break;
367 }
312 }
368 }
313 }
314
369
315 if (state == 13) {
316 la->true_addr.s_addr = htonl(addr);
317 la->true_port = port;
318 return 1;
319 } else
320 return 0;
370 if (state == 13) {
371 la->true_addr.s_addr = htonl(addr);
372 la->true_port = port;
373 return 1;
374 } else
375 return 0;
321}
322
323static int
324ParseFtp227Reply(struct libalias *la, char *sptr, int dlen)
325{
376}
377
378static int
379ParseFtp227Reply(struct libalias *la, char *sptr, int dlen)
380{
326 char ch;
327 int i, state;
328 u_int32_t addr;
329 u_short port;
330 u_int8_t octet;
381 char ch;
382 int i, state;
383 u_int32_t addr;
384 u_short port;
385 u_int8_t octet;
331
386
332 /* Format: "227 Entering Passive Mode (A,D,D,R,PO,RT)" */
387 /* Format: "227 Entering Passive Mode (A,D,D,R,PO,RT)" */
333
388
334 /* Return if data length is too short. */
335 if (dlen < 17)
336 return 0;
389 /* Return if data length is too short. */
390 if (dlen < 17)
391 return 0;
337
392
338 addr = port = octet = 0;
393 addr = port = octet = 0;
339
394
340 state = -3;
341 for (i = 0; i < dlen; i++) {
342 ch = sptr[i];
343 switch (state)
344 {
345 case -3: if (ch == '2') state++; else return 0; break;
346 case -2: if (ch == '2') state++; else return 0; break;
347 case -1: if (ch == '7') state++; else return 0; break;
395 state = -3;
396 for (i = 0; i < dlen; i++) {
397 ch = sptr[i];
398 switch (state) {
399 case -3:
400 if (ch == '2')
401 state++;
402 else
403 return 0;
404 break;
405 case -2:
406 if (ch == '2')
407 state++;
408 else
409 return 0;
410 break;
411 case -1:
412 if (ch == '7')
413 state++;
414 else
415 return 0;
416 break;
348
417
349 case 0:
350 if (ch == '(')
351 state++;
352 break;
353 case 1: case 3: case 5: case 7: case 9: case 11:
354 if (isdigit(ch)) {
355 octet = ch - '0';
356 state++;
357 } else
358 return 0;
359 break;
360 case 2: case 4: case 6: case 8:
361 if (isdigit(ch))
362 octet = 10 * octet + ch - '0';
363 else if (ch == ',') {
364 addr = (addr << 8) + octet;
365 state++;
366 } else
367 return 0;
368 break;
369 case 10: case 12:
370 if (isdigit(ch))
371 octet = 10 * octet + ch - '0';
372 else if (ch == ',' || (state == 12 && ch == ')')) {
373 port = (port << 8) + octet;
374 state++;
375 } else
376 return 0;
377 break;
418 case 0:
419 if (ch == '(')
420 state++;
421 break;
422 case 1:
423 case 3:
424 case 5:
425 case 7:
426 case 9:
427 case 11:
428 if (isdigit(ch)) {
429 octet = ch - '0';
430 state++;
431 } else
432 return 0;
433 break;
434 case 2:
435 case 4:
436 case 6:
437 case 8:
438 if (isdigit(ch))
439 octet = 10 * octet + ch - '0';
440 else if (ch == ',') {
441 addr = (addr << 8) + octet;
442 state++;
443 } else
444 return 0;
445 break;
446 case 10:
447 case 12:
448 if (isdigit(ch))
449 octet = 10 * octet + ch - '0';
450 else if (ch == ',' || (state == 12 && ch == ')')) {
451 port = (port << 8) + octet;
452 state++;
453 } else
454 return 0;
455 break;
456 }
378 }
457 }
379 }
380
458
381 if (state == 13) {
382 la->true_port = port;
383 la->true_addr.s_addr = htonl(addr);
384 return 1;
385 } else
386 return 0;
459 if (state == 13) {
460 la->true_port = port;
461 la->true_addr.s_addr = htonl(addr);
462 return 1;
463 } else
464 return 0;
387}
388
389static int
390ParseFtp229Reply(struct libalias *la, char *sptr, int dlen)
391{
465}
466
467static int
468ParseFtp229Reply(struct libalias *la, char *sptr, int dlen)
469{
392 char ch, delim;
393 int i, state;
394 u_short port;
470 char ch, delim;
471 int i, state;
472 u_short port;
395
473
396 /* Format: "229 Entering Extended Passive Mode (|||PORT|)" */
474 /* Format: "229 Entering Extended Passive Mode (|||PORT|)" */
397
475
398 /* Return if data length is too short. */
399 if (dlen < 11)
400 return 0;
476 /* Return if data length is too short. */
477 if (dlen < 11)
478 return 0;
401
479
402 port = 0;
403 delim = '|'; /* XXX gcc -Wuninitialized */
480 port = 0;
481 delim = '|'; /* XXX gcc -Wuninitialized */
404
482
405 state = -3;
406 for (i = 0; i < dlen; i++) {
407 ch = sptr[i];
408 switch (state)
409 {
410 case -3: if (ch == '2') state++; else return 0; break;
411 case -2: if (ch == '2') state++; else return 0; break;
412 case -1: if (ch == '9') state++; else return 0; break;
483 state = -3;
484 for (i = 0; i < dlen; i++) {
485 ch = sptr[i];
486 switch (state) {
487 case -3:
488 if (ch == '2')
489 state++;
490 else
491 return 0;
492 break;
493 case -2:
494 if (ch == '2')
495 state++;
496 else
497 return 0;
498 break;
499 case -1:
500 if (ch == '9')
501 state++;
502 else
503 return 0;
504 break;
413
505
414 case 0:
415 if (ch == '(')
416 state++;
417 break;
418 case 1:
419 delim = ch;
420 state++;
421 break;
422 case 2: case 3:
423 if (ch == delim)
424 state++;
425 else
426 return 0;
427 break;
428 case 4:
429 if (isdigit(ch)) {
430 port = ch - '0';
431 state++;
432 } else
433 return 0;
434 break;
435 case 5:
436 if (isdigit(ch))
437 port = 10 * port + ch - '0';
438 else if (ch == delim)
439 state++;
440 else
441 return 0;
442 break;
443 case 6:
444 if (ch == ')')
445 state++;
446 else
447 return 0;
448 break;
506 case 0:
507 if (ch == '(')
508 state++;
509 break;
510 case 1:
511 delim = ch;
512 state++;
513 break;
514 case 2:
515 case 3:
516 if (ch == delim)
517 state++;
518 else
519 return 0;
520 break;
521 case 4:
522 if (isdigit(ch)) {
523 port = ch - '0';
524 state++;
525 } else
526 return 0;
527 break;
528 case 5:
529 if (isdigit(ch))
530 port = 10 * port + ch - '0';
531 else if (ch == delim)
532 state++;
533 else
534 return 0;
535 break;
536 case 6:
537 if (ch == ')')
538 state++;
539 else
540 return 0;
541 break;
542 }
449 }
543 }
450 }
451
544
452 if (state == 7) {
453 la->true_port = port;
454 return 1;
455 } else
456 return 0;
545 if (state == 7) {
546 la->true_port = port;
547 return 1;
548 } else
549 return 0;
457}
458
459static void
460NewFtpMessage(struct libalias *la, struct ip *pip,
550}
551
552static void
553NewFtpMessage(struct libalias *la, struct ip *pip,
461 struct alias_link *link,
462 int maxpacketsize,
463 int ftp_message_type)
554 struct alias_link *link,
555 int maxpacketsize,
556 int ftp_message_type)
464{
557{
465 struct alias_link *ftp_link;
558 struct alias_link *ftp_link;
466
467/* Security checks. */
559
560/* Security checks. */
468 if (pip->ip_src.s_addr != la->true_addr.s_addr)
469 return;
561 if (pip->ip_src.s_addr != la->true_addr.s_addr)
562 return;
470
563
471 if (la->true_port < IPPORT_RESERVED)
472 return;
564 if (la->true_port < IPPORT_RESERVED)
565 return;
473
474/* Establish link to address and port found in FTP control message. */
566
567/* Establish link to address and port found in FTP control message. */
475 ftp_link = FindUdpTcpOut(la, la->true_addr, GetDestAddress(link),
476 htons(la->true_port), 0, IPPROTO_TCP, 1);
568 ftp_link = FindUdpTcpOut(la, la->true_addr, GetDestAddress(link),
569 htons(la->true_port), 0, IPPROTO_TCP, 1);
477
570
478 if (ftp_link != NULL)
479 {
480 int slen, hlen, tlen, dlen;
481 struct tcphdr *tc;
571 if (ftp_link != NULL) {
572 int slen, hlen, tlen, dlen;
573 struct tcphdr *tc;
482
483#ifndef NO_FW_PUNCH
574
575#ifndef NO_FW_PUNCH
484 /* Punch hole in firewall */
485 PunchFWHole(ftp_link);
576 /* Punch hole in firewall */
577 PunchFWHole(ftp_link);
486#endif
487
488/* Calculate data length of TCP packet */
578#endif
579
580/* Calculate data length of TCP packet */
489 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
490 hlen = (pip->ip_hl + tc->th_off) << 2;
491 tlen = ntohs(pip->ip_len);
492 dlen = tlen - hlen;
581 tc = (struct tcphdr *)((char *)pip + (pip->ip_hl << 2));
582 hlen = (pip->ip_hl + tc->th_off) << 2;
583 tlen = ntohs(pip->ip_len);
584 dlen = tlen - hlen;
493
494/* Create new FTP message. */
585
586/* Create new FTP message. */
495 {
496 char stemp[MAX_MESSAGE_SIZE + 1];
497 char *sptr;
498 u_short alias_port;
499 u_char *ptr;
500 int a1, a2, a3, a4, p1, p2;
501 struct in_addr alias_address;
587 {
588 char stemp[MAX_MESSAGE_SIZE + 1];
589 char *sptr;
590 u_short alias_port;
591 u_char *ptr;
592 int a1, a2, a3, a4, p1, p2;
593 struct in_addr alias_address;
502
503/* Decompose alias address into quad format */
594
595/* Decompose alias address into quad format */
504 alias_address = GetAliasAddress(link);
505 ptr = (u_char *) &alias_address.s_addr;
506 a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr;
596 alias_address = GetAliasAddress(link);
597 ptr = (u_char *) & alias_address.s_addr;
598 a1 = *ptr++;
599 a2 = *ptr++;
600 a3 = *ptr++;
601 a4 = *ptr;
507
602
508 alias_port = GetAliasPort(ftp_link);
603 alias_port = GetAliasPort(ftp_link);
509
604
510 switch (ftp_message_type)
511 {
512 case FTP_PORT_COMMAND:
513 case FTP_227_REPLY:
514 /* Decompose alias port into pair format. */
515 ptr = (char *) &alias_port;
516 p1 = *ptr++; p2=*ptr;
605 switch (ftp_message_type) {
606 case FTP_PORT_COMMAND:
607 case FTP_227_REPLY:
608 /* Decompose alias port into pair format. */
609 ptr = (char *)&alias_port;
610 p1 = *ptr++;
611 p2 = *ptr;
517
612
518 if (ftp_message_type == FTP_PORT_COMMAND) {
519 /* Generate PORT command string. */
520 sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
521 a1,a2,a3,a4,p1,p2);
522 } else {
523 /* Generate 227 reply string. */
524 sprintf(stemp,
525 "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
526 a1,a2,a3,a4,p1,p2);
527 }
528 break;
529 case FTP_EPRT_COMMAND:
530 /* Generate EPRT command string. */
531 sprintf(stemp, "EPRT |1|%d.%d.%d.%d|%d|\r\n",
532 a1,a2,a3,a4,ntohs(alias_port));
533 break;
534 case FTP_229_REPLY:
535 /* Generate 229 reply string. */
536 sprintf(stemp, "229 Entering Extended Passive Mode (|||%d|)\r\n",
537 ntohs(alias_port));
538 break;
539 }
613 if (ftp_message_type == FTP_PORT_COMMAND) {
614 /* Generate PORT command string. */
615 sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
616 a1, a2, a3, a4, p1, p2);
617 } else {
618 /* Generate 227 reply string. */
619 sprintf(stemp,
620 "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
621 a1, a2, a3, a4, p1, p2);
622 }
623 break;
624 case FTP_EPRT_COMMAND:
625 /* Generate EPRT command string. */
626 sprintf(stemp, "EPRT |1|%d.%d.%d.%d|%d|\r\n",
627 a1, a2, a3, a4, ntohs(alias_port));
628 break;
629 case FTP_229_REPLY:
630 /* Generate 229 reply string. */
631 sprintf(stemp, "229 Entering Extended Passive Mode (|||%d|)\r\n",
632 ntohs(alias_port));
633 break;
634 }
540
541/* Save string length for IP header modification */
635
636/* Save string length for IP header modification */
542 slen = strlen(stemp);
637 slen = strlen(stemp);
543
544/* Copy modified buffer into IP packet. */
638
639/* Copy modified buffer into IP packet. */
545 sptr = (char *) pip; sptr += hlen;
546 strncpy(sptr, stemp, maxpacketsize-hlen);
547 }
640 sptr = (char *)pip;
641 sptr += hlen;
642 strncpy(sptr, stemp, maxpacketsize - hlen);
643 }
548
549/* Save information regarding modified seq and ack numbers */
644
645/* Save information regarding modified seq and ack numbers */
550 {
551 int delta;
646 {
647 int delta;
552
648
553 SetAckModified(link);
554 delta = GetDeltaSeqOut(pip, link);
555 AddSeq(pip, link, delta+slen-dlen);
556 }
649 SetAckModified(link);
650 delta = GetDeltaSeqOut(pip, link);
651 AddSeq(pip, link, delta + slen - dlen);
652 }
557
558/* Revise IP header */
653
654/* Revise IP header */
559 {
560 u_short new_len;
655 {
656 u_short new_len;
561
657
562 new_len = htons(hlen + slen);
563 DifferentialChecksum(&pip->ip_sum,
564 &new_len,
565 &pip->ip_len,
566 1);
567 pip->ip_len = new_len;
568 }
658 new_len = htons(hlen + slen);
659 DifferentialChecksum(&pip->ip_sum,
660 &new_len,
661 &pip->ip_len,
662 1);
663 pip->ip_len = new_len;
664 }
569
570/* Compute TCP checksum for revised packet */
665
666/* Compute TCP checksum for revised packet */
571 tc->th_sum = 0;
572 tc->th_sum = TcpChecksum(pip);
573 }
574 else
575 {
667 tc->th_sum = 0;
668 tc->th_sum = TcpChecksum(pip);
669 } else {
576#ifdef DEBUG
670#ifdef DEBUG
577 fprintf(stderr,
578 "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
671 fprintf(stderr,
672 "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
579#endif
673#endif
580 }
674 }
581}
675}