1 /* $NetBSD: ftp.c,v 1.24 2021/08/27 01:38:49 lukem Exp $ */
2 /* from NetBSD: ftp.c,v 1.174 2021/08/26 06:23:24 lukem Exp */
3
4 /*-
5 * Copyright (c) 1996-2021 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Luke Mewburn.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (c) 1985, 1989, 1993, 1994
35 * The Regents of the University of California. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62 /*
63 * Copyright (C) 1997 and 1998 WIDE Project.
64 * All rights reserved.
65 *
66 * Redistribution and use in source and binary forms, with or without
67 * modification, are permitted provided that the following conditions
68 * are met:
69 * 1. Redistributions of source code must retain the above copyright
70 * notice, this list of conditions and the following disclaimer.
71 * 2. Redistributions in binary form must reproduce the above copyright
72 * notice, this list of conditions and the following disclaimer in the
73 * documentation and/or other materials provided with the distribution.
74 * 3. Neither the name of the project nor the names of its contributors
75 * may be used to endorse or promote products derived from this software
76 * without specific prior written permission.
77 *
78 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
81 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
88 * SUCH DAMAGE.
89 */
90
91 #include "tnftp.h"
92 #include <arpa/telnet.h>
93
94 #if 0 /* tnftp */
95
96 #include <sys/cdefs.h>
97 #ifndef lint
98 #if 0
99 static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94";
100 #else
101 __RCSID(" NetBSD: ftp.c,v 1.174 2021/08/26 06:23:24 lukem Exp ");
102 #endif
103 #endif /* not lint */
104
105 #include <sys/types.h>
106 #include <sys/stat.h>
107 #include <sys/socket.h>
108 #include <sys/time.h>
109
110 #include <netinet/in.h>
111 #include <netinet/in_systm.h>
112 #include <netinet/ip.h>
113 #include <arpa/inet.h>
114 #include <arpa/ftp.h>
115 #include <arpa/telnet.h>
116
117 #include <assert.h>
118 #include <ctype.h>
119 #include <err.h>
120 #include <errno.h>
121 #include <fcntl.h>
122 #include <netdb.h>
123 #include <stdio.h>
124 #include <stdlib.h>
125 #include <string.h>
126 #include <time.h>
127 #include <unistd.h>
128 #include <stdarg.h>
129
130 #endif /* tnftp */
131
132 #include "ftp_var.h"
133
134 volatile sig_atomic_t abrtflag;
135 volatile sig_atomic_t timeoutflag;
136
137 sigjmp_buf ptabort;
138 int ptabflg;
139 int ptflag = 0;
140 char pasv[BUFSIZ]; /* passive port for proxy data connection */
141
142 static int empty(FILE *, FILE *, int);
143 __dead static void abort_squared(int);
144
145 struct sockinet {
146 union sockunion {
147 struct sockaddr_in su_sin;
148 #ifdef INET6
149 struct sockaddr_in6 su_sin6;
150 #endif
151 } si_su;
152 #if !defined(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN)
153 int si_len;
154 #endif
155 };
156
157 #if !defined(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN)
158 # define su_len si_len
159 #else
160 # define su_len si_su.su_sin.sin_len
161 #endif
162 #define su_family si_su.su_sin.sin_family
163 #define su_port si_su.su_sin.sin_port
164
165 struct sockinet myctladdr, hisctladdr, data_addr;
166
167 char *
hookup(const char * host,const char * port)168 hookup(const char *host, const char *port)
169 {
170 int s = -1, error;
171 struct addrinfo hints, *res, *res0;
172 static char hostnamebuf[MAXHOSTNAMELEN];
173 socklen_t len;
174 int on = 1;
175
176 memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
177 memset((char *)&myctladdr, 0, sizeof (myctladdr));
178 memset(&hints, 0, sizeof(hints));
179 hints.ai_flags = AI_CANONNAME;
180 hints.ai_family = family;
181 hints.ai_socktype = SOCK_STREAM;
182 hints.ai_protocol = 0;
183 error = getaddrinfo(host, port, &hints, &res0);
184 if (error) {
185 warnx("Can't lookup `%s:%s': %s", host, port,
186 (error == EAI_SYSTEM) ? strerror(errno)
187 : gai_strerror(error));
188 code = -1;
189 return (0);
190 }
191
192 if (res0->ai_canonname)
193 (void)strlcpy(hostnamebuf, res0->ai_canonname,
194 sizeof(hostnamebuf));
195 else
196 (void)strlcpy(hostnamebuf, host, sizeof(hostnamebuf));
197 hostname = hostnamebuf;
198
199 for (res = res0; res; res = res->ai_next) {
200 char hname[NI_MAXHOST], sname[NI_MAXSERV];
201
202 ai_unmapped(res);
203 if (getnameinfo(res->ai_addr, res->ai_addrlen,
204 hname, sizeof(hname), sname, sizeof(sname),
205 NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
206 strlcpy(hname, "?", sizeof(hname));
207 strlcpy(sname, "?", sizeof(sname));
208 }
209 if (verbose && res0->ai_next) {
210 /* if we have multiple possibilities */
211 #ifdef INET6
212 if(res->ai_family == AF_INET6) {
213 fprintf(ttyout, "Trying [%s]:%s ...\n", hname,
214 sname);
215 } else {
216 #endif
217 fprintf(ttyout, "Trying %s:%s ...\n", hname,
218 sname);
219 #ifdef INET6
220 }
221 #endif
222 }
223 s = socket(res->ai_family, SOCK_STREAM, res->ai_protocol);
224 if (s < 0) {
225 warn("Can't create socket for connection to `%s:%s'",
226 hname, sname);
227 continue;
228 }
229 if (ftp_connect(s, res->ai_addr, res->ai_addrlen,
230 verbose || !res->ai_next) < 0) {
231 close(s);
232 s = -1;
233 continue;
234 }
235
236 /* finally we got one */
237 break;
238 }
239 if (s < 0) {
240 warnx("Can't connect to `%s:%s'", host, port);
241 code = -1;
242 freeaddrinfo(res0);
243 return 0;
244 }
245 memcpy(&hisctladdr.si_su, res->ai_addr, res->ai_addrlen);
246 hisctladdr.su_len = res->ai_addrlen;
247 freeaddrinfo(res0);
248 res0 = res = NULL;
249
250 len = hisctladdr.su_len;
251 if (getsockname(s, (struct sockaddr *)&myctladdr.si_su, &len) == -1) {
252 warn("Can't determine my address of connection to `%s:%s'",
253 host, port);
254 code = -1;
255 goto bad;
256 }
257 myctladdr.su_len = len;
258
259 #ifdef IPTOS_LOWDELAY
260 if (hisctladdr.su_family == AF_INET) {
261 int tos = IPTOS_LOWDELAY;
262 if (setsockopt(s, IPPROTO_IP, IP_TOS,
263 (void *)&tos, sizeof(tos)) == -1) {
264 DWARN("setsockopt %s (ignored)",
265 "IPTOS_LOWDELAY");
266 }
267 }
268 #endif
269 cin = fdopen(s, "r");
270 cout = fdopen(s, "w");
271 if (cin == NULL || cout == NULL) {
272 warnx("Can't fdopen socket");
273 if (cin)
274 (void)fclose(cin);
275 if (cout)
276 (void)fclose(cout);
277 code = -1;
278 goto bad;
279 }
280 if (verbose)
281 fprintf(ttyout, "Connected to %s.\n", hostname);
282 if (getreply(0) > 2) { /* read startup message from server */
283 if (cin)
284 (void)fclose(cin);
285 if (cout)
286 (void)fclose(cout);
287 code = -1;
288 goto bad;
289 }
290
291 if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,
292 (void *)&on, sizeof(on)) == -1) {
293 DWARN("setsockopt %s (ignored)", "SO_KEEPALIVE");
294 }
295
296 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE,
297 (void *)&on, sizeof(on)) == -1) {
298 DWARN("setsockopt %s (ignored)", "SO_OOBINLINE");
299 }
300
301 return (hostname);
302 bad:
303 (void)close(s);
304 return (NULL);
305 }
306
307 void
cmdabort(int notused)308 cmdabort(int notused)
309 {
310 int oerrno = errno;
311
312 sigint_raised = 1;
313 alarmtimer(0);
314 if (fromatty)
315 write(fileno(ttyout), "\n", 1);
316 abrtflag++;
317 if (ptflag)
318 siglongjmp(ptabort, 1);
319 errno = oerrno;
320 }
321
322 void
cmdtimeout(int notused)323 cmdtimeout(int notused)
324 {
325 int oerrno = errno;
326
327 alarmtimer(0);
328 if (fromatty)
329 write(fileno(ttyout), "\n", 1);
330 timeoutflag++;
331 if (ptflag)
332 siglongjmp(ptabort, 1);
333 errno = oerrno;
334 }
335
336 static int
issighandler(sigfunc func)337 issighandler(sigfunc func)
338 {
339 return (func != SIG_IGN &&
340 func != SIG_DFL &&
341 #ifdef SIG_HOLD
342 func != SIG_HOLD &&
343 #endif
344 func != SIG_ERR);
345 }
346
347 /*VARARGS*/
348 int
command(const char * fmt,...)349 command(const char *fmt, ...)
350 {
351 va_list ap;
352 int r;
353 sigfunc oldsigint;
354
355 #ifndef NO_DEBUG
356 if (ftp_debug) {
357 fputs("---> ", ttyout);
358 va_start(ap, fmt);
359 if (strncmp("PASS ", fmt, 5) == 0)
360 fputs("PASS XXXX", ttyout);
361 else if (strncmp("ACCT ", fmt, 5) == 0)
362 fputs("ACCT XXXX", ttyout);
363 else
364 vfprintf(ttyout, fmt, ap);
365 va_end(ap);
366 putc('\n', ttyout);
367 }
368 #endif
369 if (cout == NULL) {
370 warnx("No control connection for command");
371 code = -1;
372 return (0);
373 }
374
375 abrtflag = 0;
376
377 oldsigint = xsignal(SIGINT, cmdabort);
378
379 va_start(ap, fmt);
380 vfprintf(cout, fmt, ap);
381 va_end(ap);
382 fputs("\r\n", cout);
383 (void)fflush(cout);
384 cpend = 1;
385 r = getreply(!strcmp(fmt, "QUIT"));
386 if (abrtflag && issighandler(oldsigint)) {
387 (*oldsigint)(SIGINT);
388 }
389 (void)xsignal(SIGINT, oldsigint);
390 return (r);
391 }
392
393 static const char *m421[] = {
394 "remote server timed out. Connection closed",
395 "user interrupt. Connection closed",
396 "remote server has closed connection",
397 };
398
399 int
getreply(int expecteof)400 getreply(int expecteof)
401 {
402 char current_line[BUFSIZ]; /* last line of previous reply */
403 int c, n, lineno;
404 int dig;
405 int originalcode = 0, continuation = 0;
406 sigfunc oldsigint, oldsigalrm;
407 int pflag = 0;
408 char *cp, *pt = pasv;
409
410 abrtflag = 0;
411 timeoutflag = 0;
412
413 oldsigint = xsignal(SIGINT, cmdabort);
414 oldsigalrm = xsignal(SIGALRM, cmdtimeout);
415
416 for (lineno = 0 ;; lineno++) {
417 dig = n = code = 0;
418 cp = current_line;
419 while (alarmtimer(quit_time ? quit_time : 60),
420 ((c = getc(cin)) != '\n')) {
421 if (c == IAC) { /* handle telnet commands */
422 switch (c = getc(cin)) {
423 case WILL:
424 case WONT:
425 c = getc(cin);
426 fprintf(cout, "%c%c%c", IAC, DONT, c);
427 (void)fflush(cout);
428 break;
429 case DO:
430 case DONT:
431 c = getc(cin);
432 fprintf(cout, "%c%c%c", IAC, WONT, c);
433 (void)fflush(cout);
434 break;
435 default:
436 break;
437 }
438 continue;
439 }
440 dig++;
441 if (c == EOF) {
442 /*
443 * these will get trashed by pswitch()
444 * in lostpeer()
445 */
446 int reply_timeoutflag = timeoutflag;
447 int reply_abrtflag = abrtflag;
448
449 alarmtimer(0);
450 if (expecteof && feof(cin)) {
451 (void)xsignal(SIGINT, oldsigint);
452 (void)xsignal(SIGALRM, oldsigalrm);
453 code = 221;
454 return (0);
455 }
456 cpend = 0;
457 lostpeer(0);
458 if (verbose) {
459 size_t midx;
460 if (reply_timeoutflag)
461 midx = 0;
462 else if (reply_abrtflag)
463 midx = 1;
464 else
465 midx = 2;
466 (void)fprintf(ttyout,
467 "421 Service not available, %s.\n", m421[midx]);
468 (void)fflush(ttyout);
469 }
470 code = 421;
471 (void)xsignal(SIGINT, oldsigint);
472 (void)xsignal(SIGALRM, oldsigalrm);
473 return (4);
474 }
475 if (c != '\r' && (verbose > 0 ||
476 ((verbose > -1 && n == '5' && dig > 4) &&
477 (((!n && c < '5') || (n && n < '5'))
478 || !retry_connect)))) {
479 if (proxflag &&
480 (dig == 1 || (dig == 5 && verbose == 0)))
481 fprintf(ttyout, "%s:", hostname);
482 (void)putc(c, ttyout);
483 }
484 if (dig < 4 && isdigit(c))
485 code = code * 10 + (c - '0');
486 if (!pflag && (code == 227 || code == 228))
487 pflag = 1;
488 else if (!pflag && code == 229)
489 pflag = 100;
490 if (dig > 4 && pflag == 1 && isdigit(c))
491 pflag = 2;
492 if (pflag == 2) {
493 if (c != '\r' && c != ')') {
494 if (pt < &pasv[sizeof(pasv) - 1])
495 *pt++ = c;
496 } else {
497 *pt = '\0';
498 pflag = 3;
499 }
500 }
501 if (pflag == 100 && c == '(')
502 pflag = 2;
503 if (dig == 4 && c == '-') {
504 if (continuation)
505 code = 0;
506 continuation++;
507 }
508 if (n == 0)
509 n = c;
510 if (cp < ¤t_line[sizeof(current_line) - 1])
511 *cp++ = c;
512 }
513 if (verbose > 0 || ((verbose > -1 && n == '5') &&
514 (n < '5' || !retry_connect))) {
515 (void)putc(c, ttyout);
516 (void)fflush(ttyout);
517 }
518 if (cp[-1] == '\r')
519 cp[-1] = '\0';
520 *cp = '\0';
521 if (lineno == 0)
522 (void)strlcpy(reply_string, current_line,
523 sizeof(reply_string));
524 if (lineno > 0 && code == 0 && reply_callback != NULL)
525 (*reply_callback)(current_line);
526 if (continuation && code != originalcode) {
527 if (originalcode == 0)
528 originalcode = code;
529 continue;
530 }
531 if (n != '1')
532 cpend = 0;
533 alarmtimer(0);
534 (void)xsignal(SIGINT, oldsigint);
535 (void)xsignal(SIGALRM, oldsigalrm);
536 if (code == 421 || originalcode == 421)
537 lostpeer(0);
538 if (abrtflag && oldsigint != cmdabort &&
539 issighandler(oldsigint)) {
540 (*oldsigint)(SIGINT);
541 }
542 if (timeoutflag && oldsigalrm != cmdtimeout &&
543 issighandler(oldsigalrm)) {
544 (*oldsigalrm)(SIGINT);
545 }
546 return (n - '0');
547 }
548 }
549
550 static int
empty(FILE * ecin,FILE * din,int sec)551 empty(FILE *ecin, FILE *din, int sec)
552 {
553 int nr, nfd;
554 struct pollfd pfd[2];
555
556 nfd = 0;
557 if (ecin) {
558 pfd[nfd].fd = fileno(ecin);
559 pfd[nfd++].events = POLLIN;
560 }
561
562 if (din) {
563 pfd[nfd].fd = fileno(din);
564 pfd[nfd++].events = POLLIN;
565 }
566
567 if ((nr = ftp_poll(pfd, nfd, sec * 1000)) <= 0)
568 return nr;
569
570 nr = 0;
571 nfd = 0;
572 if (ecin)
573 nr |= (pfd[nfd++].revents & POLLIN) ? 1 : 0;
574 if (din)
575 nr |= (pfd[nfd++].revents & POLLIN) ? 2 : 0;
576 return nr;
577 }
578
579 sigjmp_buf xferabort;
580
581 __dead static void
abortxfer(int notused)582 abortxfer(int notused)
583 {
584 char msgbuf[100];
585 size_t len;
586
587 sigint_raised = 1;
588 alarmtimer(0);
589 mflag = 0;
590 abrtflag = 0;
591 switch (direction[0]) {
592 case 'r':
593 strlcpy(msgbuf, "\nreceive", sizeof(msgbuf));
594 break;
595 case 's':
596 strlcpy(msgbuf, "\nsend", sizeof(msgbuf));
597 break;
598 default:
599 errx(1, "abortxfer: unknown direction `%s'", direction);
600 }
601 len = strlcat(msgbuf, " aborted. Waiting for remote to finish abort.\n",
602 sizeof(msgbuf));
603 write(fileno(ttyout), msgbuf, len);
604 siglongjmp(xferabort, 1);
605 }
606
607 /*
608 * Read data from infd & write to outfd, using buf/bufsize as the temporary
609 * buffer, dealing with short reads or writes.
610 * If rate_limit != 0, rate-limit the transfer.
611 * If hash_interval != 0, fputc('c', ttyout) every hash_interval bytes.
612 * Updates global variables: bytes.
613 * Returns 0 if ok, 1 if there was a read error, 2 if there was a write error.
614 * In the case of error, errno contains the appropriate error code.
615 */
616 static int
copy_bytes(int infd,int outfd,char * buf,size_t bufsize,int rate_limit,int hash_interval)617 copy_bytes(int infd, int outfd, char *buf, size_t bufsize,
618 int rate_limit, int hash_interval)
619 {
620 volatile off_t hashc;
621 ssize_t inc, outc;
622 char *bufp;
623 struct timeval tvthen, tvnow, tvdiff;
624 off_t bufrem, bufchunk;
625 int serr;
626
627 hashc = hash_interval;
628 if (rate_limit)
629 bufchunk = rate_limit;
630 else
631 bufchunk = bufsize;
632
633 while (1) {
634 if (rate_limit) {
635 (void)gettimeofday(&tvthen, NULL);
636 }
637 errno = 0;
638 inc = outc = 0;
639 /* copy bufchunk at a time */
640 bufrem = bufchunk;
641 while (bufrem > 0) {
642 inc = read(infd, buf, MIN((off_t)bufsize, bufrem));
643 if (inc < 0) {
644 if (errno == EINTR || errno == EAGAIN) {
645 continue;
646 }
647 goto copy_done;
648 } else if (inc == 0) {
649 goto copy_done;
650 }
651 bytes += inc;
652 bufrem -= inc;
653 bufp = buf;
654 while (inc > 0) {
655 outc = write(outfd, bufp, inc);
656 if (outc < 0) {
657 if (errno == EINTR || errno == EAGAIN) {
658 continue;
659 }
660 goto copy_done;
661 }
662 inc -= outc;
663 bufp += outc;
664 }
665 if (hash_interval) {
666 while (bytes >= hashc) {
667 (void)putc('#', ttyout);
668 hashc += hash_interval;
669 }
670 (void)fflush(ttyout);
671 }
672 }
673 if (rate_limit) { /* rate limited; wait if necessary */
674 while (1) {
675 (void)gettimeofday(&tvnow, NULL);
676 timersub(&tvnow, &tvthen, &tvdiff);
677 if (tvdiff.tv_sec > 0)
678 break;
679 usleep(1000000 - tvdiff.tv_usec);
680 }
681 }
682 }
683
684 copy_done:
685 serr = errno;
686 if (hash_interval && bytes > 0) {
687 if (bytes < hash_interval)
688 (void)putc('#', ttyout);
689 (void)putc('\n', ttyout);
690 (void)fflush(ttyout);
691 }
692 errno = serr;
693 if (inc == -1)
694 return 1;
695 if (outc == -1)
696 return 2;
697
698 return 0;
699 }
700
701 void
sendrequest(const char * cmd,const char * local,const char * remote,int printnames)702 sendrequest(const char *cmd, const char *local, const char *remote,
703 int printnames)
704 {
705 struct stat st;
706 int c;
707 FILE *volatile fin;
708 FILE *volatile dout;
709 int (*volatile closefunc)(FILE *);
710 sigfunc volatile oldintr;
711 sigfunc volatile oldpipe;
712 off_t volatile hashbytes;
713 int hash_interval;
714 const char *lmode;
715 static size_t bufsize;
716 static char *buf;
717 int oprogress;
718
719 hashbytes = mark;
720 direction = "sent";
721 dout = NULL;
722 bytes = 0;
723 filesize = -1;
724 oprogress = progress;
725 if (verbose && printnames) {
726 if (*local != '-')
727 fprintf(ttyout, "local: %s ", local);
728 if (remote)
729 fprintf(ttyout, "remote: %s\n", remote);
730 }
731 if (proxy) {
732 proxtrans(cmd, local, remote);
733 return;
734 }
735 if (curtype != type)
736 changetype(type, 0);
737 closefunc = NULL;
738 oldintr = SIG_ERR;
739 oldpipe = SIG_ERR;
740 lmode = "w";
741 if (sigsetjmp(xferabort, 1)) {
742 while (cpend)
743 (void)getreply(0);
744 code = -1;
745 goto cleanupsend;
746 }
747 (void)xsignal(SIGQUIT, psummary);
748 oldintr = xsignal(SIGINT, abortxfer);
749 if (strcmp(local, "-") == 0) {
750 fin = stdin;
751 progress = 0;
752 } else if (*local == '|') {
753 oldpipe = xsignal(SIGPIPE, SIG_IGN);
754 fin = popen(local + 1, "r");
755 if (fin == NULL) {
756 warn("Can't execute `%s'", local + 1);
757 code = -1;
758 goto cleanupsend;
759 }
760 progress = 0;
761 closefunc = pclose;
762 } else {
763 fin = fopen(local, "r");
764 if (fin == NULL) {
765 warn("Can't open `%s'", local);
766 code = -1;
767 goto cleanupsend;
768 }
769 closefunc = fclose;
770 if (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) {
771 fprintf(ttyout, "%s: not a plain file.\n", local);
772 code = -1;
773 goto cleanupsend;
774 }
775 filesize = st.st_size;
776 }
777 if (initconn()) {
778 code = -1;
779 goto cleanupsend;
780 }
781 if (sigsetjmp(xferabort, 1))
782 goto abort;
783
784 if (restart_point &&
785 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
786 int rc;
787
788 rc = -1;
789 switch (curtype) {
790 case TYPE_A:
791 rc = fseeko(fin, restart_point, SEEK_SET);
792 break;
793 case TYPE_I:
794 case TYPE_L:
795 rc = lseek(fileno(fin), restart_point, SEEK_SET);
796 break;
797 }
798 if (rc < 0) {
799 warn("Can't seek to restart `%s'", local);
800 goto cleanupsend;
801 }
802 if (command("REST " LLF, (LLT)restart_point) != CONTINUE)
803 goto cleanupsend;
804 lmode = "r+";
805 }
806 if (remote) {
807 if (command("%s %s", cmd, remote) != PRELIM)
808 goto cleanupsend;
809 } else {
810 if (command("%s", cmd) != PRELIM)
811 goto cleanupsend;
812 }
813 dirchange = 1;
814 dout = dataconn(lmode);
815 if (dout == NULL)
816 goto abort;
817
818 assert(sndbuf_size > 0);
819 if ((size_t)sndbuf_size > bufsize) {
820 if (buf)
821 (void)free(buf);
822 bufsize = sndbuf_size;
823 buf = ftp_malloc(bufsize);
824 }
825
826 progressmeter(-1);
827 if (oldpipe == SIG_ERR) {
828 oldpipe = xsignal(SIGPIPE, SIG_IGN);
829 }
830 hash_interval = (hash && (!progress || filesize < 0)) ? mark : 0;
831
832 switch (curtype) {
833
834 case TYPE_I:
835 case TYPE_L:
836 c = copy_bytes(fileno(fin), fileno(dout), buf, bufsize,
837 rate_put, hash_interval);
838 if (c == 1) {
839 warn("Reading `%s'", local);
840 } else if (c == 2) {
841 if (errno != EPIPE)
842 warn("Writing to network");
843 bytes = -1;
844 }
845 break;
846
847 case TYPE_A:
848 while ((c = getc(fin)) != EOF) {
849 if (c == '\n') {
850 while (hash_interval && bytes >= hashbytes) {
851 (void)putc('#', ttyout);
852 (void)fflush(ttyout);
853 hashbytes += mark;
854 }
855 if (ferror(dout))
856 break;
857 (void)putc('\r', dout);
858 bytes++;
859 }
860 (void)putc(c, dout);
861 bytes++;
862 #if 0 /* this violates RFC 959 */
863 if (c == '\r') {
864 (void)putc('\0', dout);
865 bytes++;
866 }
867 #endif
868 }
869 if (hash_interval) {
870 if (bytes < hashbytes)
871 (void)putc('#', ttyout);
872 (void)putc('\n', ttyout);
873 }
874 if (ferror(fin))
875 warn("Reading `%s'", local);
876 if (ferror(dout)) {
877 if (errno != EPIPE)
878 warn("Writing to network");
879 bytes = -1;
880 }
881 break;
882 }
883
884 progressmeter(1);
885 if (closefunc != NULL) {
886 (*closefunc)(fin);
887 fin = NULL;
888 }
889 (void)fclose(dout);
890 dout = NULL;
891 (void)getreply(0);
892 if (bytes > 0)
893 ptransfer(0);
894 goto cleanupsend;
895
896 abort:
897 (void)xsignal(SIGINT, oldintr);
898 oldintr = SIG_ERR;
899 if (!cpend) {
900 code = -1;
901 goto cleanupsend;
902 }
903 if (data >= 0) {
904 (void)close(data);
905 data = -1;
906 }
907 if (dout) {
908 (void)fclose(dout);
909 dout = NULL;
910 }
911 (void)getreply(0);
912 code = -1;
913 if (bytes > 0)
914 ptransfer(0);
915
916 cleanupsend:
917 if (oldintr != SIG_ERR)
918 (void)xsignal(SIGINT, oldintr);
919 if (oldpipe != SIG_ERR)
920 (void)xsignal(SIGPIPE, oldpipe);
921 if (data >= 0) {
922 (void)close(data);
923 data = -1;
924 }
925 if (closefunc != NULL && fin != NULL)
926 (*closefunc)(fin);
927 if (dout)
928 (void)fclose(dout);
929 progress = oprogress;
930 restart_point = 0;
931 bytes = 0;
932 }
933
934 void
recvrequest(const char * cmd,const char * volatile local,const char * remote,const char * lmode,int printnames,int ignorespecial)935 recvrequest(const char *cmd, const char *volatile local, const char *remote,
936 const char *lmode, int printnames, int ignorespecial)
937 {
938 FILE *volatile fout;
939 FILE *volatile din;
940 int (*volatile closefunc)(FILE *);
941 sigfunc volatile oldintr;
942 sigfunc volatile oldpipe;
943 int c, d;
944 int volatile is_retr;
945 int volatile tcrflag;
946 int volatile bare_lfs;
947 static size_t bufsize;
948 static char *buf;
949 off_t volatile hashbytes;
950 int hash_interval;
951 struct stat st;
952 time_t mtime;
953 struct timeval tval[2];
954 int oprogress;
955 int opreserve;
956
957 fout = NULL;
958 din = NULL;
959 hashbytes = mark;
960 direction = "received";
961 bytes = 0;
962 bare_lfs = 0;
963 filesize = -1;
964 oprogress = progress;
965 opreserve = preserve;
966 is_retr = (strcmp(cmd, "RETR") == 0);
967 if (is_retr && verbose && printnames) {
968 if (ignorespecial || *local != '-')
969 fprintf(ttyout, "local: %s ", local);
970 if (remote)
971 fprintf(ttyout, "remote: %s\n", remote);
972 }
973 if (proxy && is_retr) {
974 proxtrans(cmd, local, remote);
975 return;
976 }
977 closefunc = NULL;
978 oldintr = SIG_ERR;
979 oldpipe = SIG_ERR;
980 tcrflag = !crflag && is_retr;
981 if (sigsetjmp(xferabort, 1)) {
982 while (cpend)
983 (void)getreply(0);
984 code = -1;
985 goto cleanuprecv;
986 }
987 (void)xsignal(SIGQUIT, psummary);
988 oldintr = xsignal(SIGINT, abortxfer);
989 if (ignorespecial || (strcmp(local, "-") && *local != '|')) {
990 if (access(local, W_OK) < 0) {
991 char *dir = strrchr(local, '/');
992
993 if (errno != ENOENT && errno != EACCES) {
994 warn("Can't access `%s'", local);
995 code = -1;
996 goto cleanuprecv;
997 }
998 if (dir != NULL)
999 *dir = 0;
1000 d = access(dir == local ? "/" :
1001 dir ? local : ".", W_OK);
1002 if (dir != NULL)
1003 *dir = '/';
1004 if (d < 0) {
1005 warn("Can't access `%s'", local);
1006 code = -1;
1007 goto cleanuprecv;
1008 }
1009 if (!runique && errno == EACCES &&
1010 chmod(local, (S_IRUSR|S_IWUSR)) < 0) {
1011 warn("Can't chmod `%s'", local);
1012 code = -1;
1013 goto cleanuprecv;
1014 }
1015 if (runique && errno == EACCES &&
1016 (local = gunique(local)) == NULL) {
1017 code = -1;
1018 goto cleanuprecv;
1019 }
1020 }
1021 else if (runique && (local = gunique(local)) == NULL) {
1022 code = -1;
1023 goto cleanuprecv;
1024 }
1025 }
1026 if (!is_retr) {
1027 if (curtype != TYPE_A)
1028 changetype(TYPE_A, 0);
1029 } else {
1030 if (curtype != type)
1031 changetype(type, 0);
1032 filesize = remotesize(remote, 0);
1033 if (code == 421 || code == -1)
1034 goto cleanuprecv;
1035 }
1036 if (initconn()) {
1037 code = -1;
1038 goto cleanuprecv;
1039 }
1040 if (sigsetjmp(xferabort, 1))
1041 goto abort;
1042 if (is_retr && restart_point &&
1043 command("REST " LLF, (LLT) restart_point) != CONTINUE)
1044 goto cleanuprecv;
1045 if (! EMPTYSTRING(remote)) {
1046 if (command("%s %s", cmd, remote) != PRELIM)
1047 goto cleanuprecv;
1048 } else {
1049 if (command("%s", cmd) != PRELIM)
1050 goto cleanuprecv;
1051 }
1052 din = dataconn("r");
1053 if (din == NULL)
1054 goto abort;
1055 if (!ignorespecial && strcmp(local, "-") == 0) {
1056 fout = stdout;
1057 progress = 0;
1058 preserve = 0;
1059 } else if (!ignorespecial && *local == '|') {
1060 oldpipe = xsignal(SIGPIPE, SIG_IGN);
1061 fout = popen(local + 1, "w");
1062 if (fout == NULL) {
1063 warn("Can't execute `%s'", local+1);
1064 goto abort;
1065 }
1066 progress = 0;
1067 preserve = 0;
1068 closefunc = pclose;
1069 } else {
1070 fout = fopen(local, lmode);
1071 if (fout == NULL) {
1072 warn("Can't open `%s'", local);
1073 goto abort;
1074 }
1075 closefunc = fclose;
1076 }
1077
1078 if (fstat(fileno(fout), &st) != -1 && !S_ISREG(st.st_mode)) {
1079 progress = 0;
1080 preserve = 0;
1081 }
1082 assert(rcvbuf_size > 0);
1083 if ((size_t)rcvbuf_size > bufsize) {
1084 if (buf)
1085 (void)free(buf);
1086 bufsize = rcvbuf_size;
1087 buf = ftp_malloc(bufsize);
1088 }
1089
1090 progressmeter(-1);
1091 hash_interval = (hash && (!progress || filesize < 0)) ? mark : 0;
1092
1093 switch (curtype) {
1094
1095 case TYPE_I:
1096 case TYPE_L:
1097 if (is_retr && restart_point &&
1098 lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
1099 warn("Can't seek to restart `%s'", local);
1100 goto cleanuprecv;
1101 }
1102 c = copy_bytes(fileno(din), fileno(fout), buf, bufsize,
1103 rate_get, hash_interval);
1104 if (c == 1) {
1105 if (errno != EPIPE)
1106 warn("Reading from network");
1107 bytes = -1;
1108 } else if (c == 2) {
1109 warn("Writing `%s'", local);
1110 }
1111 break;
1112
1113 case TYPE_A:
1114 if (is_retr && restart_point) {
1115 int ch;
1116 off_t i;
1117
1118 if (fseeko(fout, (off_t)0, SEEK_SET) < 0)
1119 goto done;
1120 for (i = 0; i++ < restart_point;) {
1121 if ((ch = getc(fout)) == EOF)
1122 goto done;
1123 if (ch == '\n')
1124 i++;
1125 }
1126 if (fseeko(fout, (off_t)0, SEEK_CUR) < 0) {
1127 done:
1128 warn("Can't seek to restart `%s'", local);
1129 goto cleanuprecv;
1130 }
1131 }
1132 while ((c = getc(din)) != EOF) {
1133 if (c == '\n')
1134 bare_lfs++;
1135 while (c == '\r') {
1136 while (hash_interval && bytes >= hashbytes) {
1137 (void)putc('#', ttyout);
1138 (void)fflush(ttyout);
1139 hashbytes += mark;
1140 }
1141 bytes++;
1142 if ((c = getc(din)) != '\n' || tcrflag) {
1143 if (ferror(fout))
1144 goto break2;
1145 (void)putc('\r', fout);
1146 if (c == '\0') {
1147 bytes++;
1148 goto contin2;
1149 }
1150 if (c == EOF)
1151 goto contin2;
1152 }
1153 }
1154 (void)putc(c, fout);
1155 bytes++;
1156 contin2: ;
1157 }
1158 break2:
1159 if (hash_interval) {
1160 if (bytes < hashbytes)
1161 (void)putc('#', ttyout);
1162 (void)putc('\n', ttyout);
1163 }
1164 if (ferror(din)) {
1165 if (errno != EPIPE)
1166 warn("Reading from network");
1167 bytes = -1;
1168 }
1169 if (ferror(fout))
1170 warn("Writing `%s'", local);
1171 break;
1172 }
1173
1174 progressmeter(1);
1175 if (closefunc != NULL) {
1176 (*closefunc)(fout);
1177 fout = NULL;
1178 }
1179 (void)fclose(din);
1180 din = NULL;
1181 (void)getreply(0);
1182 if (bare_lfs) {
1183 fprintf(ttyout,
1184 "WARNING! %d bare linefeeds received in ASCII mode.\n",
1185 bare_lfs);
1186 fputs("File may not have transferred correctly.\n", ttyout);
1187 }
1188 if (bytes >= 0 && is_retr) {
1189 if (bytes > 0)
1190 ptransfer(0);
1191 if (preserve && (closefunc == fclose)) {
1192 mtime = remotemodtime(remote, 0);
1193 if (mtime != -1) {
1194 (void)gettimeofday(&tval[0], NULL);
1195 tval[1].tv_sec = mtime;
1196 tval[1].tv_usec = 0;
1197 if (utimes(local, tval) == -1) {
1198 fprintf(ttyout,
1199 "Can't change modification time on %s to %s",
1200 local,
1201 rfc2822time(localtime(&mtime)));
1202 }
1203 }
1204 }
1205 }
1206 goto cleanuprecv;
1207
1208 abort:
1209 /*
1210 * abort using RFC 959 recommended IP,SYNC sequence
1211 */
1212 if (! sigsetjmp(xferabort, 1)) {
1213 /* this is the first call */
1214 (void)xsignal(SIGINT, abort_squared);
1215 if (!cpend) {
1216 code = -1;
1217 goto cleanuprecv;
1218 }
1219 abort_remote(din);
1220 }
1221 code = -1;
1222 if (bytes > 0)
1223 ptransfer(0);
1224
1225 cleanuprecv:
1226 if (oldintr != SIG_ERR)
1227 (void)xsignal(SIGINT, oldintr);
1228 if (oldpipe != SIG_ERR)
1229 (void)xsignal(SIGPIPE, oldpipe);
1230 if (data >= 0) {
1231 (void)close(data);
1232 data = -1;
1233 }
1234 if (closefunc != NULL && fout != NULL)
1235 (*closefunc)(fout);
1236 if (din)
1237 (void)fclose(din);
1238 progress = oprogress;
1239 preserve = opreserve;
1240 bytes = 0;
1241 }
1242
1243 /*
1244 * Need to start a listen on the data channel before we send the command,
1245 * otherwise the server's connect may fail.
1246 */
1247 int
initconn(void)1248 initconn(void)
1249 {
1250 char *p, *a;
1251 int result, tmpno = 0;
1252 int on = 1;
1253 int error;
1254 unsigned int addr[16], port[2];
1255 unsigned int af, hal, pal;
1256 socklen_t len;
1257 const char *pasvcmd = NULL;
1258 int overbose;
1259
1260 #ifdef INET6
1261 #ifndef NO_DEBUG
1262 if (myctladdr.su_family == AF_INET6 && ftp_debug &&
1263 (IN6_IS_ADDR_LINKLOCAL(&myctladdr.si_su.su_sin6.sin6_addr) ||
1264 IN6_IS_ADDR_SITELOCAL(&myctladdr.si_su.su_sin6.sin6_addr))) {
1265 warnx("Use of scoped addresses can be troublesome");
1266 }
1267 #endif
1268 #endif
1269
1270 reinit:
1271 if (passivemode) {
1272 data_addr = myctladdr;
1273 data = socket(data_addr.su_family, SOCK_STREAM, 0);
1274 if (data < 0) {
1275 warn("Can't create socket for data connection");
1276 return (1);
1277 }
1278 if ((options & SO_DEBUG) &&
1279 setsockopt(data, SOL_SOCKET, SO_DEBUG,
1280 (void *)&on, sizeof(on)) == -1) {
1281 DWARN("setsockopt %s (ignored)", "SO_DEBUG");
1282 }
1283 result = COMPLETE + 1;
1284 switch (data_addr.su_family) {
1285 case AF_INET:
1286 if (epsv4 && !epsv4bad) {
1287 pasvcmd = "EPSV";
1288 overbose = verbose;
1289 if (ftp_debug == 0)
1290 verbose = -1;
1291 result = command("EPSV");
1292 verbose = overbose;
1293 if (verbose > 0 &&
1294 (result == COMPLETE || !connected))
1295 fprintf(ttyout, "%s\n", reply_string);
1296 if (!connected)
1297 return (1);
1298 /*
1299 * this code is to be friendly with broken
1300 * BSDI ftpd
1301 */
1302 if (code / 10 == 22 && code != 229) {
1303 fputs(
1304 "wrong server: return code must be 229\n",
1305 ttyout);
1306 result = COMPLETE + 1;
1307 }
1308 if (result != COMPLETE) {
1309 epsv4bad = 1;
1310 DPRINTF("disabling epsv4 for this "
1311 "connection\n");
1312 }
1313 }
1314 if (result != COMPLETE) {
1315 pasvcmd = "PASV";
1316 result = command("PASV");
1317 if (!connected)
1318 return (1);
1319 }
1320 break;
1321 #ifdef INET6
1322 case AF_INET6:
1323 if (epsv6 && !epsv6bad) {
1324 pasvcmd = "EPSV";
1325 overbose = verbose;
1326 if (ftp_debug == 0)
1327 verbose = -1;
1328 result = command("EPSV");
1329 verbose = overbose;
1330 if (verbose > 0 &&
1331 (result == COMPLETE || !connected))
1332 fprintf(ttyout, "%s\n", reply_string);
1333 if (!connected)
1334 return (1);
1335 /*
1336 * this code is to be friendly with
1337 * broken BSDI ftpd
1338 */
1339 if (code / 10 == 22 && code != 229) {
1340 fputs(
1341 "wrong server: return code must be 229\n",
1342 ttyout);
1343 result = COMPLETE + 1;
1344 }
1345 if (result != COMPLETE) {
1346 epsv6bad = 1;
1347 DPRINTF("disabling epsv6 for this "
1348 "connection\n");
1349 }
1350 }
1351 if (result != COMPLETE) {
1352 pasvcmd = "LPSV";
1353 result = command("LPSV");
1354 }
1355 if (!connected)
1356 return (1);
1357 break;
1358 #endif
1359 default:
1360 result = COMPLETE + 1;
1361 break;
1362 }
1363 if (result != COMPLETE) {
1364 if (activefallback) {
1365 (void)close(data);
1366 data = -1;
1367 passivemode = 0;
1368 #if 0
1369 activefallback = 0;
1370 #endif
1371 goto reinit;
1372 }
1373 fputs("Passive mode refused.\n", ttyout);
1374 goto bad;
1375 }
1376
1377 #define pack2(var, off) \
1378 (((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0))
1379 #define pack4(var, off) \
1380 (((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \
1381 ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0))
1382 #define UC(b) (((int)b)&0xff)
1383
1384 /*
1385 * What we've got at this point is a string of comma separated
1386 * one-byte unsigned integer values, separated by commas.
1387 */
1388 if (strcmp(pasvcmd, "PASV") == 0) {
1389 if (data_addr.su_family != AF_INET) {
1390 fputs(
1391 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1392 goto bad;
1393 }
1394 if (code / 10 == 22 && code != 227) {
1395 fputs("wrong server: return code must be 227\n",
1396 ttyout);
1397 goto bad;
1398 }
1399 error = sscanf(pasv, "%u,%u,%u,%u,%u,%u",
1400 &addr[0], &addr[1], &addr[2], &addr[3],
1401 &port[0], &port[1]);
1402 if (error != 6) {
1403 fputs(
1404 "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1405 goto bad;
1406 }
1407 memset(&data_addr, 0, sizeof(data_addr));
1408 data_addr.su_family = AF_INET;
1409 data_addr.su_len = sizeof(struct sockaddr_in);
1410 data_addr.si_su.su_sin.sin_addr.s_addr =
1411 htonl(pack4(addr, 0));
1412 data_addr.su_port = htons(pack2(port, 0));
1413 if (data_addr.si_su.su_sin.sin_addr.s_addr !=
1414 hisctladdr.si_su.su_sin.sin_addr.s_addr) {
1415 fputs("Passive mode address mismatch.\n",
1416 ttyout);
1417 goto bad;
1418 }
1419 } else if (strcmp(pasvcmd, "LPSV") == 0) {
1420 if (code / 10 == 22 && code != 228) {
1421 fputs("wrong server: return code must be 228\n",
1422 ttyout);
1423 goto bad;
1424 }
1425 switch (data_addr.su_family) {
1426 case AF_INET:
1427 error = sscanf(pasv,
1428 "%u,%u,%u,%u,%u,%u,%u,%u,%u",
1429 &af, &hal,
1430 &addr[0], &addr[1], &addr[2], &addr[3],
1431 &pal, &port[0], &port[1]);
1432 if (error != 9) {
1433 fputs(
1434 "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1435 goto bad;
1436 }
1437 if (af != 4 || hal != 4 || pal != 2) {
1438 fputs(
1439 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1440 goto bad;
1441 }
1442
1443 memset(&data_addr, 0, sizeof(data_addr));
1444 data_addr.su_family = AF_INET;
1445 data_addr.su_len = sizeof(struct sockaddr_in);
1446 data_addr.si_su.su_sin.sin_addr.s_addr =
1447 htonl(pack4(addr, 0));
1448 data_addr.su_port = htons(pack2(port, 0));
1449 if (data_addr.si_su.su_sin.sin_addr.s_addr !=
1450 hisctladdr.si_su.su_sin.sin_addr.s_addr) {
1451 fputs("Passive mode address mismatch.\n",
1452 ttyout);
1453 goto bad;
1454 }
1455 break;
1456 #ifdef INET6
1457 case AF_INET6:
1458 error = sscanf(pasv,
1459 "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
1460 &af, &hal,
1461 &addr[0], &addr[1], &addr[2], &addr[3],
1462 &addr[4], &addr[5], &addr[6], &addr[7],
1463 &addr[8], &addr[9], &addr[10],
1464 &addr[11], &addr[12], &addr[13],
1465 &addr[14], &addr[15],
1466 &pal, &port[0], &port[1]);
1467 if (error != 21) {
1468 fputs(
1469 "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1470 goto bad;
1471 }
1472 if (af != 6 || hal != 16 || pal != 2) {
1473 fputs(
1474 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1475 goto bad;
1476 }
1477
1478 memset(&data_addr, 0, sizeof(data_addr));
1479 data_addr.su_family = AF_INET6;
1480 data_addr.su_len = sizeof(struct sockaddr_in6);
1481 {
1482 size_t i;
1483 for (i = 0; i < sizeof(struct in6_addr); i++) {
1484 data_addr.si_su.su_sin6.sin6_addr.s6_addr[i] =
1485 UC(addr[i]);
1486 }
1487 }
1488 data_addr.su_port = htons(pack2(port, 0));
1489 if (memcmp(
1490 &data_addr.si_su.su_sin6.sin6_addr,
1491 &hisctladdr.si_su.su_sin6.sin6_addr,
1492 sizeof(data_addr.si_su.su_sin6.sin6_addr))) {
1493 fputs("Passive mode address mismatch.\n",
1494 ttyout);
1495 goto bad;
1496 }
1497 break;
1498 #endif
1499 default:
1500 fputs("Unknown passive mode AF.\n", ttyout);
1501 goto bad;
1502 }
1503 } else if (strcmp(pasvcmd, "EPSV") == 0) {
1504 char delim[4];
1505
1506 port[0] = 0;
1507 if (code / 10 == 22 && code != 229) {
1508 fputs("wrong server: return code must be 229\n",
1509 ttyout);
1510 goto bad;
1511 }
1512 if (sscanf(pasv, "%c%c%c%d%c", &delim[0],
1513 &delim[1], &delim[2], &port[1],
1514 &delim[3]) != 5) {
1515 fputs("parse error!\n", ttyout);
1516 goto bad;
1517 }
1518 if (delim[0] != delim[1] || delim[0] != delim[2]
1519 || delim[0] != delim[3]) {
1520 fputs("parse error!\n", ttyout);
1521 goto bad;
1522 }
1523 data_addr = hisctladdr;
1524 data_addr.su_port = htons(port[1]);
1525 } else
1526 goto bad;
1527
1528 if (ftp_connect(data, (struct sockaddr *)&data_addr.si_su,
1529 data_addr.su_len, 1) < 0) {
1530 if (activefallback) {
1531 (void)close(data);
1532 data = -1;
1533 passivemode = 0;
1534 #if 0
1535 activefallback = 0;
1536 #endif
1537 goto reinit;
1538 }
1539 goto bad;
1540 }
1541 #ifdef IPTOS_THROUGHPUT
1542 if (data_addr.su_family == AF_INET) {
1543 on = IPTOS_THROUGHPUT;
1544 if (setsockopt(data, IPPROTO_IP, IP_TOS,
1545 (void *)&on, sizeof(on)) == -1) {
1546 DWARN("setsockopt %s (ignored)",
1547 "IPTOS_THROUGHPUT");
1548 }
1549 }
1550 #endif
1551 return (0);
1552 }
1553
1554 noport:
1555 data_addr = myctladdr;
1556 if (sendport)
1557 data_addr.su_port = 0; /* let system pick one */
1558 if (data != -1)
1559 (void)close(data);
1560 data = socket(data_addr.su_family, SOCK_STREAM, 0);
1561 if (data < 0) {
1562 warn("Can't create socket for data connection");
1563 if (tmpno)
1564 sendport = 1;
1565 return (1);
1566 }
1567 if (!sendport)
1568 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR,
1569 (void *)&on, sizeof(on)) == -1) {
1570 warn("Can't set SO_REUSEADDR on data connection");
1571 goto bad;
1572 }
1573 if (bind(data, (struct sockaddr *)&data_addr.si_su,
1574 data_addr.su_len) < 0) {
1575 warn("Can't bind for data connection");
1576 goto bad;
1577 }
1578 if ((options & SO_DEBUG) &&
1579 setsockopt(data, SOL_SOCKET, SO_DEBUG,
1580 (void *)&on, sizeof(on)) == -1) {
1581 DWARN("setsockopt %s (ignored)", "SO_DEBUG");
1582 }
1583 len = sizeof(data_addr.si_su);
1584 memset((char *)&data_addr, 0, sizeof (data_addr));
1585 if (getsockname(data, (struct sockaddr *)&data_addr.si_su, &len) == -1) {
1586 warn("Can't determine my address of data connection");
1587 goto bad;
1588 }
1589 data_addr.su_len = len;
1590 if (ftp_listen(data, 1) < 0)
1591 warn("Can't listen to data connection");
1592
1593 if (sendport) {
1594 char hname[NI_MAXHOST], sname[NI_MAXSERV];
1595 struct sockinet tmp;
1596
1597 switch (data_addr.su_family) {
1598 case AF_INET:
1599 if (!epsv4 || epsv4bad) {
1600 result = COMPLETE + 1;
1601 break;
1602 }
1603 #ifdef INET6
1604 /* FALLTHROUGH */
1605 case AF_INET6:
1606 if (!epsv6 || epsv6bad) {
1607 result = COMPLETE + 1;
1608 break;
1609 }
1610 #endif
1611 af = (data_addr.su_family == AF_INET) ? 1 : 2;
1612 tmp = data_addr;
1613 #ifdef INET6
1614 if (tmp.su_family == AF_INET6)
1615 tmp.si_su.su_sin6.sin6_scope_id = 0;
1616 #endif
1617 if (getnameinfo((struct sockaddr *)&tmp.si_su,
1618 tmp.su_len, hname, sizeof(hname), sname,
1619 sizeof(sname), NI_NUMERICHOST | NI_NUMERICSERV)) {
1620 result = ERROR;
1621 } else {
1622 overbose = verbose;
1623 if (ftp_debug == 0)
1624 verbose = -1;
1625 result = command("EPRT |%u|%s|%s|", af, hname,
1626 sname);
1627 verbose = overbose;
1628 if (verbose > 0 &&
1629 (result == COMPLETE || !connected))
1630 fprintf(ttyout, "%s\n", reply_string);
1631 if (!connected)
1632 return (1);
1633 if (result != COMPLETE) {
1634 epsv4bad = 1;
1635 DPRINTF("disabling epsv4 for this "
1636 "connection\n");
1637 }
1638 }
1639 break;
1640 default:
1641 result = COMPLETE + 1;
1642 break;
1643 }
1644 if (result == COMPLETE)
1645 goto skip_port;
1646
1647 switch (data_addr.su_family) {
1648 case AF_INET:
1649 a = (char *)&data_addr.si_su.su_sin.sin_addr;
1650 p = (char *)&data_addr.su_port;
1651 result = command("PORT %d,%d,%d,%d,%d,%d",
1652 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1653 UC(p[0]), UC(p[1]));
1654 break;
1655 #ifdef INET6
1656 case AF_INET6: {
1657 uint8_t ua[sizeof(data_addr.si_su.su_sin6.sin6_addr)];
1658 uint8_t up[sizeof(data_addr.su_port)];
1659
1660 memcpy(ua, &data_addr.si_su.su_sin6.sin6_addr,
1661 sizeof(ua));
1662 memcpy(up, &data_addr.su_port, sizeof(up));
1663
1664 result = command(
1665 "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
1666 6, 16,
1667 ua[0], ua[1], ua[2], ua[3],
1668 ua[4], ua[5], ua[6], ua[7],
1669 ua[8], ua[9], ua[10], ua[11],
1670 ua[12], ua[13], ua[14], ua[15],
1671 2,
1672 up[0], up[1]);
1673 break;
1674 }
1675 #endif
1676 default:
1677 result = COMPLETE + 1; /* xxx */
1678 }
1679 if (!connected)
1680 return (1);
1681 skip_port:
1682
1683 if (result == ERROR && sendport == -1) {
1684 sendport = 0;
1685 tmpno = 1;
1686 goto noport;
1687 }
1688 return (result != COMPLETE);
1689 }
1690 if (tmpno)
1691 sendport = 1;
1692 #ifdef IPTOS_THROUGHPUT
1693 if (data_addr.su_family == AF_INET) {
1694 on = IPTOS_THROUGHPUT;
1695 if (setsockopt(data, IPPROTO_IP, IP_TOS,
1696 (void *)&on, sizeof(on)) == -1) {
1697 DWARN("setsockopt %s (ignored)", "IPTOS_THROUGHPUT");
1698 }
1699 }
1700 #endif
1701 return (0);
1702 bad:
1703 (void)close(data);
1704 data = -1;
1705 if (tmpno)
1706 sendport = 1;
1707 return (1);
1708 }
1709
1710 FILE *
dataconn(const char * lmode)1711 dataconn(const char *lmode)
1712 {
1713 struct sockinet from;
1714 int s, flags, rv, timeout;
1715 struct timeval endtime, now, td;
1716 struct pollfd pfd[1];
1717 socklen_t fromlen;
1718
1719 if (passivemode) /* passive data connection */
1720 return (fdopen(data, lmode));
1721
1722 /* active mode data connection */
1723
1724 if ((flags = fcntl(data, F_GETFL, 0)) == -1)
1725 goto dataconn_failed; /* get current socket flags */
1726 if (fcntl(data, F_SETFL, flags | O_NONBLOCK) == -1)
1727 goto dataconn_failed; /* set non-blocking connect */
1728
1729 /* NOTE: we now must restore socket flags on successful exit */
1730
1731 /* limit time waiting on listening socket */
1732 pfd[0].fd = data;
1733 pfd[0].events = POLLIN;
1734 (void)gettimeofday(&endtime, NULL); /* determine end time */
1735 endtime.tv_sec += (quit_time > 0) ? quit_time: 60;
1736 /* without -q, default to 60s */
1737 do {
1738 (void)gettimeofday(&now, NULL);
1739 timersub(&endtime, &now, &td);
1740 timeout = td.tv_sec * 1000 + td.tv_usec/1000;
1741 if (timeout < 0)
1742 timeout = 0;
1743 rv = ftp_poll(pfd, 1, timeout);
1744 } while (rv == -1 && errno == EINTR); /* loop until poll ! EINTR */
1745 if (rv == -1) {
1746 warn("Can't poll waiting before accept");
1747 goto dataconn_failed;
1748 }
1749 if (rv == 0) {
1750 warnx("Poll timeout waiting before accept");
1751 goto dataconn_failed;
1752 }
1753
1754 /* (non-blocking) accept the connection */
1755 fromlen = myctladdr.su_len;
1756 do {
1757 s = accept(data, (struct sockaddr *) &from.si_su, &fromlen);
1758 } while (s == -1 && errno == EINTR); /* loop until accept ! EINTR */
1759 if (s == -1) {
1760 warn("Can't accept data connection");
1761 goto dataconn_failed;
1762 }
1763
1764 (void)close(data);
1765 data = s;
1766 if (fcntl(data, F_SETFL, flags) == -1) /* restore socket flags */
1767 goto dataconn_failed;
1768
1769 #ifdef IPTOS_THROUGHPUT
1770 if (from.su_family == AF_INET) {
1771 int tos = IPTOS_THROUGHPUT;
1772 if (setsockopt(s, IPPROTO_IP, IP_TOS,
1773 (void *)&tos, sizeof(tos)) == -1) {
1774 DWARN("setsockopt %s (ignored)", "IPTOS_THROUGHPUT");
1775 }
1776 }
1777 #endif
1778 return (fdopen(data, lmode));
1779
1780 dataconn_failed:
1781 (void)close(data);
1782 data = -1;
1783 return (NULL);
1784 }
1785
1786 void
psabort(int notused)1787 psabort(int notused)
1788 {
1789 int oerrno = errno;
1790
1791 sigint_raised = 1;
1792 alarmtimer(0);
1793 abrtflag++;
1794 errno = oerrno;
1795 }
1796
1797 void
pswitch(int flag)1798 pswitch(int flag)
1799 {
1800 sigfunc oldintr;
1801 static struct comvars {
1802 int connect;
1803 char name[MAXHOSTNAMELEN];
1804 struct sockinet mctl;
1805 struct sockinet hctl;
1806 FILE *in;
1807 FILE *out;
1808 int tpe;
1809 int curtpe;
1810 int cpnd;
1811 int sunqe;
1812 int runqe;
1813 int mcse;
1814 int ntflg;
1815 char nti[17];
1816 char nto[17];
1817 int mapflg;
1818 char mi[MAXPATHLEN];
1819 char mo[MAXPATHLEN];
1820 } proxstruct, tmpstruct;
1821 struct comvars *ip, *op;
1822
1823 abrtflag = 0;
1824 oldintr = xsignal(SIGINT, psabort);
1825 if (flag) {
1826 if (proxy)
1827 return;
1828 ip = &tmpstruct;
1829 op = &proxstruct;
1830 proxy++;
1831 } else {
1832 if (!proxy)
1833 return;
1834 ip = &proxstruct;
1835 op = &tmpstruct;
1836 proxy = 0;
1837 }
1838 ip->connect = connected;
1839 connected = op->connect;
1840 if (hostname)
1841 (void)strlcpy(ip->name, hostname, sizeof(ip->name));
1842 else
1843 ip->name[0] = '\0';
1844 hostname = op->name;
1845 ip->hctl = hisctladdr;
1846 hisctladdr = op->hctl;
1847 ip->mctl = myctladdr;
1848 myctladdr = op->mctl;
1849 ip->in = cin;
1850 cin = op->in;
1851 ip->out = cout;
1852 cout = op->out;
1853 ip->tpe = type;
1854 type = op->tpe;
1855 ip->curtpe = curtype;
1856 curtype = op->curtpe;
1857 ip->cpnd = cpend;
1858 cpend = op->cpnd;
1859 ip->sunqe = sunique;
1860 sunique = op->sunqe;
1861 ip->runqe = runique;
1862 runique = op->runqe;
1863 ip->mcse = mcase;
1864 mcase = op->mcse;
1865 ip->ntflg = ntflag;
1866 ntflag = op->ntflg;
1867 (void)strlcpy(ip->nti, ntin, sizeof(ip->nti));
1868 (void)strlcpy(ntin, op->nti, sizeof(ntin));
1869 (void)strlcpy(ip->nto, ntout, sizeof(ip->nto));
1870 (void)strlcpy(ntout, op->nto, sizeof(ntout));
1871 ip->mapflg = mapflag;
1872 mapflag = op->mapflg;
1873 (void)strlcpy(ip->mi, mapin, sizeof(ip->mi));
1874 (void)strlcpy(mapin, op->mi, sizeof(mapin));
1875 (void)strlcpy(ip->mo, mapout, sizeof(ip->mo));
1876 (void)strlcpy(mapout, op->mo, sizeof(mapout));
1877 (void)xsignal(SIGINT, oldintr);
1878 if (abrtflag) {
1879 abrtflag = 0;
1880 (*oldintr)(SIGINT);
1881 }
1882 }
1883
1884 __dead static void
abortpt(int notused)1885 abortpt(int notused)
1886 {
1887
1888 sigint_raised = 1;
1889 alarmtimer(0);
1890 if (fromatty)
1891 write(fileno(ttyout), "\n", 1);
1892 ptabflg++;
1893 mflag = 0;
1894 abrtflag = 0;
1895 siglongjmp(ptabort, 1);
1896 }
1897
1898 void
proxtrans(const char * cmd,const char * local,const char * remote)1899 proxtrans(const char *cmd, const char *local, const char *remote)
1900 {
1901 sigfunc volatile oldintr;
1902 int prox_type, nfnd;
1903 int volatile secndflag;
1904 const char *volatile cmd2;
1905
1906 oldintr = SIG_ERR;
1907 secndflag = 0;
1908 if (strcmp(cmd, "RETR"))
1909 cmd2 = "RETR";
1910 else
1911 cmd2 = runique ? "STOU" : "STOR";
1912 if ((prox_type = type) == 0) {
1913 if (unix_server && unix_proxy)
1914 prox_type = TYPE_I;
1915 else
1916 prox_type = TYPE_A;
1917 }
1918 if (curtype != prox_type)
1919 changetype(prox_type, 1);
1920 if (command("PASV") != COMPLETE) {
1921 fputs("proxy server does not support third party transfers.\n",
1922 ttyout);
1923 return;
1924 }
1925 pswitch(0);
1926 if (!connected) {
1927 fputs("No primary connection.\n", ttyout);
1928 pswitch(1);
1929 code = -1;
1930 return;
1931 }
1932 if (curtype != prox_type)
1933 changetype(prox_type, 1);
1934 if (command("PORT %s", pasv) != COMPLETE) {
1935 pswitch(1);
1936 return;
1937 }
1938 if (sigsetjmp(ptabort, 1))
1939 goto abort;
1940 oldintr = xsignal(SIGINT, abortpt);
1941 if ((restart_point &&
1942 (command("REST " LLF, (LLT) restart_point) != CONTINUE))
1943 || (command("%s %s", cmd, remote) != PRELIM)) {
1944 (void)xsignal(SIGINT, oldintr);
1945 pswitch(1);
1946 return;
1947 }
1948 sleep(2);
1949 pswitch(1);
1950 secndflag++;
1951 if ((restart_point &&
1952 (command("REST " LLF, (LLT) restart_point) != CONTINUE))
1953 || (command("%s %s", cmd2, local) != PRELIM))
1954 goto abort;
1955 ptflag++;
1956 (void)getreply(0);
1957 pswitch(0);
1958 (void)getreply(0);
1959 (void)xsignal(SIGINT, oldintr);
1960 pswitch(1);
1961 ptflag = 0;
1962 fprintf(ttyout, "local: %s remote: %s\n", local, remote);
1963 return;
1964 abort:
1965 if (sigsetjmp(xferabort, 1)) {
1966 (void)xsignal(SIGINT, oldintr);
1967 return;
1968 }
1969 (void)xsignal(SIGINT, abort_squared);
1970 ptflag = 0;
1971 if (strcmp(cmd, "RETR") && !proxy)
1972 pswitch(1);
1973 else if (!strcmp(cmd, "RETR") && proxy)
1974 pswitch(0);
1975 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1976 if (command("%s %s", cmd2, local) != PRELIM) {
1977 pswitch(0);
1978 if (cpend)
1979 abort_remote(NULL);
1980 }
1981 pswitch(1);
1982 if (ptabflg)
1983 code = -1;
1984 (void)xsignal(SIGINT, oldintr);
1985 return;
1986 }
1987 if (cpend)
1988 abort_remote(NULL);
1989 pswitch(!proxy);
1990 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1991 if (command("%s %s", cmd2, local) != PRELIM) {
1992 pswitch(0);
1993 if (cpend)
1994 abort_remote(NULL);
1995 pswitch(1);
1996 if (ptabflg)
1997 code = -1;
1998 (void)xsignal(SIGINT, oldintr);
1999 return;
2000 }
2001 }
2002 if (cpend)
2003 abort_remote(NULL);
2004 pswitch(!proxy);
2005 if (cpend) {
2006 if ((nfnd = empty(cin, NULL, 10)) <= 0) {
2007 if (nfnd < 0)
2008 warn("Error aborting proxy command");
2009 if (ptabflg)
2010 code = -1;
2011 lostpeer(0);
2012 }
2013 (void)getreply(0);
2014 (void)getreply(0);
2015 }
2016 if (proxy)
2017 pswitch(0);
2018 pswitch(1);
2019 if (ptabflg)
2020 code = -1;
2021 (void)xsignal(SIGINT, oldintr);
2022 }
2023
2024 void
reset(int argc,char * argv[])2025 reset(int argc, char *argv[])
2026 {
2027 int nfnd = 1;
2028
2029 if (argc == 0 && argv != NULL) {
2030 UPRINTF("usage: %s\n", argv[0]);
2031 code = -1;
2032 return;
2033 }
2034 while (nfnd > 0) {
2035 if ((nfnd = empty(cin, NULL, 0)) < 0) {
2036 warn("Error resetting connection");
2037 code = -1;
2038 lostpeer(0);
2039 } else if (nfnd)
2040 (void)getreply(0);
2041 }
2042 }
2043
2044 char *
gunique(const char * local)2045 gunique(const char *local)
2046 {
2047 static char new[MAXPATHLEN];
2048 char *cp = strrchr(local, '/');
2049 int d, count=0, len;
2050 char ext = '1';
2051
2052 if (cp)
2053 *cp = '\0';
2054 d = access(cp == local ? "/" : cp ? local : ".", W_OK);
2055 if (cp)
2056 *cp = '/';
2057 if (d < 0) {
2058 warn("Can't access `%s'", local);
2059 return (NULL);
2060 }
2061 len = strlcpy(new, local, sizeof(new));
2062 cp = &new[len];
2063 *cp++ = '.';
2064 while (!d) {
2065 if (++count == 100) {
2066 fputs("runique: can't find unique file name.\n",
2067 ttyout);
2068 return (NULL);
2069 }
2070 *cp++ = ext;
2071 *cp = '\0';
2072 if (ext == '9')
2073 ext = '0';
2074 else
2075 ext++;
2076 if ((d = access(new, F_OK)) < 0)
2077 break;
2078 if (ext != '0')
2079 cp--;
2080 else if (*(cp - 2) == '.')
2081 *(cp - 1) = '1';
2082 else {
2083 *(cp - 2) = *(cp - 2) + 1;
2084 cp--;
2085 }
2086 }
2087 return (new);
2088 }
2089
2090 /*
2091 * abort_squared --
2092 * aborts abort_remote(). lostpeer() is called because if the user is
2093 * too impatient to wait or there's another problem then ftp really
2094 * needs to get back to a known state.
2095 */
2096 static void
abort_squared(int signo)2097 abort_squared(int signo)
2098 {
2099 char msgbuf[100];
2100 size_t len;
2101
2102 sigint_raised = 1;
2103 alarmtimer(0);
2104 len = strlcpy(msgbuf, "\nremote abort aborted; closing connection.\n",
2105 sizeof(msgbuf));
2106 write(fileno(ttyout), msgbuf, len);
2107 lostpeer(signo);
2108 siglongjmp(xferabort, 1);
2109 }
2110
2111 void
abort_remote(FILE * din)2112 abort_remote(FILE *din)
2113 {
2114 unsigned char buf[BUFSIZ];
2115 int nfnd;
2116
2117 if (cout == NULL) {
2118 warnx("Lost control connection for abort");
2119 if (ptabflg)
2120 code = -1;
2121 lostpeer(0);
2122 return;
2123 }
2124 /*
2125 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
2126 * after urgent byte rather than before as is protocol now
2127 */
2128 buf[0] = IAC;
2129 buf[1] = IP;
2130 buf[2] = IAC;
2131 if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
2132 warn("Can't send abort message");
2133 fprintf(cout, "%cABOR\r\n", DM);
2134 (void)fflush(cout);
2135 if ((nfnd = empty(cin, din, 10)) <= 0) {
2136 if (nfnd < 0)
2137 warn("Can't send abort message");
2138 if (ptabflg)
2139 code = -1;
2140 lostpeer(0);
2141 }
2142 if (din && (nfnd & 2)) {
2143 while (read(fileno(din), buf, BUFSIZ) > 0)
2144 continue;
2145 }
2146 if (getreply(0) == ERROR && code == 552) {
2147 /* 552 needed for nic style abort */
2148 (void)getreply(0);
2149 }
2150 (void)getreply(0);
2151 }
2152
2153 /*
2154 * Ensure that ai->ai_addr is NOT an IPv4 mapped address.
2155 * IPv4 mapped address complicates too many things in FTP
2156 * protocol handling, as FTP protocol is defined differently
2157 * between IPv4 and IPv6.
2158 *
2159 * This may not be the best way to handle this situation,
2160 * since the semantics of IPv4 mapped address is defined in
2161 * the kernel. There are configurations where we should use
2162 * IPv4 mapped address as native IPv6 address, not as
2163 * "an IPv6 address that embeds IPv4 address" (namely, SIIT).
2164 *
2165 * More complete solution would be to have an additional
2166 * getsockopt to grab "real" peername/sockname. "real"
2167 * peername/sockname will be AF_INET if IPv4 mapped address
2168 * is used to embed IPv4 address, and will be AF_INET6 if
2169 * we use it as native. What a mess!
2170 */
2171 void
ai_unmapped(struct addrinfo * ai)2172 ai_unmapped(struct addrinfo *ai)
2173 {
2174 #ifdef INET6
2175 struct sockaddr_in6 *sin6;
2176 struct sockaddr_in sin;
2177 socklen_t len;
2178
2179 if (ai->ai_family != AF_INET6)
2180 return;
2181 if (ai->ai_addrlen != sizeof(struct sockaddr_in6) ||
2182 sizeof(sin) > ai->ai_addrlen)
2183 return;
2184 sin6 = (struct sockaddr_in6 *)ai->ai_addr;
2185 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
2186 return;
2187
2188 memset(&sin, 0, sizeof(sin));
2189 sin.sin_family = AF_INET;
2190 len = sizeof(struct sockaddr_in);
2191 memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
2192 sizeof(sin.sin_addr));
2193 sin.sin_port = sin6->sin6_port;
2194
2195 ai->ai_family = AF_INET;
2196 #if defined(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN)
2197 sin.sin_len = len;
2198 #endif
2199 memcpy(ai->ai_addr, &sin, len);
2200 ai->ai_addrlen = len;
2201 #endif
2202 }
2203
2204 #ifdef NO_USAGE
2205 void
xusage(void)2206 xusage(void)
2207 {
2208 fputs("Usage error\n", ttyout);
2209 }
2210 #endif
2211