ftp.c revision 1.112 1 /* $NetBSD: ftp.c,v 1.112 2000/11/24 13:01:24 itojun Exp $ */
2
3 /*-
4 * Copyright (c) 1996-2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Luke Mewburn.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Copyright (c) 1985, 1989, 1993, 1994
41 * The Regents of the University of California. All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 */
71
72 /*
73 * Copyright (C) 1997 and 1998 WIDE Project.
74 * All rights reserved.
75 *
76 * Redistribution and use in source and binary forms, with or without
77 * modification, are permitted provided that the following conditions
78 * are met:
79 * 1. Redistributions of source code must retain the above copyright
80 * notice, this list of conditions and the following disclaimer.
81 * 2. Redistributions in binary form must reproduce the above copyright
82 * notice, this list of conditions and the following disclaimer in the
83 * documentation and/or other materials provided with the distribution.
84 * 3. Neither the name of the project nor the names of its contributors
85 * may be used to endorse or promote products derived from this software
86 * without specific prior written permission.
87 *
88 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
89 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
90 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
91 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
92 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
93 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
94 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
95 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
96 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
97 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
98 * SUCH DAMAGE.
99 */
100
101 #include <sys/cdefs.h>
102 #ifndef lint
103 #if 0
104 static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94";
105 #else
106 __RCSID("$NetBSD: ftp.c,v 1.112 2000/11/24 13:01:24 itojun 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 = AF_UNSPEC;
184 hints.ai_socktype = SOCK_STREAM;
185 hints.ai_protocol = 0;
186 error = getaddrinfo(host, NULL, &hints, &res0);
187 if (error) {
188 warnx("%s", gai_strerror(error));
189 code = -1;
190 return (0);
191 }
192
193 if (res0->ai_canonname)
194 (void)strlcpy(hostnamebuf, res0->ai_canonname,
195 sizeof(hostnamebuf));
196 else
197 (void)strlcpy(hostnamebuf, host, sizeof(hostnamebuf));
198 hostname = hostnamebuf;
199
200 for (res = res0; res; res = res->ai_next) {
201 /*
202 * make sure that ai_addr is NOT an IPv4 mapped address.
203 * IPv4 mapped address complicates too many things in FTP
204 * protocol handling, as FTP protocol is defined differently
205 * between IPv4 and IPv6.
206 *
207 * This may not be the best way to handle this situation,
208 * since the semantics of IPv4 mapped address is defined in
209 * the kernel. There are configurations where we should use
210 * IPv4 mapped address as native IPv6 address, not as
211 * "an IPv6 address that embeds IPv4 address" (namely, SIIT).
212 *
213 * More complete solution would be to have an additional
214 * getsockopt to grab "real" peername/sockname. "real"
215 * peername/sockname will be AF_INET if IPv4 mapped address
216 * is used to embed IPv4 address, and will be AF_INET6 if
217 * we use it as native. What a mess!
218 */
219 ai_unmapped(res);
220 #if 0 /*old behavior*/
221 if (res != res0) /* not on the first address */
222 #else
223 if (res0->ai_next) /* if we have multiple possibilities */
224 #endif
225 {
226 if (getnameinfo(res->ai_addr, res->ai_addrlen,
227 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
228 strlcpy(hbuf, "?", sizeof(hbuf));
229 fprintf(ttyout, "Trying %s...\n", hbuf);
230 }
231 ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(portnum);
232 s = socket(res->ai_family, SOCK_STREAM, res->ai_protocol);
233 if (s < 0) {
234 cause = "socket";
235 continue;
236 }
237 while ((error = xconnect(s, res->ai_addr, res->ai_addrlen)) < 0
238 && errno == EINTR) {
239 ;
240 }
241 if (error) {
242 /* this "if" clause is to prevent print warning twice */
243 if (res->ai_next) {
244 if (getnameinfo(res->ai_addr, res->ai_addrlen,
245 hbuf, sizeof(hbuf), NULL, 0,
246 NI_NUMERICHOST))
247 strlcpy(hbuf, "?", sizeof(hbuf));
248 warn("connect to address %s", hbuf);
249 }
250 cause = "connect";
251 close(s);
252 s = -1;
253 continue;
254 }
255
256 /* finally we got one */
257 break;
258 }
259 if (s < 0) {
260 warn("%s", cause);
261 code = -1;
262 freeaddrinfo(res0);
263 return 0;
264 }
265 memcpy(&hisctladdr.si_su, res->ai_addr, res->ai_addrlen);
266 hisctladdr.su_len = res->ai_addrlen;
267 freeaddrinfo(res0);
268 res0 = res = NULL;
269
270 len = hisctladdr.su_len;
271 if (getsockname(s, (struct sockaddr *)&myctladdr.si_su, &len) < 0) {
272 warn("getsockname");
273 code = -1;
274 goto bad;
275 }
276 myctladdr.su_len = len;
277
278 #ifdef IPTOS_LOWDELAY
279 if (hisctladdr.su_family == AF_INET) {
280 int tos = IPTOS_LOWDELAY;
281 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
282 sizeof(int)) < 0)
283 warn("setsockopt TOS (ignored)");
284 }
285 #endif
286 cin = fdopen(s, "r");
287 cout = fdopen(s, "w");
288 if (cin == NULL || cout == NULL) {
289 warnx("fdopen failed.");
290 if (cin)
291 (void)fclose(cin);
292 if (cout)
293 (void)fclose(cout);
294 code = -1;
295 goto bad;
296 }
297 if (verbose)
298 fprintf(ttyout, "Connected to %s.\n", hostname);
299 if (getreply(0) > 2) { /* read startup message from server */
300 if (cin)
301 (void)fclose(cin);
302 if (cout)
303 (void)fclose(cout);
304 code = -1;
305 goto bad;
306 }
307 {
308 int on = 1;
309
310 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
311 < 0 && debug) {
312 warn("setsockopt");
313 }
314 }
315
316 return (hostname);
317 bad:
318 (void)close(s);
319 return (NULL);
320 }
321
322 void
323 cmdabort(int notused)
324 {
325 int oerrno = errno;
326
327 alarmtimer(0);
328 if (fromatty)
329 write(fileno(ttyout), "\n", 1);
330 abrtflag++;
331 if (ptflag)
332 siglongjmp(ptabort, 1);
333 errno = oerrno;
334 }
335
336 void
337 cmdtimeout(int notused)
338 {
339 int oerrno = errno;
340
341 alarmtimer(0);
342 if (fromatty)
343 write(fileno(ttyout), "\n", 1);
344 timeoutflag++;
345 if (ptflag)
346 siglongjmp(ptabort, 1);
347 errno = oerrno;
348 }
349
350 /*VARARGS*/
351 int
352 command(const char *fmt, ...)
353 {
354 va_list ap;
355 int r;
356 sigfunc oldsigint;
357
358 if (debug) {
359 fputs("---> ", ttyout);
360 va_start(ap, fmt);
361 if (strncmp("PASS ", fmt, 5) == 0)
362 fputs("PASS XXXX", ttyout);
363 else if (strncmp("ACCT ", fmt, 5) == 0)
364 fputs("ACCT XXXX", ttyout);
365 else
366 vfprintf(ttyout, fmt, ap);
367 va_end(ap);
368 putc('\n', ttyout);
369 }
370 if (cout == NULL) {
371 warnx("No control connection for command.");
372 code = -1;
373 return (0);
374 }
375
376 abrtflag = 0;
377
378 oldsigint = xsignal(SIGINT, cmdabort);
379
380 va_start(ap, fmt);
381 vfprintf(cout, fmt, ap);
382 va_end(ap);
383 fputs("\r\n", cout);
384 (void)fflush(cout);
385 cpend = 1;
386 r = getreply(!strcmp(fmt, "QUIT"));
387 if (abrtflag && oldsigint != SIG_IGN)
388 (*oldsigint)(SIGINT);
389 (void)xsignal(SIGINT, oldsigint);
390 return (r);
391 }
392
393 int
394 getreply(int expecteof)
395 {
396 char current_line[BUFSIZ]; /* last line of previous reply */
397 int c, n, line;
398 int dig;
399 int originalcode = 0, continuation = 0;
400 sigfunc oldsigint, oldsigalrm;
401 int pflag = 0;
402 char *cp, *pt = pasv;
403
404 abrtflag = 0;
405 timeoutflag = 0;
406
407 oldsigint = xsignal(SIGINT, cmdabort);
408 oldsigalrm = xsignal(SIGALRM, cmdtimeout);
409
410 for (line = 0 ;; line++) {
411 dig = n = code = 0;
412 cp = current_line;
413 while (alarmtimer(60),((c = getc(cin)) != '\n')) {
414 if (c == IAC) { /* handle telnet commands */
415 switch (c = getc(cin)) {
416 case WILL:
417 case WONT:
418 c = getc(cin);
419 fprintf(cout, "%c%c%c", IAC, DONT, c);
420 (void)fflush(cout);
421 break;
422 case DO:
423 case DONT:
424 c = getc(cin);
425 fprintf(cout, "%c%c%c", IAC, WONT, c);
426 (void)fflush(cout);
427 break;
428 default:
429 break;
430 }
431 continue;
432 }
433 dig++;
434 if (c == EOF) {
435 /*
436 * these will get trashed by pswitch()
437 * in lostpeer()
438 */
439 int reply_timeoutflag = timeoutflag;
440 int reply_abrtflag = abrtflag;
441
442 alarmtimer(0);
443 if (expecteof && feof(cin)) {
444 (void)xsignal(SIGINT, oldsigint);
445 (void)xsignal(SIGALRM, oldsigalrm);
446 code = 221;
447 return (0);
448 }
449 cpend = 0;
450 lostpeer(0);
451 if (verbose) {
452 if (reply_timeoutflag)
453 fputs(
454 "421 Service not available, remote server timed out. Connection closed\n",
455 ttyout);
456 else if (reply_abrtflag)
457 fputs(
458 "421 Service not available, user interrupt. Connection closed.\n",
459 ttyout);
460 else
461 fputs(
462 "421 Service not available, remote server has closed connection.\n",
463 ttyout);
464 (void)fflush(ttyout);
465 }
466 code = 421;
467 (void)xsignal(SIGINT, oldsigint);
468 (void)xsignal(SIGALRM, oldsigalrm);
469 return (4);
470 }
471 if (c != '\r' && (verbose > 0 ||
472 ((verbose > -1 && n == '5' && dig > 4) &&
473 (((!n && c < '5') || (n && n < '5'))
474 || !retry_connect)))) {
475 if (proxflag &&
476 (dig == 1 || (dig == 5 && verbose == 0)))
477 fprintf(ttyout, "%s:", hostname);
478 (void)putc(c, ttyout);
479 }
480 if (dig < 4 && isdigit(c))
481 code = code * 10 + (c - '0');
482 if (!pflag && (code == 227 || code == 228))
483 pflag = 1;
484 else if (!pflag && code == 229)
485 pflag = 100;
486 if (dig > 4 && pflag == 1 && isdigit(c))
487 pflag = 2;
488 if (pflag == 2) {
489 if (c != '\r' && c != ')')
490 *pt++ = c;
491 else {
492 *pt = '\0';
493 pflag = 3;
494 }
495 }
496 if (pflag == 100 && c == '(')
497 pflag = 2;
498 if (dig == 4 && c == '-') {
499 if (continuation)
500 code = 0;
501 continuation++;
502 }
503 if (n == 0)
504 n = c;
505 if (cp < ¤t_line[sizeof(current_line) - 1])
506 *cp++ = c;
507 }
508 if (verbose > 0 || ((verbose > -1 && n == '5') &&
509 (n < '5' || !retry_connect))) {
510 (void)putc(c, ttyout);
511 (void)fflush (ttyout);
512 }
513 if (cp[-1] == '\r')
514 cp[-1] = '\0';
515 *cp = '\0';
516 if (line == 0)
517 (void)strlcpy(reply_string, current_line,
518 sizeof(reply_string));
519 if (line > 0 && code == 0 && reply_callback != NULL)
520 (*reply_callback)(current_line);
521 if (continuation && code != originalcode) {
522 if (originalcode == 0)
523 originalcode = code;
524 continue;
525 }
526 if (n != '1')
527 cpend = 0;
528 alarmtimer(0);
529 (void)xsignal(SIGINT, oldsigint);
530 (void)xsignal(SIGALRM, oldsigalrm);
531 if (code == 421 || originalcode == 421)
532 lostpeer(0);
533 if (abrtflag && oldsigint != cmdabort && oldsigint != SIG_IGN)
534 (*oldsigint)(SIGINT);
535 if (timeoutflag && oldsigalrm != cmdtimeout &&
536 oldsigalrm != SIG_IGN)
537 (*oldsigalrm)(SIGINT);
538 return (n - '0');
539 }
540 }
541
542 static int
543 empty(FILE *cin, FILE *din, int sec)
544 {
545 int nr;
546 int nfd = 0;
547
548 #ifdef USE_SELECT
549 struct timeval t;
550 fd_set rmask;
551
552 FD_ZERO(&rmask);
553 if (cin) {
554 if (nfd < fileno(cin))
555 nfd = fileno(cin);
556 FD_SET(fileno(cin), &rmask);
557 }
558 if (din) {
559 if (nfd < fileno(din))
560 nfd = fileno(din);
561 FD_SET(fileno(din), &rmask);
562 }
563
564 t.tv_sec = (long) sec;
565 t.tv_usec = 0;
566 if ((nr = select(nfd, &rmask, NULL, NULL, &t)) <= 0)
567 return nr;
568
569 nr = 0;
570 if (cin)
571 nr |= FD_ISSET(fileno(cin), &rmask) ? 1 : 0;
572 if (din)
573 nr |= FD_ISSET(fileno(din), &rmask) ? 2 : 0;
574
575 #else
576 struct pollfd pfd[2];
577
578 if (cin) {
579 pfd[nfd].fd = fileno(cin);
580 pfd[nfd++].events = POLLIN;
581 }
582
583 if (din) {
584 pfd[nfd].fd = fileno(din);
585 pfd[nfd++].events = POLLIN;
586 }
587
588 if ((nr = poll(pfd, nfd, sec * 1000)) <= 0)
589 return nr;
590
591 nr = 0;
592 nfd = 0;
593 if (cin)
594 nr |= (pfd[nfd++].revents & POLLIN) ? 1 : 0;
595 if (din)
596 nr |= (pfd[nfd++].revents & POLLIN) ? 2 : 0;
597 #endif
598 return nr;
599 }
600
601 sigjmp_buf xferabort;
602
603 void
604 abortxfer(int notused)
605 {
606 char msgbuf[100];
607 int len;
608
609 alarmtimer(0);
610 mflag = 0;
611 abrtflag = 0;
612 switch (direction[0]) {
613 case 'r':
614 strlcpy(msgbuf, "\nreceive", sizeof(msgbuf));
615 break;
616 case 's':
617 strlcpy(msgbuf, "\nsend", sizeof(msgbuf));
618 break;
619 default:
620 errx(1, "abortxfer called with unknown direction `%s'",
621 direction);
622 }
623 len = strlcat(msgbuf, " aborted. Waiting for remote to finish abort.\n",
624 sizeof(msgbuf));
625 write(fileno(ttyout), msgbuf, len);
626 siglongjmp(xferabort, 1);
627 }
628
629 void
630 sendrequest(const char *cmd, const char *local, const char *remote,
631 int printnames)
632 {
633 struct stat st;
634 int c, d;
635 FILE *fin, *dout;
636 int (*closefunc)(FILE *);
637 sigfunc oldintr, oldintp;
638 volatile off_t hashbytes;
639 char *lmode, *bufp;
640 static size_t bufsize;
641 static char *buf;
642 int oprogress;
643
644 #ifdef __GNUC__ /* to shut up gcc warnings */
645 (void)&fin;
646 (void)&dout;
647 (void)&closefunc;
648 (void)&oldintr;
649 (void)&oldintp;
650 (void)&lmode;
651 #endif
652
653 hashbytes = mark;
654 direction = "sent";
655 dout = NULL;
656 bytes = 0;
657 filesize = -1;
658 oprogress = progress;
659 if (verbose && printnames) {
660 if (local && *local != '-')
661 fprintf(ttyout, "local: %s ", local);
662 if (remote)
663 fprintf(ttyout, "remote: %s\n", remote);
664 }
665 if (proxy) {
666 proxtrans(cmd, local, remote);
667 return;
668 }
669 if (curtype != type)
670 changetype(type, 0);
671 closefunc = NULL;
672 oldintr = NULL;
673 oldintp = NULL;
674 lmode = "w";
675 if (sigsetjmp(xferabort, 1)) {
676 while (cpend)
677 (void)getreply(0);
678 code = -1;
679 goto cleanupsend;
680 }
681 (void)xsignal(SIGQUIT, psummary);
682 oldintr = xsignal(SIGINT, abortxfer);
683 if (strcmp(local, "-") == 0) {
684 fin = stdin;
685 progress = 0;
686 } else if (*local == '|') {
687 oldintp = xsignal(SIGPIPE, SIG_IGN);
688 fin = popen(local + 1, "r");
689 if (fin == NULL) {
690 warn("%s", local + 1);
691 code = -1;
692 goto cleanupsend;
693 }
694 progress = 0;
695 closefunc = pclose;
696 } else {
697 fin = fopen(local, "r");
698 if (fin == NULL) {
699 warn("local: %s", local);
700 code = -1;
701 goto cleanupsend;
702 }
703 closefunc = fclose;
704 if (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) {
705 fprintf(ttyout, "%s: not a plain file.\n", local);
706 code = -1;
707 goto cleanupsend;
708 }
709 filesize = st.st_size;
710 }
711 if (initconn()) {
712 code = -1;
713 goto cleanupsend;
714 }
715 if (sigsetjmp(xferabort, 1))
716 goto abort;
717
718 if (restart_point &&
719 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
720 int rc;
721
722 rc = -1;
723 switch (curtype) {
724 case TYPE_A:
725 rc = fseek(fin, (long) restart_point, SEEK_SET);
726 break;
727 case TYPE_I:
728 case TYPE_L:
729 rc = lseek(fileno(fin), restart_point, SEEK_SET);
730 break;
731 }
732 if (rc < 0) {
733 warn("local: %s", local);
734 goto cleanupsend;
735 }
736 if (command("REST " LLF, (LLT)restart_point) != CONTINUE)
737 goto cleanupsend;
738 lmode = "r+w";
739 }
740 if (remote) {
741 if (command("%s %s", cmd, remote) != PRELIM)
742 goto cleanupsend;
743 } else {
744 if (command("%s", cmd) != PRELIM)
745 goto cleanupsend;
746 }
747 dout = dataconn(lmode);
748 if (dout == NULL)
749 goto abort;
750
751 if (sndbuf_size > bufsize) {
752 if (buf)
753 (void)free(buf);
754 bufsize = sndbuf_size;
755 buf = xmalloc(bufsize);
756 }
757
758 progressmeter(-1);
759 oldintp = xsignal(SIGPIPE, SIG_IGN);
760
761 switch (curtype) {
762
763 case TYPE_I:
764 case TYPE_L:
765 if (rate_put) { /* rate limited */
766 while (1) {
767 struct timeval then, now, td;
768 off_t bufrem;
769
770 (void)gettimeofday(&then, NULL);
771 errno = c = d = 0;
772 bufrem = rate_put;
773 while (bufrem > 0) {
774 if ((c = read(fileno(fin), buf,
775 MIN(bufsize, bufrem))) <= 0)
776 goto senddone;
777 bytes += c;
778 bufrem -= c;
779 for (bufp = buf; c > 0;
780 c -= d, bufp += d)
781 if ((d = write(fileno(dout),
782 bufp, c)) <= 0)
783 break;
784 if (d < 0)
785 goto senddone;
786 if (hash &&
787 (!progress || filesize < 0) ) {
788 while (bytes >= hashbytes) {
789 (void)putc('#', ttyout);
790 hashbytes += mark;
791 }
792 (void)fflush(ttyout);
793 }
794 }
795 while (1) {
796 (void)gettimeofday(&now, NULL);
797 timersub(&now, &then, &td);
798 if (td.tv_sec > 0)
799 break;
800 usleep(1000000 - td.tv_usec);
801 }
802 }
803 } else { /* simpler/faster; no rate limit */
804 while (1) {
805 errno = c = d = 0;
806 if ((c = read(fileno(fin), buf, bufsize)) <= 0)
807 goto senddone;
808 bytes += c;
809 for (bufp = buf; c > 0; c -= d, bufp += d)
810 if ((d = write(fileno(dout), bufp, c))
811 <= 0)
812 break;
813 if (d < 0)
814 goto senddone;
815 if (hash && (!progress || filesize < 0) ) {
816 while (bytes >= hashbytes) {
817 (void)putc('#', ttyout);
818 hashbytes += mark;
819 }
820 (void)fflush(ttyout);
821 }
822 }
823 }
824 senddone:
825 if (hash && (!progress || filesize < 0) && bytes > 0) {
826 if (bytes < mark)
827 (void)putc('#', ttyout);
828 (void)putc('\n', ttyout);
829 }
830 if (c < 0)
831 warn("local: %s", local);
832 if (d < 0) {
833 if (errno != EPIPE)
834 warn("netout");
835 bytes = -1;
836 }
837 break;
838
839 case TYPE_A:
840 while ((c = getc(fin)) != EOF) {
841 if (c == '\n') {
842 while (hash && (!progress || filesize < 0) &&
843 (bytes >= hashbytes)) {
844 (void)putc('#', ttyout);
845 (void)fflush(ttyout);
846 hashbytes += mark;
847 }
848 if (ferror(dout))
849 break;
850 (void)putc('\r', dout);
851 bytes++;
852 }
853 (void)putc(c, dout);
854 bytes++;
855 #if 0 /* this violates RFC */
856 if (c == '\r') {
857 (void)putc('\0', dout);
858 bytes++;
859 }
860 #endif
861 }
862 if (hash && (!progress || filesize < 0)) {
863 if (bytes < hashbytes)
864 (void)putc('#', ttyout);
865 (void)putc('\n', ttyout);
866 }
867 if (ferror(fin))
868 warn("local: %s", local);
869 if (ferror(dout)) {
870 if (errno != EPIPE)
871 warn("netout");
872 bytes = -1;
873 }
874 break;
875 }
876
877 progressmeter(1);
878 if (closefunc != NULL) {
879 (*closefunc)(fin);
880 fin = NULL;
881 }
882 (void)fclose(dout);
883 dout = NULL;
884 (void)getreply(0);
885 if (bytes > 0)
886 ptransfer(0);
887 goto cleanupsend;
888
889 abort:
890 (void)xsignal(SIGINT, oldintr);
891 oldintr = NULL;
892 if (!cpend) {
893 code = -1;
894 goto cleanupsend;
895 }
896 if (data >= 0) {
897 (void)close(data);
898 data = -1;
899 }
900 if (dout) {
901 (void)fclose(dout);
902 dout = NULL;
903 }
904 (void)getreply(0);
905 code = -1;
906 if (bytes > 0)
907 ptransfer(0);
908
909 cleanupsend:
910 if (oldintr)
911 (void)xsignal(SIGINT, oldintr);
912 if (oldintp)
913 (void)xsignal(SIGPIPE, oldintp);
914 if (data >= 0) {
915 (void)close(data);
916 data = -1;
917 }
918 if (closefunc != NULL && fin != NULL)
919 (*closefunc)(fin);
920 if (dout)
921 (void)fclose(dout);
922 progress = oprogress;
923 restart_point = 0;
924 bytes = 0;
925 }
926
927 void
928 recvrequest(const char *cmd, const char *local, const char *remote,
929 const char *lmode, int printnames, int ignorespecial)
930 {
931 FILE *fout, *din;
932 int (*closefunc)(FILE *);
933 sigfunc oldintr, oldintp;
934 int c, d;
935 volatile int is_retr, tcrflag, bare_lfs;
936 static size_t bufsize;
937 static char *buf;
938 volatile off_t hashbytes;
939 struct stat st;
940 time_t mtime;
941 struct timeval tval[2];
942 int oprogress;
943 int opreserve;
944
945 #ifdef __GNUC__ /* to shut up gcc warnings */
946 (void)&local;
947 (void)&fout;
948 (void)&din;
949 (void)&closefunc;
950 (void)&oldintr;
951 (void)&oldintp;
952 #endif
953
954 fout = NULL;
955 din = NULL;
956 hashbytes = mark;
957 direction = "received";
958 bytes = 0;
959 bare_lfs = 0;
960 filesize = -1;
961 oprogress = progress;
962 opreserve = preserve;
963 is_retr = (strcmp(cmd, "RETR") == 0);
964 if (is_retr && verbose && printnames) {
965 if (local && (ignorespecial || *local != '-'))
966 fprintf(ttyout, "local: %s ", local);
967 if (remote)
968 fprintf(ttyout, "remote: %s\n", remote);
969 }
970 if (proxy && is_retr) {
971 proxtrans(cmd, local, remote);
972 return;
973 }
974 closefunc = NULL;
975 oldintr = NULL;
976 oldintp = NULL;
977 tcrflag = !crflag && is_retr;
978 if (sigsetjmp(xferabort, 1)) {
979 while (cpend)
980 (void)getreply(0);
981 code = -1;
982 goto cleanuprecv;
983 }
984 (void)xsignal(SIGQUIT, psummary);
985 oldintr = xsignal(SIGINT, abortxfer);
986 if (ignorespecial || (strcmp(local, "-") && *local != '|')) {
987 if (access(local, W_OK) < 0) {
988 char *dir = strrchr(local, '/');
989
990 if (errno != ENOENT && errno != EACCES) {
991 warn("local: %s", local);
992 code = -1;
993 goto cleanuprecv;
994 }
995 if (dir != NULL)
996 *dir = 0;
997 d = access(dir == local ? "/" :
998 dir ? local : ".", W_OK);
999 if (dir != NULL)
1000 *dir = '/';
1001 if (d < 0) {
1002 warn("local: %s", local);
1003 code = -1;
1004 goto cleanuprecv;
1005 }
1006 if (!runique && errno == EACCES &&
1007 chmod(local, (S_IRUSR|S_IWUSR)) < 0) {
1008 warn("local: %s", local);
1009 code = -1;
1010 goto cleanuprecv;
1011 }
1012 if (runique && errno == EACCES &&
1013 (local = gunique(local)) == NULL) {
1014 code = -1;
1015 goto cleanuprecv;
1016 }
1017 }
1018 else if (runique && (local = gunique(local)) == NULL) {
1019 code = -1;
1020 goto cleanuprecv;
1021 }
1022 }
1023 if (!is_retr) {
1024 if (curtype != TYPE_A)
1025 changetype(TYPE_A, 0);
1026 } else {
1027 if (curtype != type)
1028 changetype(type, 0);
1029 filesize = remotesize(remote, 0);
1030 if (code == 421 || code == -1)
1031 goto cleanuprecv;
1032 }
1033 if (initconn()) {
1034 code = -1;
1035 goto cleanuprecv;
1036 }
1037 if (sigsetjmp(xferabort, 1))
1038 goto abort;
1039 if (is_retr && restart_point &&
1040 command("REST " LLF, (LLT) restart_point) != CONTINUE)
1041 goto cleanuprecv;
1042 if (! EMPTYSTRING(remote)) {
1043 if (command("%s %s", cmd, remote) != PRELIM)
1044 goto cleanuprecv;
1045 } else {
1046 if (command("%s", cmd) != PRELIM)
1047 goto cleanuprecv;
1048 }
1049 din = dataconn("r");
1050 if (din == NULL)
1051 goto abort;
1052 if (!ignorespecial && strcmp(local, "-") == 0) {
1053 fout = stdout;
1054 progress = 0;
1055 preserve = 0;
1056 } else if (!ignorespecial && *local == '|') {
1057 oldintp = xsignal(SIGPIPE, SIG_IGN);
1058 fout = popen(local + 1, "w");
1059 if (fout == NULL) {
1060 warn("%s", local+1);
1061 goto abort;
1062 }
1063 progress = 0;
1064 preserve = 0;
1065 closefunc = pclose;
1066 } else {
1067 fout = fopen(local, lmode);
1068 if (fout == NULL) {
1069 warn("local: %s", local);
1070 goto abort;
1071 }
1072 closefunc = fclose;
1073 }
1074
1075 if (fstat(fileno(fout), &st) != -1 && !S_ISREG(st.st_mode)) {
1076 progress = 0;
1077 preserve = 0;
1078 }
1079 if (rcvbuf_size > bufsize) {
1080 if (buf)
1081 (void)free(buf);
1082 bufsize = rcvbuf_size;
1083 buf = xmalloc(bufsize);
1084 }
1085
1086 progressmeter(-1);
1087
1088 switch (curtype) {
1089
1090 case TYPE_I:
1091 case TYPE_L:
1092 if (is_retr && restart_point &&
1093 lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
1094 warn("local: %s", local);
1095 goto cleanuprecv;
1096 }
1097 if (rate_get) { /* rate limiting */
1098 while (1) {
1099 struct timeval then, now, td;
1100 off_t bufrem;
1101
1102 (void)gettimeofday(&then, NULL);
1103 errno = c = d = 0;
1104 for (bufrem = rate_get; bufrem > 0; ) {
1105 if ((c = read(fileno(din), buf,
1106 MIN(bufsize, bufrem))) <= 0)
1107 goto recvdone;
1108 bytes += c;
1109 bufrem -=c;
1110 if ((d = write(fileno(fout), buf, c))
1111 != c)
1112 goto recvdone;
1113 if (hash &&
1114 (!progress || filesize < 0)) {
1115 while (bytes >= hashbytes) {
1116 (void)putc('#', ttyout);
1117 hashbytes += mark;
1118 }
1119 (void)fflush(ttyout);
1120 }
1121 }
1122 /* sleep until time is up */
1123 while (1) {
1124 (void)gettimeofday(&now, NULL);
1125 timersub(&now, &then, &td);
1126 if (td.tv_sec > 0)
1127 break;
1128 usleep(1000000 - td.tv_usec);
1129 }
1130 }
1131 } else { /* faster code (no limiting) */
1132 while (1) {
1133 errno = c = d = 0;
1134 if ((c = read(fileno(din), buf, bufsize)) <= 0)
1135 goto recvdone;
1136 bytes += c;
1137 if ((d = write(fileno(fout), buf, c)) != c)
1138 goto recvdone;
1139 if (hash && (!progress || filesize < 0)) {
1140 while (bytes >= hashbytes) {
1141 (void)putc('#', ttyout);
1142 hashbytes += mark;
1143 }
1144 (void)fflush(ttyout);
1145 }
1146 }
1147 }
1148 recvdone:
1149 if (hash && (!progress || filesize < 0) && bytes > 0) {
1150 if (bytes < mark)
1151 (void)putc('#', ttyout);
1152 (void)putc('\n', ttyout);
1153 }
1154 if (c < 0) {
1155 if (errno != EPIPE)
1156 warn("netin");
1157 bytes = -1;
1158 }
1159 if (d < c) {
1160 if (d < 0)
1161 warn("local: %s", local);
1162 else
1163 warnx("%s: short write", local);
1164 }
1165 break;
1166
1167 case TYPE_A:
1168 if (is_retr && restart_point) {
1169 int ch;
1170 long i, n;
1171
1172 if (fseek(fout, 0L, SEEK_SET) < 0)
1173 goto done;
1174 n = (long)restart_point;
1175 for (i = 0; i++ < n;) {
1176 if ((ch = getc(fout)) == EOF)
1177 goto done;
1178 if (ch == '\n')
1179 i++;
1180 }
1181 if (fseek(fout, 0L, 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 if (tmp.su_family == AF_INET6)
1631 tmp.si_su.su_sin6.sin6_scope_id = 0;
1632 if (getnameinfo((struct sockaddr *)&tmp.si_su,
1633 tmp.su_len, hname, sizeof(hname), sname,
1634 sizeof(sname), NI_NUMERICHOST | NI_NUMERICSERV)) {
1635 result = ERROR;
1636 } else {
1637 result = command("EPRT |%d|%s|%s|", af, hname,
1638 sname);
1639 if (!connected)
1640 return (1);
1641 if (result != COMPLETE) {
1642 epsv4bad = 1;
1643 if (debug)
1644 fputs(
1645 "disabling epsv4 for this connection\n",
1646 ttyout);
1647 }
1648 }
1649 break;
1650 default:
1651 result = COMPLETE + 1;
1652 break;
1653 }
1654 if (result == COMPLETE)
1655 goto skip_port;
1656
1657 switch (data_addr.su_family) {
1658 case AF_INET:
1659 a = (char *)&data_addr.si_su.su_sin.sin_addr;
1660 p = (char *)&data_addr.su_port;
1661 result = command("PORT %d,%d,%d,%d,%d,%d",
1662 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1663 UC(p[0]), UC(p[1]));
1664 break;
1665 #ifdef INET6
1666 case AF_INET6:
1667 a = (char *)&data_addr.si_su.su_sin6.sin6_addr;
1668 p = (char *)&data_addr.su_port;
1669 result = command(
1670 "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
1671 6, 16,
1672 UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
1673 UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
1674 UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
1675 UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
1676 2, UC(p[0]), UC(p[1]));
1677 break;
1678 #endif
1679 default:
1680 result = COMPLETE + 1; /* xxx */
1681 }
1682 if (!connected)
1683 return (1);
1684 skip_port:
1685
1686 if (result == ERROR && sendport == -1) {
1687 sendport = 0;
1688 tmpno = 1;
1689 goto noport;
1690 }
1691 return (result != COMPLETE);
1692 }
1693 if (tmpno)
1694 sendport = 1;
1695 #ifdef IPTOS_THROUGHPUT
1696 if (data_addr.su_family == AF_INET) {
1697 on = IPTOS_THROUGHPUT;
1698 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1699 sizeof(int)) < 0)
1700 warn("setsockopt TOS (ignored)");
1701 }
1702 #endif
1703 return (0);
1704 bad:
1705 (void)close(data), data = -1;
1706 if (tmpno)
1707 sendport = 1;
1708 return (1);
1709 }
1710
1711 FILE *
1712 dataconn(const char *lmode)
1713 {
1714 struct sockinet from;
1715 int s, fromlen = myctladdr.su_len;
1716
1717 if (passivemode)
1718 return (fdopen(data, lmode));
1719
1720 s = accept(data, (struct sockaddr *) &from.si_su, &fromlen);
1721 if (s < 0) {
1722 warn("accept");
1723 (void)close(data), data = -1;
1724 return (NULL);
1725 }
1726 (void)close(data);
1727 data = s;
1728 #ifdef IPTOS_THROUGHPUT
1729 if (from.su_family == AF_INET) {
1730 int tos = IPTOS_THROUGHPUT;
1731 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
1732 sizeof(int)) < 0) {
1733 warn("setsockopt TOS (ignored)");
1734 }
1735 }
1736 #endif
1737 return (fdopen(data, lmode));
1738 }
1739
1740 void
1741 psabort(int notused)
1742 {
1743 int oerrno = errno;
1744
1745 alarmtimer(0);
1746 abrtflag++;
1747 errno = oerrno;
1748 }
1749
1750 void
1751 pswitch(int flag)
1752 {
1753 sigfunc oldintr;
1754 static struct comvars {
1755 int connect;
1756 char name[MAXHOSTNAMELEN];
1757 struct sockinet mctl;
1758 struct sockinet hctl;
1759 FILE *in;
1760 FILE *out;
1761 int tpe;
1762 int curtpe;
1763 int cpnd;
1764 int sunqe;
1765 int runqe;
1766 int mcse;
1767 int ntflg;
1768 char nti[17];
1769 char nto[17];
1770 int mapflg;
1771 char mi[MAXPATHLEN];
1772 char mo[MAXPATHLEN];
1773 } proxstruct, tmpstruct;
1774 struct comvars *ip, *op;
1775
1776 abrtflag = 0;
1777 oldintr = xsignal(SIGINT, psabort);
1778 if (flag) {
1779 if (proxy)
1780 return;
1781 ip = &tmpstruct;
1782 op = &proxstruct;
1783 proxy++;
1784 } else {
1785 if (!proxy)
1786 return;
1787 ip = &proxstruct;
1788 op = &tmpstruct;
1789 proxy = 0;
1790 }
1791 ip->connect = connected;
1792 connected = op->connect;
1793 if (hostname)
1794 (void)strlcpy(ip->name, hostname, sizeof(ip->name));
1795 else
1796 ip->name[0] = '\0';
1797 hostname = op->name;
1798 ip->hctl = hisctladdr;
1799 hisctladdr = op->hctl;
1800 ip->mctl = myctladdr;
1801 myctladdr = op->mctl;
1802 ip->in = cin;
1803 cin = op->in;
1804 ip->out = cout;
1805 cout = op->out;
1806 ip->tpe = type;
1807 type = op->tpe;
1808 ip->curtpe = curtype;
1809 curtype = op->curtpe;
1810 ip->cpnd = cpend;
1811 cpend = op->cpnd;
1812 ip->sunqe = sunique;
1813 sunique = op->sunqe;
1814 ip->runqe = runique;
1815 runique = op->runqe;
1816 ip->mcse = mcase;
1817 mcase = op->mcse;
1818 ip->ntflg = ntflag;
1819 ntflag = op->ntflg;
1820 (void)strlcpy(ip->nti, ntin, sizeof(ip->nti));
1821 (void)strlcpy(ntin, op->nti, sizeof(ntin));
1822 (void)strlcpy(ip->nto, ntout, sizeof(ip->nto));
1823 (void)strlcpy(ntout, op->nto, sizeof(ntout));
1824 ip->mapflg = mapflag;
1825 mapflag = op->mapflg;
1826 (void)strlcpy(ip->mi, mapin, sizeof(ip->mi));
1827 (void)strlcpy(mapin, op->mi, sizeof(mapin));
1828 (void)strlcpy(ip->mo, mapout, sizeof(ip->mo));
1829 (void)strlcpy(mapout, op->mo, sizeof(mapout));
1830 (void)xsignal(SIGINT, oldintr);
1831 if (abrtflag) {
1832 abrtflag = 0;
1833 (*oldintr)(SIGINT);
1834 }
1835 }
1836
1837 void
1838 abortpt(int notused)
1839 {
1840
1841 alarmtimer(0);
1842 if (fromatty)
1843 write(fileno(ttyout), "\n", 1);
1844 ptabflg++;
1845 mflag = 0;
1846 abrtflag = 0;
1847 siglongjmp(ptabort, 1);
1848 }
1849
1850 void
1851 proxtrans(const char *cmd, const char *local, const char *remote)
1852 {
1853 sigfunc oldintr;
1854 int prox_type, nfnd;
1855 volatile int secndflag;
1856 char *cmd2;
1857
1858 #ifdef __GNUC__ /* to shut up gcc warnings */
1859 (void)&oldintr;
1860 (void)&cmd2;
1861 #endif
1862
1863 oldintr = NULL;
1864 secndflag = 0;
1865 if (strcmp(cmd, "RETR"))
1866 cmd2 = "RETR";
1867 else
1868 cmd2 = runique ? "STOU" : "STOR";
1869 if ((prox_type = type) == 0) {
1870 if (unix_server && unix_proxy)
1871 prox_type = TYPE_I;
1872 else
1873 prox_type = TYPE_A;
1874 }
1875 if (curtype != prox_type)
1876 changetype(prox_type, 1);
1877 if (command("PASV") != COMPLETE) {
1878 fputs("proxy server does not support third party transfers.\n",
1879 ttyout);
1880 return;
1881 }
1882 pswitch(0);
1883 if (!connected) {
1884 fputs("No primary connection.\n", ttyout);
1885 pswitch(1);
1886 code = -1;
1887 return;
1888 }
1889 if (curtype != prox_type)
1890 changetype(prox_type, 1);
1891 if (command("PORT %s", pasv) != COMPLETE) {
1892 pswitch(1);
1893 return;
1894 }
1895 if (sigsetjmp(ptabort, 1))
1896 goto abort;
1897 oldintr = xsignal(SIGINT, abortpt);
1898 if ((restart_point &&
1899 (command("REST " LLF, (LLT) restart_point) != CONTINUE))
1900 || (command("%s %s", cmd, remote) != PRELIM)) {
1901 (void)xsignal(SIGINT, oldintr);
1902 pswitch(1);
1903 return;
1904 }
1905 sleep(2);
1906 pswitch(1);
1907 secndflag++;
1908 if ((restart_point &&
1909 (command("REST " LLF, (LLT) restart_point) != CONTINUE))
1910 || (command("%s %s", cmd2, local) != PRELIM))
1911 goto abort;
1912 ptflag++;
1913 (void)getreply(0);
1914 pswitch(0);
1915 (void)getreply(0);
1916 (void)xsignal(SIGINT, oldintr);
1917 pswitch(1);
1918 ptflag = 0;
1919 fprintf(ttyout, "local: %s remote: %s\n", local, remote);
1920 return;
1921 abort:
1922 if (sigsetjmp(xferabort, 1)) {
1923 (void)xsignal(SIGINT, oldintr);
1924 return;
1925 }
1926 (void)xsignal(SIGINT, abort_squared);
1927 ptflag = 0;
1928 if (strcmp(cmd, "RETR") && !proxy)
1929 pswitch(1);
1930 else if (!strcmp(cmd, "RETR") && proxy)
1931 pswitch(0);
1932 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1933 if (command("%s %s", cmd2, local) != PRELIM) {
1934 pswitch(0);
1935 if (cpend)
1936 abort_remote(NULL);
1937 }
1938 pswitch(1);
1939 if (ptabflg)
1940 code = -1;
1941 (void)xsignal(SIGINT, oldintr);
1942 return;
1943 }
1944 if (cpend)
1945 abort_remote(NULL);
1946 pswitch(!proxy);
1947 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1948 if (command("%s %s", cmd2, local) != PRELIM) {
1949 pswitch(0);
1950 if (cpend)
1951 abort_remote(NULL);
1952 pswitch(1);
1953 if (ptabflg)
1954 code = -1;
1955 (void)xsignal(SIGINT, oldintr);
1956 return;
1957 }
1958 }
1959 if (cpend)
1960 abort_remote(NULL);
1961 pswitch(!proxy);
1962 if (cpend) {
1963 if ((nfnd = empty(cin, NULL, 10)) <= 0) {
1964 if (nfnd < 0)
1965 warn("abort");
1966 if (ptabflg)
1967 code = -1;
1968 lostpeer(0);
1969 }
1970 (void)getreply(0);
1971 (void)getreply(0);
1972 }
1973 if (proxy)
1974 pswitch(0);
1975 pswitch(1);
1976 if (ptabflg)
1977 code = -1;
1978 (void)xsignal(SIGINT, oldintr);
1979 }
1980
1981 void
1982 reset(int argc, char *argv[])
1983 {
1984 int nfnd = 1;
1985
1986 if (argc == 0 && argv != NULL) {
1987 fprintf(ttyout, "usage: %s\n", argv[0]);
1988 code = -1;
1989 return;
1990 }
1991 while (nfnd > 0) {
1992 if ((nfnd = empty(cin, NULL, 0)) < 0) {
1993 warn("reset");
1994 code = -1;
1995 lostpeer(0);
1996 } else if (nfnd)
1997 (void)getreply(0);
1998 }
1999 }
2000
2001 char *
2002 gunique(const char *local)
2003 {
2004 static char new[MAXPATHLEN];
2005 char *cp = strrchr(local, '/');
2006 int d, count=0, len;
2007 char ext = '1';
2008
2009 if (cp)
2010 *cp = '\0';
2011 d = access(cp == local ? "/" : cp ? local : ".", W_OK);
2012 if (cp)
2013 *cp = '/';
2014 if (d < 0) {
2015 warn("local: %s", local);
2016 return (NULL);
2017 }
2018 len = strlcpy(new, local, sizeof(new));
2019 cp = &new[len];
2020 *cp++ = '.';
2021 while (!d) {
2022 if (++count == 100) {
2023 fputs("runique: can't find unique file name.\n",
2024 ttyout);
2025 return (NULL);
2026 }
2027 *cp++ = ext;
2028 *cp = '\0';
2029 if (ext == '9')
2030 ext = '0';
2031 else
2032 ext++;
2033 if ((d = access(new, F_OK)) < 0)
2034 break;
2035 if (ext != '0')
2036 cp--;
2037 else if (*(cp - 2) == '.')
2038 *(cp - 1) = '1';
2039 else {
2040 *(cp - 2) = *(cp - 2) + 1;
2041 cp--;
2042 }
2043 }
2044 return (new);
2045 }
2046
2047 /*
2048 * abort_squared --
2049 * aborts abort_remote(). lostpeer() is called because if the user is
2050 * too impatient to wait or there's another problem then ftp really
2051 * needs to get back to a known state.
2052 */
2053 void
2054 abort_squared(int dummy)
2055 {
2056 char msgbuf[100];
2057 int len;
2058
2059 alarmtimer(0);
2060 len = strlcpy(msgbuf, "\nremote abort aborted; closing connection.\n",
2061 sizeof(msgbuf));
2062 write(fileno(ttyout), msgbuf, len);
2063 lostpeer(0);
2064 siglongjmp(xferabort, 1);
2065 }
2066
2067 void
2068 abort_remote(FILE *din)
2069 {
2070 char buf[BUFSIZ];
2071 int nfnd;
2072
2073 if (cout == NULL) {
2074 warnx("Lost control connection for abort.");
2075 if (ptabflg)
2076 code = -1;
2077 lostpeer(0);
2078 return;
2079 }
2080 /*
2081 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
2082 * after urgent byte rather than before as is protocol now
2083 */
2084 buf[0] = IAC;
2085 buf[1] = IP;
2086 buf[2] = IAC;
2087 if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
2088 warn("abort");
2089 fprintf(cout, "%cABOR\r\n", DM);
2090 (void)fflush(cout);
2091 if ((nfnd = empty(cin, din, 10)) <= 0) {
2092 if (nfnd < 0)
2093 warn("abort");
2094 if (ptabflg)
2095 code = -1;
2096 lostpeer(0);
2097 }
2098 if (din && (nfnd & 2)) {
2099 while (read(fileno(din), buf, BUFSIZ) > 0)
2100 continue;
2101 }
2102 if (getreply(0) == ERROR && code == 552) {
2103 /* 552 needed for nic style abort */
2104 (void)getreply(0);
2105 }
2106 (void)getreply(0);
2107 }
2108
2109 void
2110 ai_unmapped(struct addrinfo *ai)
2111 {
2112 #ifdef INET6
2113 struct sockaddr_in6 *sin6;
2114 struct sockaddr_in sin;
2115 int len;
2116
2117 if (ai->ai_family != AF_INET6)
2118 return;
2119 if (ai->ai_addrlen != sizeof(struct sockaddr_in6) ||
2120 sizeof(sin) > ai->ai_addrlen)
2121 return;
2122 sin6 = (struct sockaddr_in6 *)ai->ai_addr;
2123 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
2124 return;
2125
2126 memset(&sin, 0, sizeof(sin));
2127 sin.sin_family = AF_INET;
2128 len = sizeof(struct sockaddr_in);
2129 memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
2130 sizeof(sin.sin_addr));
2131 sin.sin_port = sin6->sin6_port;
2132
2133 ai->ai_family = AF_INET;
2134 #if HAVE_SOCKADDR_SA_LEN
2135 sin.sin_len = len;
2136 #endif
2137 memcpy(ai->ai_addr, &sin, len);
2138 ai->ai_addrlen = len;
2139 #endif
2140 }
2141