Lines 10-15
Link Here
|
10 |
* |
10 |
* |
11 |
*/ |
11 |
*/ |
12 |
|
12 |
|
|
|
13 |
/* $USAGI$ */ |
14 |
|
15 |
/* |
16 |
* Copyright (C) 1997 and 1998 WIDE Project. |
17 |
* All rights reserved. |
18 |
* |
19 |
* Redistribution and use in source and binary forms, with or without |
20 |
* modification, are permitted provided that the following conditions |
21 |
* are met: |
22 |
* 1. Redistributions of source code must retain the above copyright |
23 |
* notice, this list of conditions and the following disclaimer. |
24 |
* 2. Redistributions in binary form must reproduce the above copyright |
25 |
* notice, this list of conditions and the following disclaimer in the |
26 |
* documentation and/or other materials provided with the distribution. |
27 |
* 3. Neither the name of the project nor the names of its contributors |
28 |
* may be used to endorse or promote products derived from this software |
29 |
* without specific prior written permission. |
30 |
* |
31 |
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
32 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
33 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
34 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
35 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
36 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
37 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
38 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
39 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
40 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
41 |
* SUCH DAMAGE. |
42 |
*/ |
43 |
|
13 |
/* |
44 |
/* |
14 |
* Copyright (c) 1985, 1989 Regents of the University of California. |
45 |
* Copyright (c) 1985, 1989 Regents of the University of California. |
15 |
* All rights reserved. |
46 |
* All rights reserved. |
Lines 75-88
Link Here
|
75 |
#include "ftp_var.h" |
106 |
#include "ftp_var.h" |
76 |
#include "cmds.h" |
107 |
#include "cmds.h" |
77 |
|
108 |
|
|
|
109 |
#ifdef _USAGI |
110 |
#include "version.h" |
111 |
#else |
78 |
#include "../version.h" |
112 |
#include "../version.h" |
|
|
113 |
#endif |
114 |
|
115 |
union sockunion { |
116 |
struct sockinet { |
117 |
u_short si_family; |
118 |
u_short si_port; |
119 |
} su_si; |
120 |
struct sockaddr su_sa; |
121 |
struct sockaddr_in su_sin; |
122 |
#ifdef INET6 |
123 |
struct sockaddr_in6 su_sin6; |
124 |
#endif |
125 |
}; |
126 |
#define su_family su_sa.sa_family |
127 |
#define su_port su_si.si_port |
128 |
|
129 |
#ifdef INET6 |
130 |
#define ex_af2prot(a) (a == AF_INET ? 1 : (a == AF_INET6 ? 2 : 0)) |
131 |
#else |
132 |
#define ex_af2prot(a) (a == AF_INET ? 1 : 0) |
133 |
#endif |
79 |
|
134 |
|
80 |
int data = -1; |
135 |
int data = -1; |
81 |
off_t restart_point = 0; |
136 |
off_t restart_point = 0; |
82 |
|
137 |
|
83 |
static struct sockaddr_in hisctladdr; |
138 |
static union sockunion hisctladdr; |
84 |
static struct sockaddr_in data_addr; |
139 |
static union sockunion data_addr; |
85 |
static struct sockaddr_in myctladdr; |
140 |
static union sockunion myctladdr; |
86 |
static int ptflag = 0; |
141 |
static int ptflag = 0; |
87 |
static sigjmp_buf recvabort; |
142 |
static sigjmp_buf recvabort; |
88 |
static sigjmp_buf sendabort; |
143 |
static sigjmp_buf sendabort; |
Lines 119-197
Link Here
|
119 |
static FILE *dataconn(const char *); |
174 |
static FILE *dataconn(const char *); |
120 |
|
175 |
|
121 |
char * |
176 |
char * |
122 |
hookup(char *host, int port) |
177 |
hookup(const char *host, const char *port) |
123 |
{ |
178 |
{ |
124 |
register struct hostent *hp = 0; |
179 |
int s, tos, error; |
125 |
int s, tos; |
|
|
126 |
socklen_t len; |
180 |
socklen_t len; |
127 |
static char hostnamebuf[256]; |
181 |
static char hostnamebuf[256]; |
128 |
|
182 |
struct addrinfo hints, *res, *res0; |
|
|
183 |
char hbuf[MAXHOSTNAMELEN], pbuf[NI_MAXSERV]; |
184 |
char *cause = "ftp: unknown"; |
185 |
|
186 |
if (port) { |
187 |
strncpy(pbuf, port, sizeof(pbuf) - 1); |
188 |
pbuf[sizeof(pbuf) - 1] = '\0'; |
189 |
} else { |
190 |
sprintf(pbuf, "%d", ntohs(ftp_port)); |
191 |
} |
129 |
memset(&hisctladdr, 0, sizeof(hisctladdr)); |
192 |
memset(&hisctladdr, 0, sizeof(hisctladdr)); |
130 |
if (inet_aton(host, &hisctladdr.sin_addr)) { |
193 |
memset(&hints, 0, sizeof(hints)); |
131 |
hisctladdr.sin_family = AF_INET; |
194 |
hints.ai_flags = AI_CANONNAME; |
132 |
strncpy(hostnamebuf, host, sizeof(hostnamebuf)); |
195 |
hints.ai_socktype = SOCK_STREAM; |
133 |
hostnamebuf[sizeof(hostnamebuf)-1]=0; |
196 |
error = getaddrinfo(host, pbuf, &hints, &res0); |
134 |
} |
197 |
if (error) { |
135 |
else { |
198 |
if (port) { |
136 |
hp = gethostbyname(host); |
199 |
strcpy(hbuf, " "); |
137 |
if (hp == NULL) { |
200 |
} else { |
138 |
fprintf(stderr, "ftp: %s: ", host); |
201 |
hbuf[0] = '\0'; |
139 |
herror((char *)NULL); |
202 |
pbuf[0] = '\0'; |
140 |
code = -1; |
|
|
141 |
return((char *) 0); |
142 |
} |
203 |
} |
143 |
hisctladdr.sin_family = hp->h_addrtype; |
204 |
fprintf(stderr, "ftp: %s%s%s: %s\n", host, hbuf, pbuf, |
144 |
if (hp->h_length > (int)sizeof(hisctladdr.sin_addr)) { |
205 |
gai_strerror(error)); |
145 |
hp->h_length = sizeof(hisctladdr.sin_addr); |
|
|
146 |
} |
147 |
memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], hp->h_length); |
148 |
(void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); |
149 |
hostnamebuf[sizeof(hostnamebuf)-1] = 0; |
150 |
} |
151 |
hostname = hostnamebuf; |
152 |
s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); |
153 |
if (s < 0) { |
154 |
perror("ftp: socket"); |
155 |
code = -1; |
206 |
code = -1; |
156 |
return (0); |
207 |
return (0); |
157 |
} |
208 |
} |
158 |
hisctladdr.sin_port = port; |
209 |
|
159 |
while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { |
210 |
if (res0->ai_canonname) { |
160 |
if (hp && hp->h_addr_list[1]) { |
211 |
struct addrinfo h, *a; |
161 |
int oerrno = errno; |
212 |
memset(&h, 0, sizeof(h)); |
162 |
|
213 |
h.ai_family = PF_UNSPEC; |
163 |
fprintf(stderr, "ftp: connect to address %s: ", |
214 |
h.ai_socktype = SOCK_STREAM; |
164 |
inet_ntoa(hisctladdr.sin_addr)); |
215 |
h.ai_flags = AI_NUMERICHOST; |
165 |
errno = oerrno; |
216 |
if (!getaddrinfo(res0->ai_canonname, NULL, &h, &a)) { |
166 |
perror((char *) 0); |
217 |
strncpy(hostnamebuf, res0->ai_canonname, sizeof(hostnamebuf)); |
167 |
hp->h_addr_list++; |
218 |
freeaddrinfo(a); |
168 |
memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], |
219 |
} else |
169 |
hp->h_length); |
220 |
strncpy(hostnamebuf, host, sizeof(hostnamebuf)); |
170 |
fprintf(stdout, "Trying %s...\n", |
221 |
} |
171 |
inet_ntoa(hisctladdr.sin_addr)); |
222 |
else |
172 |
(void) close(s); |
223 |
strncpy(hostnamebuf, host, sizeof(hostnamebuf)); |
173 |
s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); |
224 |
hostnamebuf[sizeof(hostnamebuf) - 1] = '\0'; |
174 |
if (s < 0) { |
225 |
hostname = hostnamebuf; |
175 |
perror("ftp: socket"); |
226 |
|
176 |
code = -1; |
227 |
s = -1; |
177 |
return (0); |
228 |
for (res = res0; res; res = res->ai_next) { |
178 |
} |
229 |
if (!ex_af2prot(res->ai_family)) { |
|
|
230 |
cause = "ftp: mismatch address family"; |
231 |
errno = EPROTONOSUPPORT; |
232 |
continue; |
233 |
} |
234 |
if ((size_t)res->ai_addrlen > sizeof(hisctladdr)) { |
235 |
cause = "ftp: mismatch struct sockaddr size"; |
236 |
errno = EPROTO; |
237 |
continue; |
238 |
} |
239 |
if (getnameinfo(res->ai_addr, res->ai_addrlen, |
240 |
hbuf, sizeof(hbuf), NULL, 0, |
241 |
NI_NUMERICHOST)) |
242 |
strcpy(hbuf, "???"); |
243 |
if (res0->ai_next) /* if we have multiple possibilities */ |
244 |
fprintf(stdout, "Trying %s...\n", hbuf); |
245 |
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); |
246 |
if (s < 0) { |
247 |
cause = "ftp: socket"; |
248 |
continue; |
249 |
} |
250 |
while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0 |
251 |
&& errno == EINTR) { |
252 |
; |
253 |
} |
254 |
if (error) { |
255 |
/* this "if" clause is to prevent print warning twice */ |
256 |
if (res->ai_next) { |
257 |
fprintf(stderr, |
258 |
"ftp: connect to address %s\n", hbuf); |
259 |
perror(""); |
260 |
} |
261 |
cause = "ftp: connect"; |
262 |
close(s); |
263 |
s = -1; |
179 |
continue; |
264 |
continue; |
180 |
} |
265 |
} |
181 |
perror("ftp: connect"); |
266 |
/* finally we got one */ |
|
|
267 |
break; |
268 |
} |
269 |
if (s < 0) { |
270 |
perror(cause); |
182 |
code = -1; |
271 |
code = -1; |
183 |
goto bad; |
272 |
freeaddrinfo(res0); |
|
|
273 |
return NULL; |
184 |
} |
274 |
} |
185 |
len = sizeof (myctladdr); |
275 |
len = res->ai_addrlen; |
|
|
276 |
memcpy(&hisctladdr, res->ai_addr, len); |
277 |
freeaddrinfo(res0); |
186 |
if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { |
278 |
if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { |
187 |
perror("ftp: getsockname"); |
279 |
perror("ftp: getsockname"); |
188 |
code = -1; |
280 |
code = -1; |
189 |
goto bad; |
281 |
goto bad; |
190 |
} |
282 |
} |
191 |
#ifdef IP_TOS |
283 |
#ifdef IP_TOS |
|
|
284 |
if (hisctladdr.su_family == AF_INET) |
285 |
{ |
192 |
tos = IPTOS_LOWDELAY; |
286 |
tos = IPTOS_LOWDELAY; |
193 |
if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) |
287 |
if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) |
194 |
perror("ftp: setsockopt TOS (ignored)"); |
288 |
perror("ftp: setsockopt TOS (ignored)"); |
|
|
289 |
} |
195 |
#endif |
290 |
#endif |
196 |
cin = fdopen(s, "r"); |
291 |
cin = fdopen(s, "r"); |
197 |
cout = fdopen(s, "w"); |
292 |
cout = fdopen(s, "w"); |
Lines 205-211
Link Here
|
205 |
goto bad; |
300 |
goto bad; |
206 |
} |
301 |
} |
207 |
if (verbose) |
302 |
if (verbose) |
208 |
printf("Connected to %s.\n", hostname); |
303 |
printf("Connected to %s (%s).\n", hostname, hbuf); |
209 |
if (getreply(0) > 2) { /* read startup message from server */ |
304 |
if (getreply(0) > 2) { /* read startup message from server */ |
210 |
if (cin) |
305 |
if (cin) |
211 |
(void) fclose(cin); |
306 |
(void) fclose(cin); |
Lines 442-449
Link Here
|
442 |
} |
537 |
} |
443 |
if (dig < 4 && isdigit(c)) |
538 |
if (dig < 4 && isdigit(c)) |
444 |
code = code * 10 + (c - '0'); |
539 |
code = code * 10 + (c - '0'); |
445 |
if (!pflag && code == 227) |
540 |
if (!pflag && (code == 227 || code == 228)) |
446 |
pflag = 1; |
541 |
pflag = 1; |
|
|
542 |
else if (!pflag && code == 229) |
543 |
pflag = 100; |
447 |
if (dig > 4 && pflag == 1 && isdigit(c)) |
544 |
if (dig > 4 && pflag == 1 && isdigit(c)) |
448 |
pflag = 2; |
545 |
pflag = 2; |
449 |
if (pflag == 2) { |
546 |
if (pflag == 2) { |
Lines 455-460
Link Here
|
455 |
pflag = 3; |
552 |
pflag = 3; |
456 |
} |
553 |
} |
457 |
} |
554 |
} |
|
|
555 |
if (pflag == 100 && c == '(') |
556 |
pflag = 2; |
458 |
if (dig == 4 && c == '-') { |
557 |
if (dig == 4 && c == '-') { |
459 |
if (continuation) |
558 |
if (continuation) |
460 |
code = 0; |
559 |
code = 0; |
Lines 1207-1221
Link Here
|
1207 |
static int |
1306 |
static int |
1208 |
initconn(void) |
1307 |
initconn(void) |
1209 |
{ |
1308 |
{ |
1210 |
register char *p, *a; |
1309 |
u_char *p, *a; |
1211 |
int result, tmpno = 0; |
1310 |
int result, tmpno = 0; |
1212 |
socklen_t len; |
1311 |
socklen_t len; |
1213 |
int on = 1; |
1312 |
int on = 1; |
1214 |
int tos; |
1313 |
int tos, error = 0; |
1215 |
u_long a1,a2,a3,a4,p1,p2; |
1314 |
u_int ad[16], po[2], af, alen, plen; |
1216 |
|
1315 |
char *pasvcmd = NULL; |
|
|
1316 |
char hbuf[MAXHOSTNAMELEN], pbuf[NI_MAXSERV]; |
1317 |
|
1318 |
#ifdef INET6 |
1319 |
if (myctladdr.su_family == AF_INET6 |
1320 |
&& (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr) |
1321 |
|| IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) { |
1322 |
fprintf(stderr, "use of scoped address can be troublesome\n"); |
1323 |
} |
1324 |
#endif |
1217 |
if (passivemode) { |
1325 |
if (passivemode) { |
1218 |
data = socket(AF_INET, SOCK_STREAM, 0); |
1326 |
data_addr = hisctladdr; |
|
|
1327 |
data = socket(data_addr.su_family, SOCK_STREAM, 0); |
1219 |
if (data < 0) { |
1328 |
if (data < 0) { |
1220 |
perror("ftp: socket"); |
1329 |
perror("ftp: socket"); |
1221 |
return(1); |
1330 |
return(1); |
Lines 1224-1254
Link Here
|
1224 |
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, |
1333 |
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, |
1225 |
sizeof (on)) < 0) |
1334 |
sizeof (on)) < 0) |
1226 |
perror("ftp: setsockopt (ignored)"); |
1335 |
perror("ftp: setsockopt (ignored)"); |
1227 |
if (command("PASV") != COMPLETE) { |
1336 |
switch (data_addr.su_family) { |
|
|
1337 |
case AF_INET: |
1338 |
#if 0 |
1339 |
if (try_epsv) { |
1340 |
result = command(pasvcmd = "EPSV 1"); |
1341 |
if (code / 10 == 22 && code != 229) { |
1342 |
fprintf(stderr, |
1343 |
"wrong server: return code must be 229\n"); |
1344 |
result = COMPLETE + 1; |
1345 |
} |
1346 |
} else { |
1347 |
#endif |
1348 |
result = COMPLETE + 1; |
1349 |
|
1350 |
if (result != COMPLETE) { |
1351 |
try_epsv = 0; |
1352 |
result = command(pasvcmd = "PASV"); |
1353 |
} |
1354 |
break; |
1355 |
#ifdef INET6 |
1356 |
case AF_INET6: |
1357 |
if (try_epsv) { |
1358 |
result = command(pasvcmd = "EPSV 2"); |
1359 |
if (code / 10 == 22 && code != 229) { |
1360 |
fprintf(stderr, |
1361 |
"wrong server: return code must be 229\n"); |
1362 |
result = COMPLETE + 1; |
1363 |
} |
1364 |
} else { |
1365 |
result = COMPLETE + 1; |
1366 |
} |
1367 |
if (result != COMPLETE) { |
1368 |
try_epsv = 0; |
1369 |
result = command(pasvcmd = "LPSV"); |
1370 |
} |
1371 |
break; |
1372 |
#endif |
1373 |
default: |
1374 |
result = COMPLETE + 1; |
1375 |
break; |
1376 |
} |
1377 |
if (result != COMPLETE) { |
1228 |
printf("Passive mode refused.\n"); |
1378 |
printf("Passive mode refused.\n"); |
1229 |
return(1); |
1379 |
goto bad; |
1230 |
} |
1380 |
} |
1231 |
|
1381 |
|
|
|
1382 |
#define pack2(var) \ |
1383 |
(((var[0] & 0xff) << 8) | ((var[1] & 0xff) << 0)) |
1384 |
#define pack4(var) \ |
1385 |
((((var)[0] & 0xff) << 24) | (((var)[1] & 0xff) << 16) | \ |
1386 |
(((var)[2] & 0xff) << 8) | (((var)[3] & 0xff) << 0)) |
1387 |
|
1232 |
/* |
1388 |
/* |
1233 |
* What we've got at this point is a string of comma separated |
1389 |
* What we've got at this point is a string of comma separated |
1234 |
* one-byte unsigned integer values, separated by commas. |
1390 |
* one-byte unsigned integer values, separated by commas. |
1235 |
* The first four are the an IP address. The fifth is the MSB |
|
|
1236 |
* of the port number, the sixth is the LSB. From that we'll |
1237 |
* prepare a sockaddr_in. |
1238 |
*/ |
1391 |
*/ |
1239 |
|
1392 |
error = 0; |
1240 |
if (sscanf(pasv,"%ld,%ld,%ld,%ld,%ld,%ld", |
1393 |
if (strcmp(pasvcmd, "PASV") == 0) { |
1241 |
&a1,&a2,&a3,&a4,&p1,&p2) |
1394 |
if (data_addr.su_family != AF_INET) { |
1242 |
!= 6) |
1395 |
error = 2; |
1243 |
{ |
1396 |
goto psv_done; |
1244 |
printf("Passive mode address scan failure. Shouldn't happen!\n"); |
1397 |
} |
1245 |
return(1); |
1398 |
if (code / 10 == 22 && code != 227) { |
|
|
1399 |
error = 227; |
1400 |
goto psv_done; |
1401 |
} |
1402 |
if (sscanf(pasv, "%u,%u,%u,%u,%u,%u", |
1403 |
&ad[0], &ad[1], &ad[2], &ad[3], |
1404 |
&po[0], &po[1]) != 6) { |
1405 |
error = 1; |
1406 |
goto psv_done; |
1407 |
} |
1408 |
data_addr.su_sin.sin_addr.s_addr = htonl(pack4(ad)); |
1409 |
data_addr.su_port = htons(pack2(po)); |
1410 |
} else |
1411 |
if (strcmp(pasvcmd, "LPSV") == 0) { |
1412 |
if (code / 10 == 22 && code != 228) { |
1413 |
error = 228; |
1414 |
goto psv_done; |
1415 |
} |
1416 |
switch (data_addr.su_family) { |
1417 |
case AF_INET: |
1418 |
if (sscanf(pasv, "%u,%u,%u,%u,%u,%u,%u,%u,%u", |
1419 |
&af, &alen, |
1420 |
&ad[0], &ad[1], &ad[2], &ad[3], |
1421 |
&plen, &po[0], &po[1]) != 9) { |
1422 |
error = 1; |
1423 |
goto psv_done; |
1424 |
} |
1425 |
if (af != 4 || alen != 4 || plen != 2) { |
1426 |
error = 2; |
1427 |
goto psv_done; |
1428 |
} |
1429 |
data_addr.su_sin.sin_addr.s_addr = |
1430 |
htonl(pack4(ad)); |
1431 |
data_addr.su_port = htons(pack2(po)); |
1432 |
break; |
1433 |
#ifdef INET6 |
1434 |
case AF_INET6: |
1435 |
if (sscanf(pasv, |
1436 |
"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", |
1437 |
&af, &alen, |
1438 |
&ad[0], &ad[1], &ad[2], &ad[3], |
1439 |
&ad[4], &ad[5], &ad[6], &ad[7], |
1440 |
&ad[8], &ad[9], &ad[10], &ad[11], |
1441 |
&ad[12], &ad[13], &ad[14], &ad[15], |
1442 |
&plen, &po[0], &po[1]) != 21) { |
1443 |
error = 1; |
1444 |
goto psv_done; |
1445 |
} |
1446 |
if (af != 6 || alen != 16 || plen != 2) { |
1447 |
error = 2; |
1448 |
goto psv_done; |
1449 |
} |
1450 |
data_addr.su_sin6.sin6_addr.s6_addr32[0] = |
1451 |
htonl(pack4(ad)); |
1452 |
data_addr.su_sin6.sin6_addr.s6_addr32[1] = |
1453 |
htonl(pack4(ad+4)); |
1454 |
data_addr.su_sin6.sin6_addr.s6_addr32[2] = |
1455 |
htonl(pack4(ad+8)); |
1456 |
data_addr.su_sin6.sin6_addr.s6_addr32[3] = |
1457 |
htonl(pack4(ad+12)); |
1458 |
data_addr.su_port = htons(pack2(po)); |
1459 |
break; |
1460 |
#endif |
1461 |
default: |
1462 |
error = 1; |
1463 |
} |
1464 |
} else if (strncmp(pasvcmd, "EPSV", 4) == 0) { |
1465 |
char delim[4]; |
1466 |
u_int epsvpo; |
1467 |
|
1468 |
if (code / 10 == 22 && code != 229) { |
1469 |
error = 229; |
1470 |
goto psv_done; |
1471 |
} |
1472 |
if (sscanf(pasv, "%c%c%c%u%c", &delim[0], &delim[1], |
1473 |
&delim[2], &epsvpo, &delim[3]) != 5) { |
1474 |
error = 1; |
1475 |
goto psv_done; |
1476 |
} |
1477 |
if (delim[0] != delim[1] || delim[0] != delim[2] |
1478 |
|| delim[0] != delim[3]) { |
1479 |
error = 1; |
1480 |
goto psv_done; |
1481 |
} |
1482 |
data_addr.su_port = htons(epsvpo); |
1483 |
} else { |
1484 |
error = 1; |
1485 |
} |
1486 |
psv_done: |
1487 |
switch (error) { |
1488 |
case 0: |
1489 |
break; |
1490 |
case 1: |
1491 |
fprintf(stderr, |
1492 |
"Passive mode address scan failure. Shouldn't happen!\n"); |
1493 |
goto bad; |
1494 |
case 2: |
1495 |
fprintf(stderr, |
1496 |
"Passive mode AF mismatch. Shouldn't happen!\n"); |
1497 |
goto bad; |
1498 |
case 227: |
1499 |
case 228: |
1500 |
case 229: |
1501 |
fprintf(stderr, |
1502 |
"wrong server: return code must be %d\n", error); |
1503 |
goto bad; |
1504 |
default: |
1505 |
fprintf(stderr, "Bug\n"); |
1246 |
} |
1506 |
} |
1247 |
|
|
|
1248 |
data_addr.sin_family = AF_INET; |
1249 |
data_addr.sin_addr.s_addr = htonl((a1 << 24) | (a2 << 16) | |
1250 |
(a3 << 8) | a4); |
1251 |
data_addr.sin_port = htons((p1 << 8) | p2); |
1252 |
|
1507 |
|
1253 |
if (connect(data, (struct sockaddr *) &data_addr, |
1508 |
if (connect(data, (struct sockaddr *) &data_addr, |
1254 |
sizeof(data_addr))<0) { |
1509 |
sizeof(data_addr))<0) { |
Lines 1256-1275
Link Here
|
1256 |
return(1); |
1511 |
return(1); |
1257 |
} |
1512 |
} |
1258 |
#ifdef IP_TOS |
1513 |
#ifdef IP_TOS |
|
|
1514 |
if (data_addr.su_family == AF_INET) |
1515 |
{ |
1259 |
tos = IPTOS_THROUGHPUT; |
1516 |
tos = IPTOS_THROUGHPUT; |
1260 |
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&tos, |
1517 |
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&tos, |
1261 |
sizeof(tos)) < 0) |
1518 |
sizeof(tos)) < 0) |
1262 |
perror("ftp: setsockopt TOS (ignored)"); |
1519 |
perror("ftp: setsockopt TOS (ignored)"); |
|
|
1520 |
} |
1263 |
#endif |
1521 |
#endif |
1264 |
return(0); |
1522 |
return(0); |
1265 |
} |
1523 |
} |
1266 |
noport: |
1524 |
noport: |
1267 |
data_addr = myctladdr; |
1525 |
data_addr = myctladdr; |
1268 |
if (sendport) |
1526 |
if (sendport) |
1269 |
data_addr.sin_port = 0; /* let system pick one */ |
1527 |
data_addr.su_port = 0; /* let system pick one */ |
1270 |
if (data != -1) |
1528 |
if (data != -1) |
1271 |
(void) close(data); |
1529 |
(void) close(data); |
1272 |
data = socket(AF_INET, SOCK_STREAM, 0); |
1530 |
data = socket(data_addr.su_family, SOCK_STREAM, 0); |
1273 |
if (data < 0) { |
1531 |
if (data < 0) { |
1274 |
perror("ftp: socket"); |
1532 |
perror("ftp: socket"); |
1275 |
if (tmpno) |
1533 |
if (tmpno) |
Lines 1296-1308
Link Here
|
1296 |
if (listen(data, 1) < 0) |
1554 |
if (listen(data, 1) < 0) |
1297 |
perror("ftp: listen"); |
1555 |
perror("ftp: listen"); |
1298 |
if (sendport) { |
1556 |
if (sendport) { |
1299 |
a = (char *)&data_addr.sin_addr; |
1557 |
af = ex_af2prot(data_addr.su_family); |
1300 |
p = (char *)&data_addr.sin_port; |
1558 |
if (try_eprt && af > 1) { /* only IPv6 */ |
1301 |
#define UC(b) (((int)b)&0xff) |
1559 |
if (getnameinfo((struct sockaddr *)&data_addr, len, |
1302 |
result = |
1560 |
hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), |
1303 |
command("PORT %d,%d,%d,%d,%d,%d", |
1561 |
NI_NUMERICHOST | NI_NUMERICSERV) == 0) { |
1304 |
UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), |
1562 |
result = command("EPRT |%d|%s|%s|", |
1305 |
UC(p[0]), UC(p[1])); |
1563 |
af, hbuf, pbuf); |
|
|
1564 |
if (result != COMPLETE) { |
1565 |
try_eprt = 0; |
1566 |
} |
1567 |
} else { |
1568 |
result = ERROR; |
1569 |
} |
1570 |
} else { |
1571 |
result = COMPLETE + 1; |
1572 |
} |
1573 |
if (result == COMPLETE) |
1574 |
goto prt_done; |
1575 |
|
1576 |
p = (u_char *)&data_addr.su_port; |
1577 |
switch (data_addr.su_family) { |
1578 |
case AF_INET: |
1579 |
a = (u_char *)&data_addr.su_sin.sin_addr; |
1580 |
result = command("PORT %u,%u,%u,%u,%u,%u", |
1581 |
a[0], a[1], a[2], a[3], p[0], p[1]); |
1582 |
break; |
1583 |
#ifdef INET6 |
1584 |
case AF_INET6: |
1585 |
a = (u_char *)&data_addr.su_sin6.sin6_addr; |
1586 |
result = command( |
1587 |
"LPRT 6,16,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,2,%d,%d", |
1588 |
a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], |
1589 |
a[8], a[9],a[10],a[11],a[12],a[13],a[14],a[15], |
1590 |
p[0], p[1]); |
1591 |
break; |
1592 |
#endif |
1593 |
default: |
1594 |
result = COMPLETE + 1; /* xxx */ |
1595 |
} |
1596 |
|
1597 |
prt_done: |
1306 |
if (result == ERROR && sendport == -1) { |
1598 |
if (result == ERROR && sendport == -1) { |
1307 |
sendport = 0; |
1599 |
sendport = 0; |
1308 |
tmpno = 1; |
1600 |
tmpno = 1; |
Lines 1313-1321
Link Here
|
1313 |
if (tmpno) |
1605 |
if (tmpno) |
1314 |
sendport = 1; |
1606 |
sendport = 1; |
1315 |
#ifdef IP_TOS |
1607 |
#ifdef IP_TOS |
|
|
1608 |
if (data_addr.su_family == AF_INET) |
1609 |
{ |
1316 |
on = IPTOS_THROUGHPUT; |
1610 |
on = IPTOS_THROUGHPUT; |
1317 |
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) |
1611 |
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) |
1318 |
perror("ftp: setsockopt TOS (ignored)"); |
1612 |
perror("ftp: setsockopt TOS (ignored)"); |
|
|
1613 |
} |
1319 |
#endif |
1614 |
#endif |
1320 |
return (0); |
1615 |
return (0); |
1321 |
bad: |
1616 |
bad: |
Lines 1328-1334
Link Here
|
1328 |
static FILE * |
1623 |
static FILE * |
1329 |
dataconn(const char *lmode) |
1624 |
dataconn(const char *lmode) |
1330 |
{ |
1625 |
{ |
1331 |
struct sockaddr_in from; |
1626 |
union sockunion from; |
1332 |
int s, tos; |
1627 |
int s, tos; |
1333 |
socklen_t fromlen = sizeof(from); |
1628 |
socklen_t fromlen = sizeof(from); |
1334 |
int ret; |
1629 |
int ret; |
Lines 1345-1353
Link Here
|
1345 |
(void) close(data); |
1640 |
(void) close(data); |
1346 |
data = s; |
1641 |
data = s; |
1347 |
#ifdef IP_TOS |
1642 |
#ifdef IP_TOS |
|
|
1643 |
if (from.su_family == AF_INET) |
1644 |
{ |
1348 |
tos = IPTOS_THROUGHPUT; |
1645 |
tos = IPTOS_THROUGHPUT; |
1349 |
if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) |
1646 |
if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) |
1350 |
perror("ftp: setsockopt TOS (ignored)"); |
1647 |
perror("ftp: setsockopt TOS (ignored)"); |
|
|
1648 |
} |
1351 |
#endif |
1649 |
#endif |
1352 |
|
1650 |
|
1353 |
#ifdef USE_SSL |
1651 |
#ifdef USE_SSL |
Lines 1470-1477
Link Here
|
1470 |
static struct comvars { |
1768 |
static struct comvars { |
1471 |
int connect; |
1769 |
int connect; |
1472 |
char name[MAXHOSTNAMELEN]; |
1770 |
char name[MAXHOSTNAMELEN]; |
1473 |
struct sockaddr_in mctl; |
1771 |
union sockunion mctl; |
1474 |
struct sockaddr_in hctl; |
1772 |
union sockunion hctl; |
1475 |
FILE *in; |
1773 |
FILE *in; |
1476 |
FILE *out; |
1774 |
FILE *out; |
1477 |
int tpe; |
1775 |
int tpe; |
Lines 1509-1515
Link Here
|
1509 |
connected = op->connect; |
1807 |
connected = op->connect; |
1510 |
if (hostname) { |
1808 |
if (hostname) { |
1511 |
(void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); |
1809 |
(void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); |
1512 |
ip->name[strlen(ip->name)] = '\0'; |
1810 |
ip->name[sizeof(ip->name) - 1] = '\0'; |
1513 |
} |
1811 |
} |
1514 |
else { |
1812 |
else { |
1515 |
ip->name[0] = 0; |
1813 |
ip->name[0] = 0; |
Lines 1538-1555
Link Here
|
1538 |
ip->ntflg = ntflag; |
1836 |
ip->ntflg = ntflag; |
1539 |
ntflag = op->ntflg; |
1837 |
ntflag = op->ntflg; |
1540 |
(void) strncpy(ip->nti, ntin, 16); |
1838 |
(void) strncpy(ip->nti, ntin, 16); |
1541 |
(ip->nti)[strlen(ip->nti)] = '\0'; |
1839 |
(ip->nti)[16] = '\0'; /* shouldn't use strlen */ |
1542 |
(void) strcpy(ntin, op->nti); |
1840 |
(void) strcpy(ntin, op->nti); |
1543 |
(void) strncpy(ip->nto, ntout, 16); |
1841 |
(void) strncpy(ip->nto, ntout, 16); |
1544 |
(ip->nto)[strlen(ip->nto)] = '\0'; |
1842 |
(ip->nto)[16] = '\0'; |
1545 |
(void) strcpy(ntout, op->nto); |
1843 |
(void) strcpy(ntout, op->nto); |
1546 |
ip->mapflg = mapflag; |
1844 |
ip->mapflg = mapflag; |
1547 |
mapflag = op->mapflg; |
1845 |
mapflag = op->mapflg; |
1548 |
(void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); |
1846 |
(void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); |
1549 |
(ip->mi)[strlen(ip->mi)] = '\0'; |
1847 |
(ip->mi)[MAXPATHLEN - 1] = '\0'; |
1550 |
(void) strcpy(mapin, op->mi); |
1848 |
(void) strcpy(mapin, op->mi); |
1551 |
(void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); |
1849 |
(void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); |
1552 |
(ip->mo)[strlen(ip->mo)] = '\0'; |
1850 |
(ip->mo)[MAXPATHLEN - 1] = '\0'; |
1553 |
(void) strcpy(mapout, op->mo); |
1851 |
(void) strcpy(mapout, op->mo); |
1554 |
(void) signal(SIGINT, oldintr); |
1852 |
(void) signal(SIGINT, oldintr); |
1555 |
if (abrtflag) { |
1853 |
if (abrtflag) { |