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