|
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) { |