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