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