]>
Commit | Line | Data |
---|---|---|
7ba0088d | 1 | /* |
fdfd5971 | 2 | * Copyright (c) 2000-2009 Apple Inc. All rights reserved. |
7ba0088d | 3 | * |
fdfd5971 A |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
7ba0088d A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
fdfd5971 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
7ba0088d | 27 | */ |
fdfd5971 | 28 | |
7ba0088d A |
29 | /*- |
30 | * Copyright (c) 2001 Charles Mott <cmott@scientech.com> | |
31 | * All rights reserved. | |
32 | * | |
33 | * Redistribution and use in source and binary forms, with or without | |
34 | * modification, are permitted provided that the following conditions | |
35 | * are met: | |
36 | * 1. Redistributions of source code must retain the above copyright | |
37 | * notice, this list of conditions and the following disclaimer. | |
38 | * 2. Redistributions in binary form must reproduce the above copyright | |
39 | * notice, this list of conditions and the following disclaimer in the | |
40 | * documentation and/or other materials provided with the distribution. | |
41 | * | |
42 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
43 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
44 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
45 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
46 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
47 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
48 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
49 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
50 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
51 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
52 | * SUCH DAMAGE. | |
53 | * | |
54 | * Based upon: | |
55 | * $FreeBSD: src/lib/libalias/alias_ftp.c,v 1.5.2.4 2001/08/21 03:50:25 brian Exp $ | |
56 | */ | |
57 | ||
b7080c8e A |
58 | /* |
59 | Alias_ftp.c performs special processing for FTP sessions under | |
7ba0088d A |
60 | TCP. Specifically, when a PORT/EPRT command from the client |
61 | side or 227/229 reply from the server is sent, it is intercepted | |
62 | and modified. The address is changed to the gateway machine | |
63 | and an aliasing port is used. | |
b7080c8e | 64 | |
7ba0088d A |
65 | For this routine to work, the message must fit entirely into a |
66 | single TCP packet. This is typically the case, but exceptions | |
b7080c8e A |
67 | can easily be envisioned under the actual specifications. |
68 | ||
69 | Probably the most troubling aspect of the approach taken here is | |
7ba0088d | 70 | that the new message will typically be a different length, and |
b7080c8e A |
71 | this causes a certain amount of bookkeeping to keep track of the |
72 | changes of sequence and acknowledgment numbers, since the client | |
73 | machine is totally unaware of the modification to the TCP stream. | |
74 | ||
75 | ||
7ba0088d | 76 | References: RFC 959, RFC 2428. |
b7080c8e A |
77 | |
78 | Initial version: August, 1996 (cjm) | |
79 | ||
80 | Version 1.6 | |
81 | Brian Somers and Martin Renters identified an IP checksum | |
82 | error for modified IP packets. | |
83 | ||
84 | Version 1.7: January 9, 1996 (cjm) | |
7ba0088d | 85 | Differential checksum computation for change |
b7080c8e | 86 | in IP packet length. |
7ba0088d | 87 | |
b7080c8e A |
88 | Version 2.1: May, 1997 (cjm) |
89 | Very minor changes to conform with | |
90 | local/global/function naming conventions | |
7ba0088d A |
91 | within the packet aliasing module. |
92 | ||
93 | Version 3.1: May, 2000 (eds) | |
94 | Add support for passive mode, alias the 227 replies. | |
b7080c8e A |
95 | |
96 | See HISTORY file for record of revisions. | |
97 | */ | |
98 | ||
99 | /* Includes */ | |
100 | #include <ctype.h> | |
7ba0088d | 101 | #include <stdio.h> |
b7080c8e A |
102 | #include <string.h> |
103 | #include <sys/types.h> | |
104 | #include <netinet/in_systm.h> | |
105 | #include <netinet/in.h> | |
106 | #include <netinet/ip.h> | |
107 | #include <netinet/tcp.h> | |
108 | ||
109 | #include "alias_local.h" | |
110 | ||
7ba0088d A |
111 | #define FTP_CONTROL_PORT_NUMBER 21 |
112 | #define MAX_MESSAGE_SIZE 128 | |
113 | ||
114 | enum ftp_message_type { | |
115 | FTP_PORT_COMMAND, | |
116 | FTP_EPRT_COMMAND, | |
117 | FTP_227_REPLY, | |
118 | FTP_229_REPLY, | |
119 | FTP_UNKNOWN_MESSAGE | |
120 | }; | |
b7080c8e | 121 | |
7ba0088d A |
122 | static int ParseFtpPortCommand(char *, int); |
123 | static int ParseFtpEprtCommand(char *, int); | |
124 | static int ParseFtp227Reply(char *, int); | |
125 | static int ParseFtp229Reply(char *, int); | |
126 | static void NewFtpMessage(struct ip *, struct alias_link *, int, int); | |
b7080c8e | 127 | |
7ba0088d A |
128 | static struct in_addr true_addr; /* in network byte order. */ |
129 | static u_short true_port; /* in host byte order. */ | |
b7080c8e A |
130 | |
131 | void | |
132 | AliasHandleFtpOut( | |
133 | struct ip *pip, /* IP packet to examine/patch */ | |
134 | struct alias_link *link, /* The link to go through (aliased port) */ | |
135 | int maxpacketsize /* The maximum size this packet can grow to (including headers) */) | |
136 | { | |
137 | int hlen, tlen, dlen; | |
b7080c8e A |
138 | char *sptr; |
139 | struct tcphdr *tc; | |
7ba0088d A |
140 | int ftp_message_type; |
141 | ||
b7080c8e A |
142 | /* Calculate data length of TCP packet */ |
143 | tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); | |
144 | hlen = (pip->ip_hl + tc->th_off) << 2; | |
145 | tlen = ntohs(pip->ip_len); | |
146 | dlen = tlen - hlen; | |
147 | ||
b7080c8e | 148 | /* Place string pointer and beginning of data */ |
7ba0088d | 149 | sptr = (char *) pip; |
b7080c8e A |
150 | sptr += hlen; |
151 | ||
7ba0088d A |
152 | /* |
153 | * Check that data length is not too long and previous message was | |
154 | * properly terminated with CRLF. | |
155 | */ | |
156 | if (dlen <= MAX_MESSAGE_SIZE && GetLastLineCrlfTermed(link)) { | |
157 | ftp_message_type = FTP_UNKNOWN_MESSAGE; | |
158 | ||
159 | if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER) { | |
160 | /* | |
161 | * When aliasing a client, check for the PORT/EPRT command. | |
162 | */ | |
163 | if (ParseFtpPortCommand(sptr, dlen)) | |
164 | ftp_message_type = FTP_PORT_COMMAND; | |
165 | else if (ParseFtpEprtCommand(sptr, dlen)) | |
166 | ftp_message_type = FTP_EPRT_COMMAND; | |
167 | } else { | |
168 | /* | |
169 | * When aliasing a server, check for the 227/229 reply. | |
170 | */ | |
171 | if (ParseFtp227Reply(sptr, dlen)) | |
172 | ftp_message_type = FTP_227_REPLY; | |
173 | else if (ParseFtp229Reply(sptr, dlen)) | |
174 | ftp_message_type = FTP_229_REPLY; | |
175 | } | |
176 | ||
177 | if (ftp_message_type != FTP_UNKNOWN_MESSAGE) | |
178 | NewFtpMessage(pip, link, maxpacketsize, ftp_message_type); | |
179 | } | |
180 | ||
181 | /* Track the msgs which are CRLF term'd for PORT/PASV FW breach */ | |
182 | ||
183 | if (dlen) { /* only if there's data */ | |
184 | sptr = (char *) pip; /* start over at beginning */ | |
185 | tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may have grown */ | |
186 | SetLastLineCrlfTermed(link, | |
187 | (sptr[tlen-2] == '\r') && (sptr[tlen-1] == '\n')); | |
188 | } | |
189 | } | |
190 | ||
191 | static int | |
192 | ParseFtpPortCommand(char *sptr, int dlen) | |
193 | { | |
194 | char ch; | |
195 | int i, state; | |
196 | u_int32_t addr; | |
197 | u_short port; | |
198 | u_int8_t octet; | |
199 | ||
200 | /* Format: "PORT A,D,D,R,PO,RT". */ | |
201 | ||
202 | /* Return if data length is too short. */ | |
203 | if (dlen < 18) | |
204 | return 0; | |
205 | ||
206 | addr = port = octet = 0; | |
207 | state = -4; | |
208 | for (i = 0; i < dlen; i++) { | |
209 | ch = sptr[i]; | |
210 | switch (state) { | |
211 | case -4: if (ch == 'P') state++; else return 0; break; | |
212 | case -3: if (ch == 'O') state++; else return 0; break; | |
213 | case -2: if (ch == 'R') state++; else return 0; break; | |
214 | case -1: if (ch == 'T') state++; else return 0; break; | |
215 | ||
216 | case 0: | |
217 | if (isspace(ch)) | |
218 | break; | |
219 | else | |
220 | state++; | |
221 | case 1: case 3: case 5: case 7: case 9: case 11: | |
222 | if (isdigit(ch)) { | |
223 | octet = ch - '0'; | |
224 | state++; | |
225 | } else | |
226 | return 0; | |
227 | break; | |
228 | case 2: case 4: case 6: case 8: | |
229 | if (isdigit(ch)) | |
230 | octet = 10 * octet + ch - '0'; | |
231 | else if (ch == ',') { | |
232 | addr = (addr << 8) + octet; | |
233 | state++; | |
234 | } else | |
235 | return 0; | |
236 | break; | |
237 | case 10: case 12: | |
238 | if (isdigit(ch)) | |
239 | octet = 10 * octet + ch - '0'; | |
240 | else if (ch == ',' || state == 12) { | |
241 | port = (port << 8) + octet; | |
242 | state++; | |
243 | } else | |
244 | return 0; | |
245 | break; | |
246 | } | |
247 | } | |
248 | ||
249 | if (state == 13) { | |
250 | true_addr.s_addr = htonl(addr); | |
251 | true_port = port; | |
252 | return 1; | |
253 | } else | |
254 | return 0; | |
255 | } | |
256 | ||
257 | static int | |
258 | ParseFtpEprtCommand(char *sptr, int dlen) | |
259 | { | |
260 | char ch, delim; | |
261 | int i, state; | |
262 | u_int32_t addr; | |
263 | u_short port; | |
264 | u_int8_t octet; | |
265 | ||
266 | /* Format: "EPRT |1|A.D.D.R|PORT|". */ | |
267 | ||
268 | /* Return if data length is too short. */ | |
269 | if (dlen < 18) | |
270 | return 0; | |
271 | ||
272 | addr = port = octet = 0; | |
273 | delim = '|'; /* XXX gcc -Wuninitialized */ | |
274 | state = -4; | |
275 | for (i = 0; i < dlen; i++) { | |
276 | ch = sptr[i]; | |
277 | switch (state) | |
278 | { | |
279 | case -4: if (ch == 'E') state++; else return 0; break; | |
280 | case -3: if (ch == 'P') state++; else return 0; break; | |
281 | case -2: if (ch == 'R') state++; else return 0; break; | |
282 | case -1: if (ch == 'T') state++; else return 0; break; | |
283 | ||
284 | case 0: | |
285 | if (!isspace(ch)) { | |
286 | delim = ch; | |
287 | state++; | |
288 | } | |
289 | break; | |
290 | case 1: | |
291 | if (ch == '1') /* IPv4 address */ | |
292 | state++; | |
293 | else | |
294 | return 0; | |
295 | break; | |
296 | case 2: | |
297 | if (ch == delim) | |
298 | state++; | |
299 | else | |
300 | return 0; | |
301 | break; | |
302 | case 3: case 5: case 7: case 9: | |
303 | if (isdigit(ch)) { | |
304 | octet = ch - '0'; | |
305 | state++; | |
306 | } else | |
307 | return 0; | |
308 | break; | |
309 | case 4: case 6: case 8: case 10: | |
310 | if (isdigit(ch)) | |
311 | octet = 10 * octet + ch - '0'; | |
312 | else if (ch == '.' || state == 10) { | |
313 | addr = (addr << 8) + octet; | |
314 | state++; | |
315 | } else | |
316 | return 0; | |
317 | break; | |
318 | case 11: | |
319 | if (isdigit(ch)) { | |
320 | port = ch - '0'; | |
321 | state++; | |
322 | } else | |
323 | return 0; | |
324 | break; | |
325 | case 12: | |
326 | if (isdigit(ch)) | |
327 | port = 10 * port + ch - '0'; | |
328 | else if (ch == delim) | |
329 | state++; | |
330 | else | |
331 | return 0; | |
332 | break; | |
333 | } | |
334 | } | |
335 | ||
336 | if (state == 13) { | |
337 | true_addr.s_addr = htonl(addr); | |
338 | true_port = port; | |
339 | return 1; | |
340 | } else | |
341 | return 0; | |
342 | } | |
b7080c8e | 343 | |
7ba0088d A |
344 | static int |
345 | ParseFtp227Reply(char *sptr, int dlen) | |
346 | { | |
347 | char ch; | |
348 | int i, state; | |
349 | u_int32_t addr; | |
350 | u_short port; | |
351 | u_int8_t octet; | |
352 | ||
353 | /* Format: "227 Entering Passive Mode (A,D,D,R,PO,RT)" */ | |
354 | ||
355 | /* Return if data length is too short. */ | |
356 | if (dlen < 17) | |
357 | return 0; | |
358 | ||
359 | addr = port = octet = 0; | |
360 | ||
361 | state = -3; | |
362 | for (i = 0; i < dlen; i++) { | |
363 | ch = sptr[i]; | |
364 | switch (state) | |
b7080c8e | 365 | { |
7ba0088d A |
366 | case -3: if (ch == '2') state++; else return 0; break; |
367 | case -2: if (ch == '2') state++; else return 0; break; | |
368 | case -1: if (ch == '7') state++; else return 0; break; | |
369 | ||
370 | case 0: | |
371 | if (ch == '(') | |
372 | state++; | |
373 | break; | |
374 | case 1: case 3: case 5: case 7: case 9: case 11: | |
375 | if (isdigit(ch)) { | |
376 | octet = ch - '0'; | |
377 | state++; | |
378 | } else | |
379 | return 0; | |
380 | break; | |
381 | case 2: case 4: case 6: case 8: | |
382 | if (isdigit(ch)) | |
383 | octet = 10 * octet + ch - '0'; | |
384 | else if (ch == ',') { | |
385 | addr = (addr << 8) + octet; | |
386 | state++; | |
387 | } else | |
388 | return 0; | |
389 | break; | |
390 | case 10: case 12: | |
391 | if (isdigit(ch)) | |
392 | octet = 10 * octet + ch - '0'; | |
393 | else if (ch == ',' || (state == 12 && ch == ')')) { | |
394 | port = (port << 8) + octet; | |
395 | state++; | |
396 | } else | |
397 | return 0; | |
398 | break; | |
399 | } | |
b7080c8e | 400 | } |
7ba0088d A |
401 | |
402 | if (state == 13) { | |
403 | true_port = port; | |
404 | true_addr.s_addr = htonl(addr); | |
405 | return 1; | |
406 | } else | |
407 | return 0; | |
408 | } | |
409 | ||
410 | static int | |
411 | ParseFtp229Reply(char *sptr, int dlen) | |
412 | { | |
413 | char ch, delim; | |
414 | int i, state; | |
415 | u_short port; | |
416 | ||
417 | /* Format: "229 Entering Extended Passive Mode (|||PORT|)" */ | |
418 | ||
419 | /* Return if data length is too short. */ | |
420 | if (dlen < 11) | |
421 | return 0; | |
422 | ||
423 | port = 0; | |
424 | delim = '|'; /* XXX gcc -Wuninitialized */ | |
425 | ||
426 | state = -3; | |
427 | for (i = 0; i < dlen; i++) { | |
428 | ch = sptr[i]; | |
429 | switch (state) | |
430 | { | |
431 | case -3: if (ch == '2') state++; else return 0; break; | |
432 | case -2: if (ch == '2') state++; else return 0; break; | |
433 | case -1: if (ch == '9') state++; else return 0; break; | |
434 | ||
435 | case 0: | |
436 | if (ch == '(') | |
437 | state++; | |
438 | break; | |
439 | case 1: | |
440 | delim = ch; | |
441 | state++; | |
442 | break; | |
443 | case 2: case 3: | |
444 | if (ch == delim) | |
445 | state++; | |
446 | else | |
447 | return 0; | |
448 | break; | |
449 | case 4: | |
450 | if (isdigit(ch)) { | |
451 | port = ch - '0'; | |
452 | state++; | |
453 | } else | |
454 | return 0; | |
455 | break; | |
456 | case 5: | |
457 | if (isdigit(ch)) | |
458 | port = 10 * port + ch - '0'; | |
459 | else if (ch == delim) | |
460 | state++; | |
461 | else | |
462 | return 0; | |
463 | break; | |
464 | case 6: | |
465 | if (ch == ')') | |
466 | state++; | |
467 | else | |
468 | return 0; | |
469 | break; | |
470 | } | |
471 | } | |
472 | ||
473 | if (state == 7) { | |
474 | true_port = port; | |
475 | return 1; | |
476 | } else | |
477 | return 0; | |
b7080c8e A |
478 | } |
479 | ||
480 | static void | |
7ba0088d A |
481 | NewFtpMessage(struct ip *pip, |
482 | struct alias_link *link, | |
483 | int maxpacketsize, | |
484 | int ftp_message_type) | |
485 | { | |
b7080c8e A |
486 | struct alias_link *ftp_link; |
487 | ||
7ba0088d A |
488 | /* Security checks. */ |
489 | if (ftp_message_type != FTP_229_REPLY && | |
490 | pip->ip_src.s_addr != true_addr.s_addr) | |
491 | return; | |
492 | ||
493 | if (true_port < IPPORT_RESERVED) | |
494 | return; | |
495 | ||
496 | /* Establish link to address and port found in FTP control message. */ | |
b7080c8e | 497 | ftp_link = FindUdpTcpOut(true_addr, GetDestAddress(link), |
7ba0088d | 498 | htons(true_port), 0, IPPROTO_TCP, 1); |
b7080c8e A |
499 | |
500 | if (ftp_link != NULL) | |
501 | { | |
502 | int slen, hlen, tlen, dlen; | |
503 | struct tcphdr *tc; | |
504 | ||
505 | #ifndef NO_FW_PUNCH | |
7ba0088d A |
506 | if (ftp_message_type == FTP_PORT_COMMAND || |
507 | ftp_message_type == FTP_EPRT_COMMAND) { | |
508 | /* Punch hole in firewall */ | |
509 | PunchFWHole(ftp_link); | |
510 | } | |
b7080c8e A |
511 | #endif |
512 | ||
513 | /* Calculate data length of TCP packet */ | |
514 | tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); | |
515 | hlen = (pip->ip_hl + tc->th_off) << 2; | |
516 | tlen = ntohs(pip->ip_len); | |
517 | dlen = tlen - hlen; | |
518 | ||
7ba0088d | 519 | /* Create new FTP message. */ |
b7080c8e | 520 | { |
7ba0088d | 521 | char stemp[MAX_MESSAGE_SIZE + 1]; |
b7080c8e A |
522 | char *sptr; |
523 | u_short alias_port; | |
524 | u_char *ptr; | |
7ba0088d | 525 | int a1, a2, a3, a4, p1, p2; |
b7080c8e | 526 | struct in_addr alias_address; |
7ba0088d | 527 | |
b7080c8e A |
528 | /* Decompose alias address into quad format */ |
529 | alias_address = GetAliasAddress(link); | |
530 | ptr = (u_char *) &alias_address.s_addr; | |
531 | a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr; | |
532 | ||
7ba0088d A |
533 | alias_port = GetAliasPort(ftp_link); |
534 | ||
535 | switch (ftp_message_type) | |
536 | { | |
537 | case FTP_PORT_COMMAND: | |
538 | case FTP_227_REPLY: | |
539 | /* Decompose alias port into pair format. */ | |
b8dff150 | 540 | ptr = (u_char *) &alias_port; |
7ba0088d A |
541 | p1 = *ptr++; p2=*ptr; |
542 | ||
543 | if (ftp_message_type == FTP_PORT_COMMAND) { | |
544 | /* Generate PORT command string. */ | |
fdfd5971 | 545 | snprintf(stemp, sizeof(stemp), "PORT %d,%d,%d,%d,%d,%d\r\n", |
7ba0088d A |
546 | a1,a2,a3,a4,p1,p2); |
547 | } else { | |
548 | /* Generate 227 reply string. */ | |
fdfd5971 | 549 | snprintf(stemp, sizeof(stemp), |
7ba0088d A |
550 | "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n", |
551 | a1,a2,a3,a4,p1,p2); | |
552 | } | |
553 | break; | |
554 | case FTP_EPRT_COMMAND: | |
555 | /* Generate EPRT command string. */ | |
fdfd5971 | 556 | snprintf(stemp, sizeof(stemp), "EPRT |1|%d.%d.%d.%d|%d|\r\n", |
7ba0088d A |
557 | a1,a2,a3,a4,ntohs(alias_port)); |
558 | break; | |
559 | case FTP_229_REPLY: | |
560 | /* Generate 229 reply string. */ | |
fdfd5971 | 561 | snprintf(stemp, sizeof(stemp), "229 Entering Extended Passive Mode (|||%d|)\r\n", |
7ba0088d A |
562 | ntohs(alias_port)); |
563 | break; | |
564 | } | |
b7080c8e A |
565 | |
566 | /* Save string length for IP header modification */ | |
567 | slen = strlen(stemp); | |
568 | ||
7ba0088d | 569 | /* Copy modified buffer into IP packet. */ |
b7080c8e A |
570 | sptr = (char *) pip; sptr += hlen; |
571 | strncpy(sptr, stemp, maxpacketsize-hlen); | |
572 | } | |
573 | ||
574 | /* Save information regarding modified seq and ack numbers */ | |
575 | { | |
576 | int delta; | |
577 | ||
578 | SetAckModified(link); | |
579 | delta = GetDeltaSeqOut(pip, link); | |
580 | AddSeq(pip, link, delta+slen-dlen); | |
581 | } | |
582 | ||
583 | /* Revise IP header */ | |
584 | { | |
585 | u_short new_len; | |
586 | ||
587 | new_len = htons(hlen + slen); | |
588 | DifferentialChecksum(&pip->ip_sum, | |
589 | &new_len, | |
590 | &pip->ip_len, | |
591 | 1); | |
592 | pip->ip_len = new_len; | |
593 | } | |
594 | ||
595 | /* Compute TCP checksum for revised packet */ | |
596 | tc->th_sum = 0; | |
597 | tc->th_sum = TcpChecksum(pip); | |
598 | } | |
599 | else | |
600 | { | |
601 | #ifdef DEBUG | |
602 | fprintf(stderr, | |
603 | "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n"); | |
604 | #endif | |
605 | } | |
606 | } |