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