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