Deleted Added
full compact
alias_ftp.c (50597) alias_ftp.c (59075)
1/*
2 Alias_ftp.c performs special processing for FTP sessions under
3 TCP. Specifically, when a PORT command from the client side
4 is sent, it is intercepted and modified. The address is changed
5 to the gateway machine and an aliasing port is used.
6
7 For this routine to work, the PORT command must fit entirely
8 into a single TCP packet. This is typically the case, but exceptions
9 can easily be envisioned under the actual specifications.
10
11 Probably the most troubling aspect of the approach taken here is
12 that the new PORT command will typically be a different length, and
13 this causes a certain amount of bookkeeping to keep track of the
14 changes of sequence and acknowledgment numbers, since the client
15 machine is totally unaware of the modification to the TCP stream.
16
1/*
2 Alias_ftp.c performs special processing for FTP sessions under
3 TCP. Specifically, when a PORT command from the client side
4 is sent, it is intercepted and modified. The address is changed
5 to the gateway machine and an aliasing port is used.
6
7 For this routine to work, the PORT command must fit entirely
8 into a single TCP packet. This is typically the case, but exceptions
9 can easily be envisioned under the actual specifications.
10
11 Probably the most troubling aspect of the approach taken here is
12 that the new PORT command will typically be a different length, and
13 this causes a certain amount of bookkeeping to keep track of the
14 changes of sequence and acknowledgment numbers, since the client
15 machine is totally unaware of the modification to the TCP stream.
16
17 This version also supports the EPRT command, which is functionally
18 equivalent to the PORT command, but was designed to support both
19 IPv4 and IPv6 addresses. See RFC 2428 for specifications.
17
20
21
18 This software is placed into the public domain with no restrictions
19 on its distribution.
20
21 Initial version: August, 1996 (cjm)
22
23 Version 1.6
24 Brian Somers and Martin Renters identified an IP checksum
25 error for modified IP packets.
26
27 Version 1.7: January 9, 1996 (cjm)
22 This software is placed into the public domain with no restrictions
23 on its distribution.
24
25 Initial version: August, 1996 (cjm)
26
27 Version 1.6
28 Brian Somers and Martin Renters identified an IP checksum
29 error for modified IP packets.
30
31 Version 1.7: January 9, 1996 (cjm)
28 Differental checksum computation for change
32 Differential checksum computation for change
29 in IP packet length.
30
31 Version 2.1: May, 1997 (cjm)
32 Very minor changes to conform with
33 local/global/function naming conventions
33 in IP packet length.
34
35 Version 2.1: May, 1997 (cjm)
36 Very minor changes to conform with
37 local/global/function naming conventions
34 withing the packet alising module.
38 within the packet aliasing module.
35
36 See HISTORY file for record of revisions.
37
39
40 See HISTORY file for record of revisions.
41
38 $FreeBSD: head/sys/netinet/libalias/alias_ftp.c 50597 1999-08-29 23:17:04Z billf $
42 $FreeBSD: head/sys/netinet/libalias/alias_ftp.c 59075 2000-04-06 15:54:52Z ru $
39*/
40
41/* Includes */
42#include <ctype.h>
43#include <stdio.h>
44#include <string.h>
45#include <sys/types.h>
46#include <netinet/in_systm.h>
47#include <netinet/in.h>
48#include <netinet/ip.h>
49#include <netinet/tcp.h>
50
51#include "alias_local.h"
52
43*/
44
45/* Includes */
46#include <ctype.h>
47#include <stdio.h>
48#include <string.h>
49#include <sys/types.h>
50#include <netinet/in_systm.h>
51#include <netinet/in.h>
52#include <netinet/ip.h>
53#include <netinet/tcp.h>
54
55#include "alias_local.h"
56
53static void NewFtpPortCommand(struct ip *, struct alias_link *, struct in_addr, u_short, int);
57static int ParseFtpPortCommand(char *, int, struct ip *, struct alias_link *, int);
58static void ParseFtpEprtCommand(char *, int, struct ip *, struct alias_link *, int);
59static void NewFtpPortCommand(struct ip *, struct alias_link *, struct in_addr, u_short, int, int);
54
55
56
57void
58AliasHandleFtpOut(
59struct ip *pip, /* IP packet to examine/patch */
60struct alias_link *link, /* The link to go through (aliased port) */
61int maxpacketsize /* The maximum size this packet can grow to (including headers) */)
62{
63 int hlen, tlen, dlen;
60
61
62
63void
64AliasHandleFtpOut(
65struct ip *pip, /* IP packet to examine/patch */
66struct alias_link *link, /* The link to go through (aliased port) */
67int maxpacketsize /* The maximum size this packet can grow to (including headers) */)
68{
69 int hlen, tlen, dlen;
64 struct in_addr true_addr;
65 u_short true_port;
66 char *sptr;
67 struct tcphdr *tc;
68
69/* Calculate data length of TCP packet */
70 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
71 hlen = (pip->ip_hl + tc->th_off) << 2;
72 tlen = ntohs(pip->ip_len);
73 dlen = tlen - hlen;
74
70 char *sptr;
71 struct tcphdr *tc;
72
73/* Calculate data length of TCP packet */
74 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
75 hlen = (pip->ip_hl + tc->th_off) << 2;
76 tlen = ntohs(pip->ip_len);
77 dlen = tlen - hlen;
78
75/* Return is data length is too long or too short */
79/* Return if data length is too long or too short */
76 if (dlen<10 || dlen>80)
77 return;
78
79/* Place string pointer and beginning of data */
80 sptr = (char *) pip;
81 sptr += hlen;
82
83/* Parse through string using state diagram method */
80 if (dlen<10 || dlen>80)
81 return;
82
83/* Place string pointer and beginning of data */
84 sptr = (char *) pip;
85 sptr += hlen;
86
87/* Parse through string using state diagram method */
88 if (!ParseFtpPortCommand(sptr, dlen, pip, link, maxpacketsize))
89 ParseFtpEprtCommand(sptr, dlen, pip, link, maxpacketsize);
90}
91
92static int
93ParseFtpPortCommand(
94char *sptr,
95int dlen,
96struct ip *pip, /* IP packet to examine/patch */
97struct alias_link *link, /* The link to go through (aliased port) */
98int maxpacketsize /* The maximum size this packet can grow to (including headers) */)
99{
100 struct in_addr true_addr;
101 u_short true_port;
102 char ch;
103 int i, state;
104 u_long a1, a2, a3, a4;
105 u_short p1, p2;
106
107 a1=0; a2=0; a3=0; a4=0; p1=0; p2=0;
108 state=-4;
109 for (i=0; i<dlen; i++)
84 {
110 {
85 char ch, zero;
86 int i, state;
87 u_long a1, a2, a3, a4;
88 u_short p1, p2;
111 ch = sptr[i];
112 switch (state)
113 {
114 case -4: if (ch == 'P') state++; else return 0; break;
115 case -3: if (ch == 'O') state++; else return 0; break;
116 case -2: if (ch == 'R') state++; else return 0; break;
117 case -1: if (ch == 'T') state++; else return 0; break;
89
118
90 a1=0; a2=0; a3=0; a4=0; p1=0; p2=0;
91 zero = '0';
92 state=-4;
93 for (i=0; i<dlen; i++)
94 {
95 ch = sptr[i];
96 switch (state)
97 {
98 case -4: if (ch == 'P') state=-3; else return; break;
99 case -3: if (ch == 'O') state=-2; else return; break;
100 case -2: if (ch == 'R') state=-1; else return; break;
101 case -1: if (ch == 'T') state= 0; else return; break;
119 case 0 :
120 if (isdigit(ch)) {a1=ch-'0'; state++;} break;
121 case 1 :
122 if (isdigit(ch)) a1=10*a1+ch-'0'; else state++; break;
123 case 2 :
124 if (isdigit(ch)) {a2=ch-'0'; state++;} break;
125 case 3 :
126 if (isdigit(ch)) a2=10*a2+ch-'0'; else state++; break;
127 case 4 :
128 if (isdigit(ch)) {a3=ch-'0'; state++;} break;
129 case 5 :
130 if (isdigit(ch)) a3=10*a3+ch-'0'; else state++; break;
131 case 6 :
132 if (isdigit(ch)) {a4=ch-'0'; state++;} break;
133 case 7 :
134 if (isdigit(ch)) a4=10*a4+ch-'0'; else state++; break;
135 case 8 :
136 if (isdigit(ch)) {p1=ch-'0'; state++;} break;
137 case 9 :
138 if (isdigit(ch)) p1=10*p1+ch-'0'; else state++; break;
139 case 10:
140 if (isdigit(ch)) {p2=ch-'0'; state++;} break;
141 case 11:
142 if (isdigit(ch)) p2=10*p2+ch-'0'; break;
143 }
144 }
102
145
103 case 0 :
104 if (isdigit(ch)) {a1=ch-zero; state=1 ;} break;
105 case 1 :
106 if (isdigit(ch)) a1=10*a1+ch-zero; else state=2 ; break;
107 case 2 :
108 if (isdigit(ch)) {a2=ch-zero; state=3 ;} break;
109 case 3 :
110 if (isdigit(ch)) a2=10*a2+ch-zero; else state=4 ; break;
111 case 4 :
112 if (isdigit(ch)) {a3=ch-zero; state=5 ;} break;
113 case 5 :
114 if (isdigit(ch)) a3=10*a3+ch-zero; else state=6 ; break;
115 case 6 :
116 if (isdigit(ch)) {a4=ch-zero; state=7 ;} break;
117 case 7 :
118 if (isdigit(ch)) a4=10*a4+ch-zero; else state=8 ; break;
119 case 8 :
120 if (isdigit(ch)) {p1=ch-zero; state=9 ;} break;
121 case 9 :
122 if (isdigit(ch)) p1=10*p1+ch-zero; else state=10; break;
123 case 10:
124 if (isdigit(ch)) {p2=ch-zero; state=11;} break;
125 case 11:
126 if (isdigit(ch)) p2=10*p2+ch-zero; break;
127 }
128 }
146 if (state == 11)
147 {
148 true_port = htons((p1<<8) + p2);
149 true_addr.s_addr = htonl((a1<<24) + (a2<<16) +(a3<<8) + a4);
150 NewFtpPortCommand(pip, link, true_addr, true_port, maxpacketsize, 0);
151 return 1;
152 }
153 else
154 return 0;
155}
129
156
130 if (state == 11)
131 {
132 true_port = htons((p1<<8) + p2);
133 true_addr.s_addr = htonl((a1<<24) + (a2<<16) +(a3<<8) + a4);
134 NewFtpPortCommand(pip, link, true_addr, true_port, maxpacketsize);
135 }
157static void
158ParseFtpEprtCommand(
159char *sptr,
160int dlen,
161struct ip *pip, /* IP packet to examine/patch */
162struct alias_link *link, /* The link to go through (aliased port) */
163int maxpacketsize /* The maximum size this packet can grow to (including headers) */)
164{
165 struct in_addr true_addr;
166 u_short true_port;
167 char ch, delim;
168 int i, state;
169 u_long a1, a2, a3, a4;
170 u_short pt;
171
172 a1=0; a2=0; a3=0; a4=0; pt=0;
173 delim='|'; /* XXX gcc -Wuninitialized */
174 state=-4;
175 for (i=0; i<dlen; i++)
176 {
177 ch = sptr[i];
178 switch (state)
179 {
180 case -4: if (ch == 'E') state++; else return; break;
181 case -3: if (ch == 'P') state++; else return; break;
182 case -2: if (ch == 'R') state++; else return; break;
183 case -1: if (ch == 'T') state++; else return; break;
184
185 case 0 :
186 if (!isspace(ch)) {delim=ch; state++;} break;
187 case 1 :
188 if (ch=='1') /* IPv4 address */ state++; else return; break;
189 case 2 :
190 if (ch==delim) state++; else return; break;
191 case 3 :
192 if (isdigit(ch)) {a1=ch-'0'; state++;} else return; break;
193 case 4 :
194 if (isdigit(ch)) a1=10*a1+ch-'0';
195 else if (ch=='.') state++;
196 else return;
197 break;
198 case 5 :
199 if (isdigit(ch)) {a2=ch-'0'; state++;} else return; break;
200 case 6 :
201 if (isdigit(ch)) a2=10*a2+ch-'0';
202 else if (ch=='.') state++;
203 else return;
204 break;
205 case 7:
206 if (isdigit(ch)) {a3=ch-'0'; state++;} else return; break;
207 case 8 :
208 if (isdigit(ch)) a3=10*a3+ch-'0';
209 else if (ch=='.') state++;
210 else return;
211 break;
212 case 9 :
213 if (isdigit(ch)) {a4=ch-'0'; state++;} else return; break;
214 case 10:
215 if (isdigit(ch)) a4=10*a4+ch-'0';
216 else if (ch==delim) state++;
217 else return;
218 break;
219 case 11:
220 if (isdigit(ch)) {pt=ch-'0'; state++;} else return; break;
221 case 12:
222 if (isdigit(ch)) pt=10*pt+ch-'0';
223 else if (ch==delim) state++;
224 else return;
225 break;
226 }
136 }
227 }
228
229 if (state == 13)
230 {
231 true_port = htons(pt);
232 true_addr.s_addr = htonl((a1<<24) + (a2<<16) +(a3<<8) + a4);
233 NewFtpPortCommand(pip, link, true_addr, true_port, maxpacketsize, 1);
234 }
137}
138
139static void
140NewFtpPortCommand(struct ip *pip,
141 struct alias_link *link,
142 struct in_addr true_addr,
143 u_short true_port,
235}
236
237static void
238NewFtpPortCommand(struct ip *pip,
239 struct alias_link *link,
240 struct in_addr true_addr,
241 u_short true_port,
144 int maxpacketsize)
242 int maxpacketsize,
243 int is_eprt)
145{
146 struct alias_link *ftp_link;
147
148/* Establish link to address and port found in PORT command */
149 ftp_link = FindUdpTcpOut(true_addr, GetDestAddress(link),
150 true_port, 0, IPPROTO_TCP);
151
152 if (ftp_link != NULL)

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

174 int a1, a2, a3, a4, p1, p2;
175 struct in_addr alias_address;
176
177/* Decompose alias address into quad format */
178 alias_address = GetAliasAddress(link);
179 ptr = (u_char *) &alias_address.s_addr;
180 a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr;
181
244{
245 struct alias_link *ftp_link;
246
247/* Establish link to address and port found in PORT command */
248 ftp_link = FindUdpTcpOut(true_addr, GetDestAddress(link),
249 true_port, 0, IPPROTO_TCP);
250
251 if (ftp_link != NULL)

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

273 int a1, a2, a3, a4, p1, p2;
274 struct in_addr alias_address;
275
276/* Decompose alias address into quad format */
277 alias_address = GetAliasAddress(link);
278 ptr = (u_char *) &alias_address.s_addr;
279 a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr;
280
281 alias_port = GetAliasPort(ftp_link);
282
283 if (is_eprt) {
284/* Generate EPRT command string */
285 sprintf(stemp, "EPRT |1|%d.%d.%d.%d|%d|\r\n",
286 a1,a2,a3,a4,ntohs(alias_port));
287 } else {
182/* Decompose alias port into pair format */
288/* Decompose alias port into pair format */
183 alias_port = GetAliasPort(ftp_link);
184 ptr = (char *) &alias_port;
185 p1 = *ptr++; p2=*ptr;
289 ptr = (char *) &alias_port;
290 p1 = *ptr++; p2=*ptr;
186
291
187/* Generate command string */
188 sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
189 a1,a2,a3,a4,p1,p2);
292/* Generate PORT command string */
293 sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
294 a1,a2,a3,a4,p1,p2);
295 }
190
191/* Save string length for IP header modification */
192 slen = strlen(stemp);
193
194/* Copy into IP packet */
195 sptr = (char *) pip; sptr += hlen;
196 strncpy(sptr, stemp, maxpacketsize-hlen);
197 }

--- 34 unchanged lines hidden ---
296
297/* Save string length for IP header modification */
298 slen = strlen(stemp);
299
300/* Copy into IP packet */
301 sptr = (char *) pip; sptr += hlen;
302 strncpy(sptr, stemp, maxpacketsize-hlen);
303 }

--- 34 unchanged lines hidden ---