Bug Summary

File:src/usr.bin/ftp/ftp.c
Warning:line 456, column 13
Although the value stored to 'c' is used in the enclosing expression, the value is never actually read from 'c'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ftp.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/ftp/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/ftp/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/ftp/ftp.c
1/* $OpenBSD: ftp.c,v 1.107 2019/11/18 04:37:35 deraadt Exp $ */
2/* $NetBSD: ftp.c,v 1.27 1997/08/18 10:20:23 lukem Exp $ */
3
4/*
5 * Copyright (C) 1997 and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1985, 1989, 1993, 1994
35 * The Regents of the University of California. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62#include <sys/types.h>
63#include <sys/stat.h>
64#include <sys/socket.h>
65
66#include <netinet/in.h>
67#include <netinet/ip.h>
68#include <arpa/inet.h>
69#include <arpa/ftp.h>
70#include <arpa/telnet.h>
71
72#include <ctype.h>
73#include <err.h>
74#include <errno(*__errno()).h>
75#include <fcntl.h>
76#include <netdb.h>
77#include <poll.h>
78#include <stdarg.h>
79#include <stdio.h>
80#include <stdlib.h>
81#include <string.h>
82#include <unistd.h>
83
84#include "ftp_var.h"
85
86union sockaddr_union {
87 struct sockaddr sa;
88 struct sockaddr_in sin;
89 struct sockaddr_in6 sin6;
90};
91
92union sockaddr_union myctladdr, hisctladdr, data_addr;
93
94int data = -1;
95int abrtflag = 0;
96jmp_buf ptabort;
97int ptabflg;
98int ptflag = 0;
99off_t restart_point = 0;
100
101
102FILE *cin, *cout;
103
104char *
105hookup(char *host, char *port)
106{
107 int s, tos, error;
108 static char hostnamebuf[HOST_NAME_MAX255+1];
109 struct addrinfo hints, *res, *res0;
110#ifndef SMALL
111 struct addrinfo *ares;
112#endif
113 char hbuf[NI_MAXHOST256];
114 char *cause = "unknown";
115 socklen_t namelen;
116
117 epsv4bad = 0;
118
119 memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
120 memset(&hints, 0, sizeof(hints));
121 hints.ai_flags = AI_CANONNAME2;
122 hints.ai_family = family;
123 hints.ai_socktype = SOCK_STREAM1;
124 hints.ai_protocol = 0;
125 error = getaddrinfo(host, port, &hints, &res0);
126 if (error == EAI_SERVICE-8) {
127 /*
128 * If the services file is corrupt/missing, fall back
129 * on our hard-coded defines.
130 */
131 char pbuf[NI_MAXSERV32];
132
133 pbuf[0] = '\0';
134 if (strcmp(port, "ftp") == 0)
135 snprintf(pbuf, sizeof(pbuf), "%d", FTP_PORT21);
136 else if (strcmp(port, "ftpgate") == 0)
137 snprintf(pbuf, sizeof(pbuf), "%d", GATE_PORT21);
138 else if (strcmp(port, "http") == 0)
139 snprintf(pbuf, sizeof(pbuf), "%d", HTTP_PORT80);
140#ifndef SMALL
141 else if (strcmp(port, "https") == 0)
142 snprintf(pbuf, sizeof(pbuf), "%d", HTTPS_PORT443);
143#endif /* !SMALL */
144 if (pbuf[0])
145 error = getaddrinfo(host, pbuf, &hints, &res0);
146 }
147 if (error) {
148 if (error == EAI_SERVICE-8)
149 warnx("%s: bad port number `%s'", host, port);
150 else
151 warnx("%s: %s", host, gai_strerror(error));
152 code = -1;
153 return (0);
154 }
155
156 if (res0->ai_canonname)
157 strlcpy(hostnamebuf, res0->ai_canonname, sizeof(hostnamebuf));
158 else
159 strlcpy(hostnamebuf, host, sizeof(hostnamebuf));
160 hostname = hostnamebuf;
161
162#ifndef SMALL
163 if (srcaddr) {
164 struct addrinfo ahints;
165
166 memset(&ahints, 0, sizeof(ahints));
167 ahints.ai_family = family;
168 ahints.ai_socktype = SOCK_STREAM1;
169 ahints.ai_flags |= AI_NUMERICHOST4;
170 ahints.ai_protocol = 0;
171
172 error = getaddrinfo(srcaddr, NULL((void*)0), &ahints, &ares);
173 if (error) {
174 warnx("%s: %s", srcaddr, gai_strerror(error));
175 code = -1;
176 return (0);
177 }
178 }
179#endif /* !SMALL */
180
181 s = -1;
182 for (res = res0; res; res = res->ai_next) {
183 if (res0->ai_next) /* if we have multiple possibilities */
184 {
185 if (getnameinfo(res->ai_addr, res->ai_addrlen,
186 hbuf, sizeof(hbuf), NULL((void*)0), 0, NI_NUMERICHOST1) != 0)
187 strlcpy(hbuf, "unknown", sizeof(hbuf));
188 if (verbose)
189 fprintf(ttyout, "Trying %s...\n", hbuf);
190 }
191 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
192 if (s == -1) {
193 cause = "socket";
194 continue;
195 }
196#ifndef SMALL
197 if (srcaddr) {
198 if (ares->ai_family != res->ai_family) {
199 close(s);
200 s = -1;
201 errno(*__errno()) = EINVAL22;
202 cause = "bind";
203 continue;
204 }
205 if (bind(s, ares->ai_addr, ares->ai_addrlen) == -1) {
206 cause = "bind";
207 error = errno(*__errno());
208 close(s);
209 errno(*__errno()) = error;
210 s = -1;
211 continue;
212 }
213 }
214#endif /* !SMALL */
215 for (error = connect(s, res->ai_addr, res->ai_addrlen);
216 error != 0 && errno(*__errno()) == EINTR4; error = connect_wait(s))
217 continue;
218 if (error != 0) {
219 /* this "if" clause is to prevent print warning twice */
220 if (verbose && res->ai_next) {
221 if (getnameinfo(res->ai_addr, res->ai_addrlen,
222 hbuf, sizeof(hbuf), NULL((void*)0), 0,
223 NI_NUMERICHOST1) != 0)
224 strlcpy(hbuf, "(unknown)",
225 sizeof(hbuf));
226 warn("connect to address %s", hbuf);
227 }
228 cause = "connect";
229 error = errno(*__errno());
230 close(s);
231 errno(*__errno()) = error;
232 s = -1;
233 continue;
234 }
235
236 /* finally we got one */
237 break;
238 }
239 if (s == -1) {
240 warn("%s", cause);
241 code = -1;
242 freeaddrinfo(res0);
243 return 0;
244 }
245 memcpy(&hisctladdr, res->ai_addr, res->ai_addrlen);
246 namelen = res->ai_addrlen;
247 freeaddrinfo(res0);
248 res0 = res = NULL((void*)0);
249#ifndef SMALL
250 if (srcaddr) {
251 freeaddrinfo(ares);
252 ares = NULL((void*)0);
253 }
254#endif /* !SMALL */
255 if (getsockname(s, &myctladdr.sa, &namelen) == -1) {
256 warn("getsockname");
257 code = -1;
258 goto bad;
259 }
260 if (hisctladdr.sa.sa_family == AF_INET2) {
261 tos = IPTOS_LOWDELAY0x10;
262 if (setsockopt(s, IPPROTO_IP0, IP_TOS3, (char *)&tos, sizeof(int)) == -1)
263 warn("setsockopt TOS (ignored)");
264 }
265 cin = fdopen(s, "r");
266 cout = fdopen(s, "w");
267 if (cin == NULL((void*)0) || cout == NULL((void*)0)) {
268 warnx("fdopen failed.");
269 if (cin)
270 (void)fclose(cin);
271 if (cout)
272 (void)fclose(cout);
273 code = -1;
274 goto bad;
275 }
276 if (verbose)
277 fprintf(ttyout, "Connected to %s.\n", hostname);
278 if (getreply(0) > 2) { /* read startup message from server */
279 if (cin)
280 (void)fclose(cin);
281 if (cout)
282 (void)fclose(cout);
283 code = -1;
284 goto bad;
285 }
286 {
287 int ret, on = 1;
288
289 ret = setsockopt(s, SOL_SOCKET0xffff, SO_OOBINLINE0x0100, (char *)&on, sizeof(on));
290#ifndef SMALL
291 if (ret == -1 && debug)
292 warn("setsockopt");
293#endif /* !SMALL */
294 }
295
296 return (hostname);
297bad:
298 (void)close(s);
299 return (NULL((void*)0));
300}
301
302/* ARGSUSED */
303void
304cmdabort(int signo)
305{
306 int save_errno = errno(*__errno());
307
308 alarmtimer(0);
309 (void) write(fileno(ttyout)(!__isthreaded ? ((ttyout)->_file) : (fileno)(ttyout)), "\n\r", 2);
310 abrtflag++;
311
312 errno(*__errno()) = save_errno;
313 if (ptflag)
314 longjmp(ptabort, 1);
315}
316
317int
318command(const char *fmt, ...)
319{
320 va_list ap;
321 int r;
322 sig_t oldintr;
323
324 abrtflag = 0;
325#ifndef SMALL
326 if (debug) {
327 fputs("---> ", ttyout);
328 va_start(ap, fmt)__builtin_va_start(ap, fmt);
329 if (strncmp("PASS ", fmt, 5) == 0)
330 fputs("PASS XXXX", ttyout);
331 else if (strncmp("ACCT ", fmt, 5) == 0)
332 fputs("ACCT XXXX", ttyout);
333 else
334 vfprintf(ttyout, fmt, ap);
335 va_end(ap)__builtin_va_end(ap);
336 putc('\n', ttyout)(!__isthreaded ? __sputc('\n', ttyout) : (putc)('\n', ttyout)
)
;
337 (void)fflush(ttyout);
338 }
339#endif /* !SMALL */
340 if (cout == NULL((void*)0)) {
341 warnx("No control connection for command.");
342 code = -1;
343 return (0);
344 }
345 oldintr = signal(SIGINT2, cmdabort);
346 va_start(ap, fmt)__builtin_va_start(ap, fmt);
347 vfprintf(cout, fmt, ap);
348 va_end(ap)__builtin_va_end(ap);
349 fputs("\r\n", cout);
350 (void)fflush(cout);
351 cpend = 1;
352 r = getreply(!strcmp(fmt, "QUIT"));
353 if (abrtflag && oldintr != SIG_IGN(void (*)(int))1)
354 (*oldintr)(SIGINT2);
355 (void)signal(SIGINT2, oldintr);
356 return (r);
357}
358
359int keep_alive_timeout = 60; /* 0 -> no timeout */
360
361static int full_noops_sent = 0;
362static time_t last_timestamp = 0; /* 0 -> no measurement yet */
363static char noop[] = "NOOP\r\n";
364#define NOOP_LENGTH(sizeof noop - 1) (sizeof noop - 1)
365static int current_nop_pos = 0; /* 0 -> no noop started */
366
367/* to achieve keep alive, we send noop one byte at a time */
368static void
369send_noop_char(void)
370{
371#ifndef SMALL
372 if (debug)
373 fprintf(ttyout, "---> %c\n", noop[current_nop_pos]);
374#endif /* !SMALL */
375 fputc(noop[current_nop_pos++], cout);
376 (void)fflush(cout);
377 if (current_nop_pos >= NOOP_LENGTH(sizeof noop - 1)) {
378 full_noops_sent++;
379 current_nop_pos = 0;
380 }
381}
382
383static void
384may_reset_noop_timeout(void)
385{
386 if (keep_alive_timeout != 0)
387 last_timestamp = time(NULL((void*)0));
388}
389
390static void
391may_receive_noop_ack(void)
392{
393 int i;
394
395 if (cout == NULL((void*)0)) {
396 /* Lost connection; so just pretend we're fine. */
397 current_nop_pos = full_noops_sent = 0;
398 return;
399 }
400
401 /* finish sending last incomplete noop */
402 if (current_nop_pos != 0) {
403 fputs(&(noop[current_nop_pos]), cout);
404#ifndef SMALL
405 if (debug)
406 fprintf(ttyout, "---> %s\n", &(noop[current_nop_pos]));
407#endif /* !SMALL */
408 (void)fflush(cout);
409 current_nop_pos = 0;
410 full_noops_sent++;
411 }
412 /* and get the replies */
413 for (i = 0; i < full_noops_sent; i++)
414 (void)getreply(0);
415
416 full_noops_sent = 0;
417}
418
419static void
420may_send_noop_char(void)
421{
422 if (keep_alive_timeout != 0) {
423 if (last_timestamp != 0) {
424 time_t t = time(NULL((void*)0));
425
426 if (t - last_timestamp >= keep_alive_timeout) {
427 last_timestamp = t;
428 send_noop_char();
429 }
430 } else {
431 last_timestamp = time(NULL((void*)0));
432 }
433 }
434}
435
436char reply_string[BUFSIZ1024]; /* first line of previous reply */
437
438int
439getreply(int expecteof)
440{
441 char current_line[BUFSIZ1024]; /* last line of previous reply */
442 int c, n, lineno;
443 int dig;
444 int originalcode = 0, continuation = 0;
445 sig_t oldintr;
446 int pflag = 0;
447 char *cp, *pt = pasv;
448
449 memset(current_line, 0, sizeof(current_line));
450 oldintr = signal(SIGINT2, cmdabort);
451 for (lineno = 0 ;; lineno++) {
452 dig = n = code = 0;
453 cp = current_line;
454 while ((c = fgetc(cin)) != '\n') {
455 if (c == IAC255) { /* handle telnet commands */
456 switch (c = fgetc(cin)) {
Although the value stored to 'c' is used in the enclosing expression, the value is never actually read from 'c'
457 case WILL251:
458 case WONT252:
459 c = fgetc(cin);
460 fprintf(cout, "%c%c%c", IAC255, DONT254, c);
461 (void)fflush(cout);
462 break;
463 case DO253:
464 case DONT254:
465 c = fgetc(cin);
466 fprintf(cout, "%c%c%c", IAC255, WONT252, c);
467 (void)fflush(cout);
468 break;
469 default:
470 break;
471 }
472 continue;
473 }
474 dig++;
475 if (c == EOF(-1)) {
476 if (expecteof) {
477 (void)signal(SIGINT2, oldintr);
478 code = 221;
479 return (0);
480 }
481 lostpeer();
482 if (verbose) {
483 fputs(
484"421 Service not available, remote server has closed connection.\n", ttyout);
485 (void)fflush(ttyout);
486 }
487 code = 421;
488 return (4);
489 }
490 if (c != '\r' && (verbose > 0 ||
491 ((verbose > -1 && n == '5' && dig > 4) &&
492 (((!n && c < '5') || (n && n < '5')) ||
493 !retry_connect)))) {
494 if (proxflag &&
495 (dig == 1 || (dig == 5 && verbose == 0)))
496 fprintf(ttyout, "%s:", hostname);
497 (void)putc(c, ttyout)(!__isthreaded ? __sputc(c, ttyout) : (putc)(c, ttyout));
498 }
499 if (dig < 4 && isdigit(c))
500 code = code * 10 + (c - '0');
501 if (!pflag && (code == 227 || code == 228))
502 pflag = 1;
503 else if (!pflag && code == 229)
504 pflag = 100;
505 if (dig > 4 && pflag == 1 && isdigit(c))
506 pflag = 2;
507 if (pflag == 2) {
508 if (c != '\r' && c != ')') {
509 if (pt < &pasv[sizeof(pasv) - 1])
510 *pt++ = c;
511 } else {
512 *pt = '\0';
513 pflag = 3;
514 }
515 }
516 if (pflag == 100 && c == '(')
517 pflag = 2;
518 if (dig == 4 && c == '-') {
519 if (continuation)
520 code = 0;
521 continuation++;
522 }
523 if (n == 0)
524 n = c;
525 if (cp < &current_line[sizeof(current_line) - 1])
526 *cp++ = c;
527 }
528 if (verbose > 0 || ((verbose > -1 && n == '5') &&
529 (n < '5' || !retry_connect))) {
530 (void)putc(c, ttyout)(!__isthreaded ? __sputc(c, ttyout) : (putc)(c, ttyout));
531 (void)fflush (ttyout);
532 }
533 if (lineno == 0) {
534 size_t len = cp - current_line;
535
536 if (len > sizeof(reply_string))
537 len = sizeof(reply_string);
538
539 (void)strlcpy(reply_string, current_line, len);
540 }
541 if (continuation && code != originalcode) {
542 if (originalcode == 0)
543 originalcode = code;
544 continue;
545 }
546 *cp = '\0';
547 if (n != '1')
548 cpend = 0;
549 (void)signal(SIGINT2, oldintr);
550 if (code == 421 || originalcode == 421)
551 lostpeer();
552 if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN(void (*)(int))1)
553 (*oldintr)(SIGINT2);
554 return (n - '0');
555 }
556}
557
558#ifndef SMALL
559jmp_buf sendabort;
560
561/* ARGSUSED */
562void
563abortsend(int signo)
564{
565 int save_errno = errno(*__errno());
566 alarmtimer(0);
567 mflag = 0;
568 abrtflag = 0;
569#define MSG "\nsend aborted\nwaiting for remote to finish abort.\n"
570 (void) write(fileno(ttyout)(!__isthreaded ? ((ttyout)->_file) : (fileno)(ttyout)), MSG, strlen(MSG));
571#undef MSG
572
573 errno(*__errno()) = save_errno;
574 longjmp(sendabort, 1);
575}
576
577void
578sendrequest(const char *cmd, const char *local, const char *remote,
579 int printnames)
580{
581 struct stat st;
582 int c, d;
583 FILE * volatile fin, * volatile dout;
584 int (* volatile closefunc)(FILE *);
585 volatile sig_t oldinti, oldintr, oldintp;
586 volatile off_t hashbytes;
587 char * volatile lmode;
588 char buf[BUFSIZ1024], *bufp;
589 int oprogress, serrno;
590
591 hashbytes = mark;
592 direction = "sent";
593 dout = NULL((void*)0);
594 bytes = 0;
595 filesize = -1;
596 oprogress = progress;
597 if (verbose && printnames) {
598 if (local && *local != '-')
599 fprintf(ttyout, "local: %s ", local);
600 if (remote)
601 fprintf(ttyout, "remote: %s\n", remote);
602 }
603 if (proxy) {
604 proxtrans(cmd, local, remote);
605 return;
606 }
607 if (curtype != type)
608 changetype(type, 0);
609 closefunc = NULL((void*)0);
610 oldintr = NULL((void*)0);
611 oldintp = NULL((void*)0);
612 oldinti = NULL((void*)0);
613 lmode = "w";
614 if (setjmp(sendabort)) {
615 while (cpend) {
616 (void)getreply(0);
617 }
618 if (data >= 0) {
619 (void)close(data);
620 data = -1;
621 }
622 if (oldintr)
623 (void)signal(SIGINT2, oldintr);
624 if (oldintp)
625 (void)signal(SIGPIPE13, oldintp);
626 if (oldinti)
627 (void)signal(SIGINFO29, oldinti);
628 progress = oprogress;
629 code = -1;
630 return;
631 }
632 oldintr = signal(SIGINT2, abortsend);
633 oldinti = signal(SIGINFO29, psummary);
634 if (strcmp(local, "-") == 0) {
635 fin = stdin(&__sF[0]);
636 if (progress == 1)
637 progress = 0;
638 } else if (*local == '|') {
639 oldintp = signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
640 fin = popen(local + 1, "r");
641 if (fin == NULL((void*)0)) {
642 warn("%s", local + 1);
643 (void)signal(SIGINT2, oldintr);
644 (void)signal(SIGPIPE13, oldintp);
645 (void)signal(SIGINFO29, oldinti);
646 code = -1;
647 return;
648 }
649 if (progress == 1)
650 progress = 0;
651 closefunc = pclose;
652 } else {
653 fin = fopen(local, "r");
654 if (fin == NULL((void*)0)) {
655 warn("local: %s", local);
656 (void)signal(SIGINT2, oldintr);
657 (void)signal(SIGINFO29, oldinti);
658 code = -1;
659 return;
660 }
661 closefunc = fclose;
662 if (fstat(fileno(fin)(!__isthreaded ? ((fin)->_file) : (fileno)(fin)), &st) == -1 ||
663 (st.st_mode & S_IFMT0170000) != S_IFREG0100000) {
664 fprintf(ttyout, "%s: not a plain file.\n", local);
665 (void)signal(SIGINT2, oldintr);
666 (void)signal(SIGINFO29, oldinti);
667 fclose(fin);
668 code = -1;
669 return;
670 }
671 filesize = st.st_size;
672 }
673 if (initconn()) {
674 (void)signal(SIGINT2, oldintr);
675 (void)signal(SIGINFO29, oldinti);
676 if (oldintp)
677 (void)signal(SIGPIPE13, oldintp);
678 code = -1;
679 progress = oprogress;
680 if (closefunc != NULL((void*)0))
681 (*closefunc)(fin);
682 return;
683 }
684 if (setjmp(sendabort))
685 goto abort;
686
687 if (restart_point &&
688 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
689 int rc = -1;
690
691 switch (curtype) {
692 case TYPE_A1:
693 rc = fseeko(fin, restart_point, SEEK_SET0);
694 break;
695 case TYPE_I3:
696 if (lseek(fileno(fin)(!__isthreaded ? ((fin)->_file) : (fileno)(fin)), restart_point, SEEK_SET0) != -1)
697 rc = 0;
698 break;
699 }
700 if (rc == -1) {
701 warn("local: %s", local);
702 progress = oprogress;
703 if (closefunc != NULL((void*)0))
704 (*closefunc)(fin);
705 return;
706 }
707 if (command("REST %lld", (long long) restart_point)
708 != CONTINUE3) {
709 progress = oprogress;
710 if (closefunc != NULL((void*)0))
711 (*closefunc)(fin);
712 return;
713 }
714 lmode = "r+w";
715 }
716 if (remote) {
717 if (command("%s %s", cmd, remote) != PRELIM1) {
718 (void)signal(SIGINT2, oldintr);
719 (void)signal(SIGINFO29, oldinti);
720 progress = oprogress;
721 if (oldintp)
722 (void)signal(SIGPIPE13, oldintp);
723 if (closefunc != NULL((void*)0))
724 (*closefunc)(fin);
725 return;
726 }
727 } else
728 if (command("%s", cmd) != PRELIM1) {
729 (void)signal(SIGINT2, oldintr);
730 (void)signal(SIGINFO29, oldinti);
731 progress = oprogress;
732 if (oldintp)
733 (void)signal(SIGPIPE13, oldintp);
734 if (closefunc != NULL((void*)0))
735 (*closefunc)(fin);
736 return;
737 }
738 dout = dataconn(lmode);
739 if (dout == NULL((void*)0))
740 goto abort;
741 progressmeter(-1, remote);
742 may_reset_noop_timeout();
743 oldintp = signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
744 serrno = 0;
745 switch (curtype) {
746
747 case TYPE_I3:
748 d = 0;
749 while ((c = read(fileno(fin)(!__isthreaded ? ((fin)->_file) : (fileno)(fin)), buf, sizeof(buf))) > 0) {
750 may_send_noop_char();
751 bytes += c;
752 for (bufp = buf; c > 0; c -= d, bufp += d)
753 if ((d = write(fileno(dout)(!__isthreaded ? ((dout)->_file) : (fileno)(dout)), bufp, (size_t)c))
754 <= 0)
755 break;
756 if (hash && (!progress || filesize < 0) ) {
757 while (bytes >= hashbytes) {
758 (void)putc('#', ttyout)(!__isthreaded ? __sputc('#', ttyout) : (putc)('#', ttyout));
759 hashbytes += mark;
760 }
761 (void)fflush(ttyout);
762 }
763 }
764 if (c == -1 || d == -1)
765 serrno = errno(*__errno());
766 if (hash && (!progress || filesize < 0) && bytes > 0) {
767 if (bytes < mark)
768 (void)putc('#', ttyout)(!__isthreaded ? __sputc('#', ttyout) : (putc)('#', ttyout));
769 (void)putc('\n', ttyout)(!__isthreaded ? __sputc('\n', ttyout) : (putc)('\n', ttyout)
)
;
770 (void)fflush(ttyout);
771 }
772 if (c < 0)
773 warnc(serrno, "local: %s", local);
774 if (d < 0) {
775 if (serrno != EPIPE32)
776 warnc(serrno, "netout");
777 bytes = -1;
778 }
779 break;
780
781 case TYPE_A1:
782 while ((c = fgetc(fin)) != EOF(-1)) {
783 may_send_noop_char();
784 if (c == '\n') {
785 while (hash && (!progress || filesize < 0) &&
786 (bytes >= hashbytes)) {
787 (void)putc('#', ttyout)(!__isthreaded ? __sputc('#', ttyout) : (putc)('#', ttyout));
788 (void)fflush(ttyout);
789 hashbytes += mark;
790 }
791 if (ferror(dout)(!__isthreaded ? (((dout)->_flags & 0x0040) != 0) : (ferror
)(dout))
)
792 break;
793 (void)putc('\r', dout)(!__isthreaded ? __sputc('\r', dout) : (putc)('\r', dout));
794 bytes++;
795 }
796 (void)putc(c, dout)(!__isthreaded ? __sputc(c, dout) : (putc)(c, dout));
797 bytes++;
798 }
799 if (ferror(fin)(!__isthreaded ? (((fin)->_flags & 0x0040) != 0) : (ferror
)(fin))
|| ferror(dout)(!__isthreaded ? (((dout)->_flags & 0x0040) != 0) : (ferror
)(dout))
)
800 serrno = errno(*__errno());
801 if (hash && (!progress || filesize < 0)) {
802 if (bytes < hashbytes)
803 (void)putc('#', ttyout)(!__isthreaded ? __sputc('#', ttyout) : (putc)('#', ttyout));
804 (void)putc('\n', ttyout)(!__isthreaded ? __sputc('\n', ttyout) : (putc)('\n', ttyout)
)
;
805 (void)fflush(ttyout);
806 }
807 if (ferror(fin)(!__isthreaded ? (((fin)->_flags & 0x0040) != 0) : (ferror
)(fin))
)
808 warnc(serrno, "local: %s", local);
809 if (ferror(dout)(!__isthreaded ? (((dout)->_flags & 0x0040) != 0) : (ferror
)(dout))
) {
810 if (errno(*__errno()) != EPIPE32)
811 warnc(serrno, "netout");
812 bytes = -1;
813 }
814 break;
815 }
816 progressmeter(1, NULL((void*)0));
817 progress = oprogress;
818 if (closefunc != NULL((void*)0))
819 (*closefunc)(fin);
820 (void)fclose(dout);
821 (void)getreply(0);
822 may_receive_noop_ack();
823 (void)signal(SIGINT2, oldintr);
824 (void)signal(SIGINFO29, oldinti);
825 if (oldintp)
826 (void)signal(SIGPIPE13, oldintp);
827 if (bytes > 0)
828 ptransfer(0);
829 return;
830abort:
831 (void)signal(SIGINT2, oldintr);
832 (void)signal(SIGINFO29, oldinti);
833 progress = oprogress;
834 if (oldintp)
835 (void)signal(SIGPIPE13, oldintp);
836 if (!cpend) {
837 code = -1;
838 return;
839 }
840 if (data >= 0) {
841 (void)close(data);
842 data = -1;
843 }
844 if (dout)
845 (void)fclose(dout);
846 (void)getreply(0);
847 code = -1;
848 if (closefunc != NULL((void*)0) && fin != NULL((void*)0))
849 (*closefunc)(fin);
850 if (bytes > 0)
851 ptransfer(0);
852}
853#endif /* !SMALL */
854
855jmp_buf recvabort;
856
857/* ARGSUSED */
858void
859abortrecv(int signo)
860{
861
862 alarmtimer(0);
863 mflag = 0;
864 abrtflag = 0;
865 fputs("\nreceive aborted\nwaiting for remote to finish abort.\n", ttyout);
866 (void)fflush(ttyout);
867 longjmp(recvabort, 1);
868}
869
870void
871recvrequest(const char *cmd, const char * volatile local, const char *remote,
872 const char *lmode, int printnames, int ignorespecial)
873{
874 FILE * volatile fout, * volatile din;
875 int (* volatile closefunc)(FILE *);
876 volatile sig_t oldinti, oldintr, oldintp;
877 int c, d, serrno;
878 volatile int is_retr, tcrflag, bare_lfs;
879 static size_t bufsize;
880 static char *buf;
881 volatile off_t hashbytes;
882 struct stat st;
883 time_t mtime;
884 int oprogress;
885 int opreserve;
886
887 fout = NULL((void*)0);
888 din = NULL((void*)0);
889 oldinti = NULL((void*)0);
890 hashbytes = mark;
891 direction = "received";
892 bytes = 0;
893 bare_lfs = 0;
894 filesize = -1;
895 oprogress = progress;
896 opreserve = preserve;
897 is_retr = strcmp(cmd, "RETR") == 0;
898 if (is_retr && verbose && printnames) {
899 if (local && (ignorespecial || *local != '-'))
900 fprintf(ttyout, "local: %s ", local);
901 if (remote)
902 fprintf(ttyout, "remote: %s\n", remote);
903 }
904 if (proxy && is_retr) {
905 proxtrans(cmd, local, remote);
906 return;
907 }
908 closefunc = NULL((void*)0);
909 oldintr = NULL((void*)0);
910 oldintp = NULL((void*)0);
911 tcrflag = !crflag && is_retr;
912 if (setjmp(recvabort)) {
913 while (cpend) {
914 (void)getreply(0);
915 }
916 if (data >= 0) {
917 (void)close(data);
918 data = -1;
919 }
920 if (oldintr)
921 (void)signal(SIGINT2, oldintr);
922 if (oldinti)
923 (void)signal(SIGINFO29, oldinti);
924 progress = oprogress;
925 preserve = opreserve;
926 code = -1;
927 return;
928 }
929 oldintr = signal(SIGINT2, abortrecv);
930 oldinti = signal(SIGINFO29, psummary);
931 if (ignorespecial || (strcmp(local, "-") && *local != '|')) {
932 if (access(local, W_OK0x02) == -1) {
933 char *dir;
934
935 if (errno(*__errno()) != ENOENT2 && errno(*__errno()) != EACCES13) {
936 warn("local: %s", local);
937 (void)signal(SIGINT2, oldintr);
938 (void)signal(SIGINFO29, oldinti);
939 code = -1;
940 return;
941 }
942 dir = strrchr(local, '/');
943 if (dir != NULL((void*)0))
944 *dir = 0;
945 d = access(dir == local ? "/" : dir ? local : ".", W_OK0x02);
946 if (dir != NULL((void*)0))
947 *dir = '/';
948 if (d == -1) {
949 warn("local: %s", local);
950 (void)signal(SIGINT2, oldintr);
951 (void)signal(SIGINFO29, oldinti);
952 code = -1;
953 return;
954 }
955 if (!runique && errno(*__errno()) == EACCES13 &&
956 chmod(local, (S_IRUSR0000400|S_IWUSR0000200)) == -1) {
957 warn("local: %s", local);
958 (void)signal(SIGINT2, oldintr);
959 (void)signal(SIGINFO29, oldinti);
960 code = -1;
961 return;
962 }
963 if (runique && errno(*__errno()) == EACCES13 &&
964 (local = gunique(local)) == NULL((void*)0)) {
965 (void)signal(SIGINT2, oldintr);
966 (void)signal(SIGINFO29, oldinti);
967 code = -1;
968 return;
969 }
970 } else if (runique && (local = gunique(local)) == NULL((void*)0)) {
971 (void)signal(SIGINT2, oldintr);
972 (void)signal(SIGINFO29, oldinti);
973 code = -1;
974 return;
975 }
976 }
977 if (!is_retr) {
978 if (curtype != TYPE_A1)
979 changetype(TYPE_A1, 0);
980 } else {
981 if (curtype != type)
982 changetype(type, 0);
983 filesize = remotesize(remote, 0);
984 }
985 if (initconn()) {
986 (void)signal(SIGINT2, oldintr);
987 (void)signal(SIGINFO29, oldinti);
988 code = -1;
989 return;
990 }
991 if (setjmp(recvabort))
992 goto abort;
993 if (is_retr && restart_point &&
994 command("REST %lld", (long long) restart_point) != CONTINUE3)
995 return;
996 if (remote) {
997 if (command("%s %s", cmd, remote) != PRELIM1) {
998 (void)signal(SIGINT2, oldintr);
999 (void)signal(SIGINFO29, oldinti);
1000 return;
1001 }
1002 } else {
1003 if (command("%s", cmd) != PRELIM1) {
1004 (void)signal(SIGINT2, oldintr);
1005 (void)signal(SIGINFO29, oldinti);
1006 return;
1007 }
1008 }
1009 din = dataconn("r");
1010 if (din == NULL((void*)0))
1011 goto abort;
1012 if (!ignorespecial && strcmp(local, "-") == 0) {
1013 fout = stdout(&__sF[1]);
1014 preserve = 0;
1015 } else if (!ignorespecial && *local == '|') {
1016 oldintp = signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
1017 fout = popen(local + 1, "w");
1018 if (fout == NULL((void*)0)) {
1019 warn("%s", local+1);
1020 goto abort;
1021 }
1022 if (progress == 1)
1023 progress = 0;
1024 preserve = 0;
1025 closefunc = pclose;
1026 } else {
1027 fout = fopen(local, lmode);
1028 if (fout == NULL((void*)0)) {
1029 warn("local: %s", local);
1030 goto abort;
1031 }
1032 closefunc = fclose;
1033 }
1034 if (fstat(fileno(fout)(!__isthreaded ? ((fout)->_file) : (fileno)(fout)), &st) == -1 || st.st_blksize == 0)
1035 st.st_blksize = BUFSIZ1024;
1036 if (st.st_blksize > bufsize) {
1037 (void)free(buf);
1038 buf = malloc((unsigned)st.st_blksize);
1039 if (buf == NULL((void*)0)) {
1040 warn("malloc");
1041 bufsize = 0;
1042 goto abort;
1043 }
1044 bufsize = st.st_blksize;
1045 }
1046 if ((st.st_mode & S_IFMT0170000) != S_IFREG0100000) {
1047 if (progress == 1)
1048 progress = 0;
1049 preserve = 0;
1050 }
1051 progressmeter(-1, remote);
1052 may_reset_noop_timeout();
1053 serrno = 0;
1054 switch (curtype) {
1055
1056 case TYPE_I3:
1057 if (restart_point &&
1058 lseek(fileno(fout)(!__isthreaded ? ((fout)->_file) : (fileno)(fout)), restart_point, SEEK_SET0) == -1) {
1059 warn("local: %s", local);
1060 progress = oprogress;
1061 preserve = opreserve;
1062 if (closefunc != NULL((void*)0))
1063 (*closefunc)(fout);
1064 return;
1065 }
1066 errno(*__errno()) = d = 0;
1067 while ((c = read(fileno(din)(!__isthreaded ? ((din)->_file) : (fileno)(din)), buf, bufsize)) > 0) {
1068 ssize_t wr;
1069 size_t rd = c;
1070
1071 may_send_noop_char();
1072 d = 0;
1073 do {
1074 wr = write(fileno(fout)(!__isthreaded ? ((fout)->_file) : (fileno)(fout)), buf + d, rd);
1075 if (wr == -1) {
1076 d = -1;
1077 break;
1078 }
1079 d += wr;
1080 rd -= wr;
1081 } while (d < c);
1082 if (rd != 0)
1083 break;
1084 bytes += c;
1085 if (hash && (!progress || filesize < 0)) {
1086 while (bytes >= hashbytes) {
1087 (void)putc('#', ttyout)(!__isthreaded ? __sputc('#', ttyout) : (putc)('#', ttyout));
1088 hashbytes += mark;
1089 }
1090 (void)fflush(ttyout);
1091 }
1092 }
1093 if (c == -1 || d < c)
1094 serrno = errno(*__errno());
1095 if (hash && (!progress || filesize < 0) && bytes > 0) {
1096 if (bytes < mark)
1097 (void)putc('#', ttyout)(!__isthreaded ? __sputc('#', ttyout) : (putc)('#', ttyout));
1098 (void)putc('\n', ttyout)(!__isthreaded ? __sputc('\n', ttyout) : (putc)('\n', ttyout)
)
;
1099 (void)fflush(ttyout);
1100 }
1101 if (c < 0) {
1102 if (serrno != EPIPE32)
1103 warnc(serrno, "netin");
1104 bytes = -1;
1105 }
1106 if (d < c) {
1107 if (d < 0)
1108 warnc(serrno, "local: %s", local);
1109 else
1110 warnx("%s: short write", local);
1111 }
1112 break;
1113
1114 case TYPE_A1:
1115 if (restart_point) {
1116 int i, n, ch;
1117
1118 if (fseek(fout, 0L, SEEK_SET0) == -1)
1119 goto done;
1120 n = restart_point;
1121 for (i = 0; i++ < n;) {
1122 if ((ch = fgetc(fout)) == EOF(-1)) {
1123 if (!ferror(fout)(!__isthreaded ? (((fout)->_flags & 0x0040) != 0) : (ferror
)(fout))
)
1124 errno(*__errno()) = 0;
1125 goto done;
1126 }
1127 if (ch == '\n')
1128 i++;
1129 }
1130 if (fseek(fout, 0L, SEEK_CUR1) == -1) {
1131done:
1132 if (errno(*__errno()))
1133 warn("local: %s", local);
1134 else
1135 warnx("local: %s", local);
1136 progress = oprogress;
1137 preserve = opreserve;
1138 if (closefunc != NULL((void*)0))
1139 (*closefunc)(fout);
1140 return;
1141 }
1142 }
1143 while ((c = fgetc(din)) != EOF(-1)) {
1144 may_send_noop_char();
1145 if (c == '\n')
1146 bare_lfs++;
1147 while (c == '\r') {
1148 while (hash && (!progress || filesize < 0) &&
1149 (bytes >= hashbytes)) {
1150 (void)putc('#', ttyout)(!__isthreaded ? __sputc('#', ttyout) : (putc)('#', ttyout));
1151 (void)fflush(ttyout);
1152 hashbytes += mark;
1153 }
1154 bytes++;
1155 if ((c = fgetc(din)) != '\n' || tcrflag) {
1156 if (ferror(fout)(!__isthreaded ? (((fout)->_flags & 0x0040) != 0) : (ferror
)(fout))
)
1157 goto break2;
1158 (void)putc('\r', fout)(!__isthreaded ? __sputc('\r', fout) : (putc)('\r', fout));
1159 if (c == '\0') {
1160 bytes++;
1161 goto contin2;
1162 }
1163 if (c == EOF(-1))
1164 goto contin2;
1165 }
1166 }
1167 (void)putc(c, fout)(!__isthreaded ? __sputc(c, fout) : (putc)(c, fout));
1168 bytes++;
1169 contin2: ;
1170 }
1171break2:
1172 if (ferror(din)(!__isthreaded ? (((din)->_flags & 0x0040) != 0) : (ferror
)(din))
|| ferror(fout)(!__isthreaded ? (((fout)->_flags & 0x0040) != 0) : (ferror
)(fout))
)
1173 serrno = errno(*__errno());
1174 if (bare_lfs) {
1175 fprintf(ttyout,
1176"WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs);
1177 fputs("File may not have transferred correctly.\n",
1178 ttyout);
1179 }
1180 if (hash && (!progress || filesize < 0)) {
1181 if (bytes < hashbytes)
1182 (void)putc('#', ttyout)(!__isthreaded ? __sputc('#', ttyout) : (putc)('#', ttyout));
1183 (void)putc('\n', ttyout)(!__isthreaded ? __sputc('\n', ttyout) : (putc)('\n', ttyout)
)
;
1184 (void)fflush(ttyout);
1185 }
1186 if (ferror(din)(!__isthreaded ? (((din)->_flags & 0x0040) != 0) : (ferror
)(din))
) {
1187 if (serrno != EPIPE32)
1188 warnc(serrno, "netin");
1189 bytes = -1;
1190 }
1191 if (ferror(fout)(!__isthreaded ? (((fout)->_flags & 0x0040) != 0) : (ferror
)(fout))
)
1192 warnc(serrno, "local: %s", local);
1193 break;
1194 }
1195 progressmeter(1, NULL((void*)0));
1196 progress = oprogress;
1197 preserve = opreserve;
1198 if (closefunc != NULL((void*)0))
1199 (*closefunc)(fout);
1200 (void)signal(SIGINT2, oldintr);
1201 (void)signal(SIGINFO29, oldinti);
1202 if (oldintp)
1203 (void)signal(SIGPIPE13, oldintp);
1204 (void)fclose(din);
1205 (void)getreply(0);
1206 may_receive_noop_ack();
1207 if (bytes >= 0 && is_retr) {
1208 if (bytes > 0)
1209 ptransfer(0);
1210 if (preserve && (closefunc == fclose)) {
1211 mtime = remotemodtime(remote, 0);
1212 if (mtime != -1) {
1213 struct timespec times[2];
1214
1215 times[0].tv_nsec = UTIME_OMIT-1L;
1216 times[1].tv_sec = mtime;
1217 times[1].tv_nsec = 0;
1218 if (utimensat(AT_FDCWD-100, local, times, 0) == -1)
1219 fprintf(ttyout,
1220 "Can't change modification time on %s to %s",
1221 local, asctime(localtime(&mtime)));
1222 }
1223 }
1224 }
1225 return;
1226
1227abort:
1228 /* abort using RFC959 recommended IP,SYNC sequence */
1229 progress = oprogress;
1230 preserve = opreserve;
1231 if (oldintp)
1232 (void)signal(SIGPIPE13, oldintp);
1233 (void)signal(SIGINT2, SIG_IGN(void (*)(int))1);
1234 if (!cpend) {
1235 code = -1;
1236 (void)signal(SIGINT2, oldintr);
1237 (void)signal(SIGINFO29, oldinti);
1238 return;
1239 }
1240
1241 abort_remote(din);
1242 code = -1;
1243 if (data >= 0) {
1244 (void)close(data);
1245 data = -1;
1246 }
1247 if (closefunc != NULL((void*)0) && fout != NULL((void*)0))
1248 (*closefunc)(fout);
1249 if (din)
1250 (void)fclose(din);
1251 if (bytes > 0)
1252 ptransfer(0);
1253 (void)signal(SIGINT2, oldintr);
1254 (void)signal(SIGINFO29, oldinti);
1255}
1256
1257/*
1258 * Need to start a listen on the data channel before we send the command,
1259 * otherwise the server's connect may fail.
1260 */
1261int
1262initconn(void)
1263{
1264 char *p, *a;
1265 int result = ERROR5, tmpno = 0;
1266 int on = 1;
1267 int error;
1268 u_int addr[16], port[2];
1269 u_int af, hal, pal;
1270 char *pasvcmd = NULL((void*)0);
1271 socklen_t namelen;
1272#ifndef SMALL
1273 struct addrinfo *ares;
1274#endif
1275
1276 if (myctladdr.sa.sa_family == AF_INET624
1277 && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.sin6.sin6_addr)(((&myctladdr.sin6.sin6_addr)->__u6_addr.__u6_addr8[0]
== 0xfe) && (((&myctladdr.sin6.sin6_addr)->__u6_addr
.__u6_addr8[1] & 0xc0) == 0x80))
1278 || IN6_IS_ADDR_SITELOCAL(&myctladdr.sin6.sin6_addr)(((&myctladdr.sin6.sin6_addr)->__u6_addr.__u6_addr8[0]
== 0xfe) && (((&myctladdr.sin6.sin6_addr)->__u6_addr
.__u6_addr8[1] & 0xc0) == 0xc0))
)) {
1279 warnx("use of scoped address can be troublesome");
1280 }
1281#ifndef SMALL
1282 if (srcaddr) {
1283 struct addrinfo ahints;
1284
1285 memset(&ahints, 0, sizeof(ahints));
1286 ahints.ai_family = family;
1287 ahints.ai_socktype = SOCK_STREAM1;
1288 ahints.ai_flags |= AI_NUMERICHOST4;
1289 ahints.ai_protocol = 0;
1290
1291 error = getaddrinfo(srcaddr, NULL((void*)0), &ahints, &ares);
1292 if (error) {
1293 warnx("%s: %s", srcaddr, gai_strerror(error));
1294 code = -1;
1295 return (0);
1296 }
1297 }
1298#endif /* !SMALL */
1299reinit:
1300 if (passivemode) {
1301 data_addr = myctladdr;
1302 data = socket(data_addr.sa.sa_family, SOCK_STREAM1, 0);
1303 if (data == -1) {
1304 warn("socket");
1305 return (1);
1306 }
1307#ifndef SMALL
1308 if (srcaddr) {
1309 if (bind(data, ares->ai_addr, ares->ai_addrlen) == -1) {
1310 warn("bind");
1311 close(data);
1312 return (1);
1313 }
1314 }
1315 if ((options & SO_DEBUG0x0001) &&
1316 setsockopt(data, SOL_SOCKET0xffff, SO_DEBUG0x0001, (char *)&on,
1317 sizeof(on)) == -1)
1318 warn("setsockopt (ignored)");
1319#endif /* !SMALL */
1320 switch (data_addr.sa.sa_family) {
1321 case AF_INET2:
1322 if (epsv4 && !epsv4bad) {
1323 int ov;
1324 /* shut this command up in case it fails */
1325 ov = verbose;
1326 verbose = -1;
1327 result = command(pasvcmd = "EPSV");
1328 /*
1329 * now back to whatever verbosity we had before
1330 * and we can try PASV
1331 */
1332 verbose = ov;
1333 if (code / 10 == 22 && code != 229) {
1334 fputs(
1335"wrong server: return code must be 229\n",
1336 ttyout);
1337 result = COMPLETE2 + 1;
1338 }
1339 if (result != COMPLETE2) {
1340 epsv4bad = 1;
1341#ifndef SMALL
1342 if (debug) {
1343 fputs(
1344"disabling epsv4 for this connection\n",
1345 ttyout);
1346 }
1347#endif /* !SMALL */
1348 }
1349 }
1350 if (result != COMPLETE2)
1351 result = command(pasvcmd = "PASV");
1352 break;
1353 case AF_INET624:
1354 result = command(pasvcmd = "EPSV");
1355 if (code / 10 == 22 && code != 229) {
1356 fputs(
1357"wrong server: return code must be 229\n",
1358 ttyout);
1359 result = COMPLETE2 + 1;
1360 }
1361 if (result != COMPLETE2)
1362 result = command(pasvcmd = "LPSV");
1363 break;
1364 default:
1365 result = COMPLETE2 + 1;
1366 break;
1367 }
1368 if (result != COMPLETE2) {
1369 if (activefallback) {
1370 (void)close(data);
1371 data = -1;
1372 passivemode = 0;
1373 activefallback = 0;
1374 goto reinit;
1375 }
1376 fputs("Passive mode refused.\n", ttyout);
1377 goto bad;
1378 }
1379
1380#define pack2(var, off)(((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] &
0xff) << 0))
\
1381 (((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0))
1382#define pack4(var, off)(((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1]
& 0xff) << 16) | ((var[(off) + 2] & 0xff) <<
8) | ((var[(off) + 3] & 0xff) << 0))
\
1383 (((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \
1384 ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0))
1385
1386 /*
1387 * What we've got at this point is a string of comma separated
1388 * one-byte unsigned integer values, separated by commas.
1389 */
1390 if (!pasvcmd)
1391 goto bad;
1392 if (strcmp(pasvcmd, "PASV") == 0) {
1393 if (data_addr.sa.sa_family != AF_INET2) {
1394 fputs(
1395"Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1396 goto bad;
1397 }
1398 if (code / 10 == 22 && code != 227) {
1399 fputs("wrong server: return code must be 227\n",
1400 ttyout);
1401 goto bad;
1402 }
1403 error = sscanf(pasv, "%u,%u,%u,%u,%u,%u",
1404 &addr[0], &addr[1], &addr[2], &addr[3],
1405 &port[0], &port[1]);
1406 if (error != 6) {
1407 fputs(
1408"Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1409 goto bad;
1410 }
1411 memset(&data_addr, 0, sizeof(data_addr));
1412 data_addr.sin.sin_family = AF_INET2;
1413 data_addr.sin.sin_len = sizeof(struct sockaddr_in);
1414 data_addr.sin.sin_addr.s_addr =
1415 htonl(pack4(addr, 0))(__uint32_t)(__builtin_constant_p((((addr[(0) + 0] & 0xff
) << 24) | ((addr[(0) + 1] & 0xff) << 16) | (
(addr[(0) + 2] & 0xff) << 8) | ((addr[(0) + 3] &
0xff) << 0))) ? (__uint32_t)(((__uint32_t)((((addr[(0)
+ 0] & 0xff) << 24) | ((addr[(0) + 1] & 0xff) <<
16) | ((addr[(0) + 2] & 0xff) << 8) | ((addr[(0) +
3] & 0xff) << 0))) & 0xff) << 24 | ((__uint32_t
)((((addr[(0) + 0] & 0xff) << 24) | ((addr[(0) + 1]
& 0xff) << 16) | ((addr[(0) + 2] & 0xff) <<
8) | ((addr[(0) + 3] & 0xff) << 0))) & 0xff00)
<< 8 | ((__uint32_t)((((addr[(0) + 0] & 0xff) <<
24) | ((addr[(0) + 1] & 0xff) << 16) | ((addr[(0) +
2] & 0xff) << 8) | ((addr[(0) + 3] & 0xff) <<
0))) & 0xff0000) >> 8 | ((__uint32_t)((((addr[(0) +
0] & 0xff) << 24) | ((addr[(0) + 1] & 0xff) <<
16) | ((addr[(0) + 2] & 0xff) << 8) | ((addr[(0) +
3] & 0xff) << 0))) & 0xff000000) >> 24) :
__swap32md((((addr[(0) + 0] & 0xff) << 24) | ((addr
[(0) + 1] & 0xff) << 16) | ((addr[(0) + 2] & 0xff
) << 8) | ((addr[(0) + 3] & 0xff) << 0))))
;
1416 data_addr.sin.sin_port = htons(pack2(port, 0))(__uint16_t)(__builtin_constant_p((((port[(0) + 0] & 0xff
) << 8) | ((port[(0) + 1] & 0xff) << 0))) ? (
__uint16_t)(((__uint16_t)((((port[(0) + 0] & 0xff) <<
8) | ((port[(0) + 1] & 0xff) << 0))) & 0xffU) <<
8 | ((__uint16_t)((((port[(0) + 0] & 0xff) << 8) |
((port[(0) + 1] & 0xff) << 0))) & 0xff00U) >>
8) : __swap16md((((port[(0) + 0] & 0xff) << 8) | (
(port[(0) + 1] & 0xff) << 0))))
;
1417 } else if (strcmp(pasvcmd, "LPSV") == 0) {
1418 if (code / 10 == 22 && code != 228) {
1419 fputs("wrong server: return code must be 228\n",
1420 ttyout);
1421 goto bad;
1422 }
1423 switch (data_addr.sa.sa_family) {
1424 case AF_INET2:
1425 error = sscanf(pasv,
1426"%u,%u,%u,%u,%u,%u,%u,%u,%u",
1427 &af, &hal,
1428 &addr[0], &addr[1], &addr[2], &addr[3],
1429 &pal, &port[0], &port[1]);
1430 if (error != 9) {
1431 fputs(
1432"Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1433 goto bad;
1434 }
1435 if (af != 4 || hal != 4 || pal != 2) {
1436 fputs(
1437"Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1438 error = 1;
1439 goto bad;
1440 }
1441
1442 memset(&data_addr, 0, sizeof(data_addr));
1443 data_addr.sin.sin_family = AF_INET2;
1444 data_addr.sin.sin_len = sizeof(struct sockaddr_in);
1445 data_addr.sin.sin_addr.s_addr =
1446 htonl(pack4(addr, 0))(__uint32_t)(__builtin_constant_p((((addr[(0) + 0] & 0xff
) << 24) | ((addr[(0) + 1] & 0xff) << 16) | (
(addr[(0) + 2] & 0xff) << 8) | ((addr[(0) + 3] &
0xff) << 0))) ? (__uint32_t)(((__uint32_t)((((addr[(0)
+ 0] & 0xff) << 24) | ((addr[(0) + 1] & 0xff) <<
16) | ((addr[(0) + 2] & 0xff) << 8) | ((addr[(0) +
3] & 0xff) << 0))) & 0xff) << 24 | ((__uint32_t
)((((addr[(0) + 0] & 0xff) << 24) | ((addr[(0) + 1]
& 0xff) << 16) | ((addr[(0) + 2] & 0xff) <<
8) | ((addr[(0) + 3] & 0xff) << 0))) & 0xff00)
<< 8 | ((__uint32_t)((((addr[(0) + 0] & 0xff) <<
24) | ((addr[(0) + 1] & 0xff) << 16) | ((addr[(0) +
2] & 0xff) << 8) | ((addr[(0) + 3] & 0xff) <<
0))) & 0xff0000) >> 8 | ((__uint32_t)((((addr[(0) +
0] & 0xff) << 24) | ((addr[(0) + 1] & 0xff) <<
16) | ((addr[(0) + 2] & 0xff) << 8) | ((addr[(0) +
3] & 0xff) << 0))) & 0xff000000) >> 24) :
__swap32md((((addr[(0) + 0] & 0xff) << 24) | ((addr
[(0) + 1] & 0xff) << 16) | ((addr[(0) + 2] & 0xff
) << 8) | ((addr[(0) + 3] & 0xff) << 0))))
;
1447 data_addr.sin.sin_port = htons(pack2(port, 0))(__uint16_t)(__builtin_constant_p((((port[(0) + 0] & 0xff
) << 8) | ((port[(0) + 1] & 0xff) << 0))) ? (
__uint16_t)(((__uint16_t)((((port[(0) + 0] & 0xff) <<
8) | ((port[(0) + 1] & 0xff) << 0))) & 0xffU) <<
8 | ((__uint16_t)((((port[(0) + 0] & 0xff) << 8) |
((port[(0) + 1] & 0xff) << 0))) & 0xff00U) >>
8) : __swap16md((((port[(0) + 0] & 0xff) << 8) | (
(port[(0) + 1] & 0xff) << 0))))
;
1448 break;
1449 case AF_INET624:
1450 error = sscanf(pasv,
1451"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
1452 &af, &hal,
1453 &addr[0], &addr[1], &addr[2], &addr[3],
1454 &addr[4], &addr[5], &addr[6], &addr[7],
1455 &addr[8], &addr[9], &addr[10],
1456 &addr[11], &addr[12], &addr[13],
1457 &addr[14], &addr[15],
1458 &pal, &port[0], &port[1]);
1459 if (error != 21) {
1460 fputs(
1461"Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1462 goto bad;
1463 }
1464 if (af != 6 || hal != 16 || pal != 2) {
1465 fputs(
1466"Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1467 goto bad;
1468 }
1469
1470 memset(&data_addr, 0, sizeof(data_addr));
1471 data_addr.sin6.sin6_family = AF_INET624;
1472 data_addr.sin6.sin6_len = sizeof(struct sockaddr_in6);
1473 {
1474 u_int32_t *p32;
1475 p32 = (u_int32_t *)&data_addr.sin6.sin6_addr;
1476 p32[0] = htonl(pack4(addr, 0))(__uint32_t)(__builtin_constant_p((((addr[(0) + 0] & 0xff
) << 24) | ((addr[(0) + 1] & 0xff) << 16) | (
(addr[(0) + 2] & 0xff) << 8) | ((addr[(0) + 3] &
0xff) << 0))) ? (__uint32_t)(((__uint32_t)((((addr[(0)
+ 0] & 0xff) << 24) | ((addr[(0) + 1] & 0xff) <<
16) | ((addr[(0) + 2] & 0xff) << 8) | ((addr[(0) +
3] & 0xff) << 0))) & 0xff) << 24 | ((__uint32_t
)((((addr[(0) + 0] & 0xff) << 24) | ((addr[(0) + 1]
& 0xff) << 16) | ((addr[(0) + 2] & 0xff) <<
8) | ((addr[(0) + 3] & 0xff) << 0))) & 0xff00)
<< 8 | ((__uint32_t)((((addr[(0) + 0] & 0xff) <<
24) | ((addr[(0) + 1] & 0xff) << 16) | ((addr[(0) +
2] & 0xff) << 8) | ((addr[(0) + 3] & 0xff) <<
0))) & 0xff0000) >> 8 | ((__uint32_t)((((addr[(0) +
0] & 0xff) << 24) | ((addr[(0) + 1] & 0xff) <<
16) | ((addr[(0) + 2] & 0xff) << 8) | ((addr[(0) +
3] & 0xff) << 0))) & 0xff000000) >> 24) :
__swap32md((((addr[(0) + 0] & 0xff) << 24) | ((addr
[(0) + 1] & 0xff) << 16) | ((addr[(0) + 2] & 0xff
) << 8) | ((addr[(0) + 3] & 0xff) << 0))))
;
1477 p32[1] = htonl(pack4(addr, 4))(__uint32_t)(__builtin_constant_p((((addr[(4) + 0] & 0xff
) << 24) | ((addr[(4) + 1] & 0xff) << 16) | (
(addr[(4) + 2] & 0xff) << 8) | ((addr[(4) + 3] &
0xff) << 0))) ? (__uint32_t)(((__uint32_t)((((addr[(4)
+ 0] & 0xff) << 24) | ((addr[(4) + 1] & 0xff) <<
16) | ((addr[(4) + 2] & 0xff) << 8) | ((addr[(4) +
3] & 0xff) << 0))) & 0xff) << 24 | ((__uint32_t
)((((addr[(4) + 0] & 0xff) << 24) | ((addr[(4) + 1]
& 0xff) << 16) | ((addr[(4) + 2] & 0xff) <<
8) | ((addr[(4) + 3] & 0xff) << 0))) & 0xff00)
<< 8 | ((__uint32_t)((((addr[(4) + 0] & 0xff) <<
24) | ((addr[(4) + 1] & 0xff) << 16) | ((addr[(4) +
2] & 0xff) << 8) | ((addr[(4) + 3] & 0xff) <<
0))) & 0xff0000) >> 8 | ((__uint32_t)((((addr[(4) +
0] & 0xff) << 24) | ((addr[(4) + 1] & 0xff) <<
16) | ((addr[(4) + 2] & 0xff) << 8) | ((addr[(4) +
3] & 0xff) << 0))) & 0xff000000) >> 24) :
__swap32md((((addr[(4) + 0] & 0xff) << 24) | ((addr
[(4) + 1] & 0xff) << 16) | ((addr[(4) + 2] & 0xff
) << 8) | ((addr[(4) + 3] & 0xff) << 0))))
;
1478 p32[2] = htonl(pack4(addr, 8))(__uint32_t)(__builtin_constant_p((((addr[(8) + 0] & 0xff
) << 24) | ((addr[(8) + 1] & 0xff) << 16) | (
(addr[(8) + 2] & 0xff) << 8) | ((addr[(8) + 3] &
0xff) << 0))) ? (__uint32_t)(((__uint32_t)((((addr[(8)
+ 0] & 0xff) << 24) | ((addr[(8) + 1] & 0xff) <<
16) | ((addr[(8) + 2] & 0xff) << 8) | ((addr[(8) +
3] & 0xff) << 0))) & 0xff) << 24 | ((__uint32_t
)((((addr[(8) + 0] & 0xff) << 24) | ((addr[(8) + 1]
& 0xff) << 16) | ((addr[(8) + 2] & 0xff) <<
8) | ((addr[(8) + 3] & 0xff) << 0))) & 0xff00)
<< 8 | ((__uint32_t)((((addr[(8) + 0] & 0xff) <<
24) | ((addr[(8) + 1] & 0xff) << 16) | ((addr[(8) +
2] & 0xff) << 8) | ((addr[(8) + 3] & 0xff) <<
0))) & 0xff0000) >> 8 | ((__uint32_t)((((addr[(8) +
0] & 0xff) << 24) | ((addr[(8) + 1] & 0xff) <<
16) | ((addr[(8) + 2] & 0xff) << 8) | ((addr[(8) +
3] & 0xff) << 0))) & 0xff000000) >> 24) :
__swap32md((((addr[(8) + 0] & 0xff) << 24) | ((addr
[(8) + 1] & 0xff) << 16) | ((addr[(8) + 2] & 0xff
) << 8) | ((addr[(8) + 3] & 0xff) << 0))))
;
1479 p32[3] = htonl(pack4(addr, 12))(__uint32_t)(__builtin_constant_p((((addr[(12) + 0] & 0xff
) << 24) | ((addr[(12) + 1] & 0xff) << 16) | (
(addr[(12) + 2] & 0xff) << 8) | ((addr[(12) + 3] &
0xff) << 0))) ? (__uint32_t)(((__uint32_t)((((addr[(12
) + 0] & 0xff) << 24) | ((addr[(12) + 1] & 0xff
) << 16) | ((addr[(12) + 2] & 0xff) << 8) | (
(addr[(12) + 3] & 0xff) << 0))) & 0xff) <<
24 | ((__uint32_t)((((addr[(12) + 0] & 0xff) << 24
) | ((addr[(12) + 1] & 0xff) << 16) | ((addr[(12) +
2] & 0xff) << 8) | ((addr[(12) + 3] & 0xff) <<
0))) & 0xff00) << 8 | ((__uint32_t)((((addr[(12) +
0] & 0xff) << 24) | ((addr[(12) + 1] & 0xff) <<
16) | ((addr[(12) + 2] & 0xff) << 8) | ((addr[(12)
+ 3] & 0xff) << 0))) & 0xff0000) >> 8 | (
(__uint32_t)((((addr[(12) + 0] & 0xff) << 24) | ((addr
[(12) + 1] & 0xff) << 16) | ((addr[(12) + 2] & 0xff
) << 8) | ((addr[(12) + 3] & 0xff) << 0))) &
0xff000000) >> 24) : __swap32md((((addr[(12) + 0] &
0xff) << 24) | ((addr[(12) + 1] & 0xff) << 16
) | ((addr[(12) + 2] & 0xff) << 8) | ((addr[(12) + 3
] & 0xff) << 0))))
;
1480 }
1481 data_addr.sin6.sin6_port = htons(pack2(port, 0))(__uint16_t)(__builtin_constant_p((((port[(0) + 0] & 0xff
) << 8) | ((port[(0) + 1] & 0xff) << 0))) ? (
__uint16_t)(((__uint16_t)((((port[(0) + 0] & 0xff) <<
8) | ((port[(0) + 1] & 0xff) << 0))) & 0xffU) <<
8 | ((__uint16_t)((((port[(0) + 0] & 0xff) << 8) |
((port[(0) + 1] & 0xff) << 0))) & 0xff00U) >>
8) : __swap16md((((port[(0) + 0] & 0xff) << 8) | (
(port[(0) + 1] & 0xff) << 0))))
;
1482 break;
1483 default:
1484 fputs("Bad family!\n", ttyout);
1485 goto bad;
1486 }
1487 } else if (strcmp(pasvcmd, "EPSV") == 0) {
1488 char delim[4];
1489
1490 port[0] = 0;
1491 if (code / 10 == 22 && code != 229) {
1492 fputs("wrong server: return code must be 229\n",
1493 ttyout);
1494 goto bad;
1495 }
1496 if (sscanf(pasv, "%c%c%c%d%c", &delim[0],
1497 &delim[1], &delim[2], &port[1],
1498 &delim[3]) != 5) {
1499 fputs("parse error!\n", ttyout);
1500 goto bad;
1501 }
1502 if (delim[0] != delim[1] || delim[0] != delim[2]
1503 || delim[0] != delim[3]) {
1504 fputs("parse error!\n", ttyout);
1505 goto bad;
1506 }
1507 data_addr = hisctladdr;
1508 data_addr.sin.sin_port = htons(port[1])(__uint16_t)(__builtin_constant_p(port[1]) ? (__uint16_t)(((__uint16_t
)(port[1]) & 0xffU) << 8 | ((__uint16_t)(port[1]) &
0xff00U) >> 8) : __swap16md(port[1]))
;
1509 } else
1510 goto bad;
1511
1512 for (error = connect(data, &data_addr.sa, data_addr.sa.sa_len);
1513 error != 0 && errno(*__errno()) == EINTR4;
1514 error = connect_wait(data))
1515 continue;
1516 if (error != 0) {
1517 if (activefallback) {
1518 (void)close(data);
1519 data = -1;
1520 passivemode = 0;
1521 activefallback = 0;
1522 goto reinit;
1523 }
1524 warn("connect");
1525 goto bad;
1526 }
1527 if (data_addr.sa.sa_family == AF_INET2) {
1528 on = IPTOS_THROUGHPUT0x08;
1529 if (setsockopt(data, IPPROTO_IP0, IP_TOS3, (char *)&on,
1530 sizeof(int)) == -1)
1531 warn("setsockopt TOS (ignored)");
1532 }
1533 return (0);
1534 }
1535
1536noport:
1537 data_addr = myctladdr;
1538 if (sendport)
1539 data_addr.sin.sin_port = 0; /* let system pick one */
1540 if (data != -1)
1541 (void)close(data);
1542 data = socket(data_addr.sa.sa_family, SOCK_STREAM1, 0);
1543 if (data == -1) {
1544 warn("socket");
1545 if (tmpno)
1546 sendport = 1;
1547 return (1);
1548 }
1549 if (!sendport)
1550 if (setsockopt(data, SOL_SOCKET0xffff, SO_REUSEADDR0x0004, (char *)&on,
1551 sizeof(on)) == -1) {
1552 warn("setsockopt (reuse address)");
1553 goto bad;
1554 }
1555 switch (data_addr.sa.sa_family) {
1556 case AF_INET2:
1557 on = IP_PORTRANGE_HIGH1;
1558 if (setsockopt(data, IPPROTO_IP0, IP_PORTRANGE19,
1559 (char *)&on, sizeof(on)) == -1)
1560 warn("setsockopt IP_PORTRANGE (ignored)");
1561 break;
1562 case AF_INET624:
1563 on = IPV6_PORTRANGE_HIGH1;
1564 if (setsockopt(data, IPPROTO_IPV641, IPV6_PORTRANGE14,
1565 (char *)&on, sizeof(on)) == -1)
1566 warn("setsockopt IPV6_PORTRANGE (ignored)");
1567 break;
1568 }
1569 if (bind(data, &data_addr.sa, data_addr.sa.sa_len) == -1) {
1570 warn("bind");
1571 goto bad;
1572 }
1573#ifndef SMALL
1574 if (options & SO_DEBUG0x0001 &&
1575 setsockopt(data, SOL_SOCKET0xffff, SO_DEBUG0x0001, (char *)&on,
1576 sizeof(on)) == -1)
1577 warn("setsockopt (ignored)");
1578#endif /* !SMALL */
1579 namelen = sizeof(data_addr);
1580 if (getsockname(data, &data_addr.sa, &namelen) == -1) {
1581 warn("getsockname");
1582 goto bad;
1583 }
1584 if (listen(data, 1) == -1)
1585 warn("listen");
1586
1587#define UC(b)(((int)b)&0xff) (((int)b)&0xff)
1588
1589 if (sendport) {
1590 char hname[NI_MAXHOST256], pbuf[NI_MAXSERV32];
1591 int af_tmp;
1592 union sockaddr_union tmp;
1593
1594 tmp = data_addr;
1595 switch (tmp.sa.sa_family) {
1596 case AF_INET2:
1597 if (!epsv4 || epsv4bad) {
1598 result = COMPLETE2 +1;
1599 break;
1600 }
1601 /*FALLTHROUGH*/
1602 case AF_INET624:
1603 if (tmp.sa.sa_family == AF_INET624)
1604 tmp.sin6.sin6_scope_id = 0;
1605 af_tmp = (tmp.sa.sa_family == AF_INET2) ? 1 : 2;
1606 if (getnameinfo(&tmp.sa, tmp.sa.sa_len, hname,
1607 sizeof(hname), pbuf, sizeof(pbuf),
1608 NI_NUMERICHOST1 | NI_NUMERICSERV2)) {
1609 result = ERROR5;
1610 } else {
1611 result = command("EPRT |%d|%s|%s|",
1612 af_tmp, hname, pbuf);
1613 if (result != COMPLETE2) {
1614 epsv4bad = 1;
1615#ifndef SMALL
1616 if (debug) {
1617 fputs(
1618"disabling epsv4 for this connection\n",
1619 ttyout);
1620 }
1621#endif /* !SMALL */
1622 }
1623 }
1624 break;
1625 default:
1626 result = COMPLETE2 + 1;
1627 break;
1628 }
1629 if (result == COMPLETE2)
1630 goto skip_port;
1631
1632 switch (data_addr.sa.sa_family) {
1633 case AF_INET2:
1634 a = (char *)&data_addr.sin.sin_addr;
1635 p = (char *)&data_addr.sin.sin_port;
1636 result = command("PORT %d,%d,%d,%d,%d,%d",
1637 UC(a[0])(((int)a[0])&0xff), UC(a[1])(((int)a[1])&0xff), UC(a[2])(((int)a[2])&0xff), UC(a[3])(((int)a[3])&0xff),
1638 UC(p[0])(((int)p[0])&0xff), UC(p[1])(((int)p[1])&0xff));
1639 break;
1640 case AF_INET624:
1641 a = (char *)&data_addr.sin6.sin6_addr;
1642 p = (char *)&data_addr.sin6.sin6_port;
1643 result = command(
1644"LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
1645 6, 16,
1646 UC(a[0])(((int)a[0])&0xff),UC(a[1])(((int)a[1])&0xff),UC(a[2])(((int)a[2])&0xff),UC(a[3])(((int)a[3])&0xff),
1647 UC(a[4])(((int)a[4])&0xff),UC(a[5])(((int)a[5])&0xff),UC(a[6])(((int)a[6])&0xff),UC(a[7])(((int)a[7])&0xff),
1648 UC(a[8])(((int)a[8])&0xff),UC(a[9])(((int)a[9])&0xff),UC(a[10])(((int)a[10])&0xff),UC(a[11])(((int)a[11])&0xff),
1649 UC(a[12])(((int)a[12])&0xff),UC(a[13])(((int)a[13])&0xff),UC(a[14])(((int)a[14])&0xff),UC(a[15])(((int)a[15])&0xff),
1650 2, UC(p[0])(((int)p[0])&0xff), UC(p[1])(((int)p[1])&0xff));
1651 break;
1652 default:
1653 result = COMPLETE2 + 1; /* xxx */
1654 }
1655 skip_port:
1656
1657 if (result == ERROR5 && sendport == -1) {
1658 sendport = 0;
1659 tmpno = 1;
1660 goto noport;
1661 }
1662 return (result != COMPLETE2);
1663 }
1664 if (tmpno)
1665 sendport = 1;
1666 if (data_addr.sa.sa_family == AF_INET2) {
1667 on = IPTOS_THROUGHPUT0x08;
1668 if (setsockopt(data, IPPROTO_IP0, IP_TOS3, (char *)&on,
1669 sizeof(int)) == -1)
1670 warn("setsockopt TOS (ignored)");
1671 }
1672 return (0);
1673bad:
1674 (void)close(data), data = -1;
1675 if (tmpno)
1676 sendport = 1;
1677 return (1);
1678}
1679
1680FILE *
1681dataconn(const char *lmode)
1682{
1683 union sockaddr_union from;
1684 socklen_t fromlen = myctladdr.sa.sa_len;
1685 int s;
1686
1687 if (passivemode)
1688 return (fdopen(data, lmode));
1689
1690 s = accept(data, &from.sa, &fromlen);
1691 if (s == -1) {
1692 warn("accept");
1693 (void)close(data), data = -1;
1694 return (NULL((void*)0));
1695 }
1696 (void)close(data);
1697 data = s;
1698 if (from.sa.sa_family == AF_INET2) {
1699 int tos = IPTOS_THROUGHPUT0x08;
1700 if (setsockopt(s, IPPROTO_IP0, IP_TOS3, (char *)&tos,
1701 sizeof(int)) == -1) {
1702 warn("setsockopt TOS (ignored)");
1703 }
1704 }
1705 return (fdopen(data, lmode));
1706}
1707
1708/* ARGSUSED */
1709void
1710psummary(int signo)
1711{
1712 int save_errno = errno(*__errno());
1713
1714 if (bytes > 0)
1715 ptransfer(1);
1716 errno(*__errno()) = save_errno;
1717}
1718
1719/* ARGSUSED */
1720void
1721psabort(int signo)
1722{
1723
1724 alarmtimer(0);
1725 abrtflag++;
1726}
1727
1728void
1729pswitch(int flag)
1730{
1731 sig_t oldintr;
1732 static struct comvars {
1733 int connect;
1734 char name[HOST_NAME_MAX255+1];
1735 union sockaddr_union mctl;
1736 union sockaddr_union hctl;
1737 FILE *in;
1738 FILE *out;
1739 int tpe;
1740 int curtpe;
1741 int cpnd;
1742 int sunqe;
1743 int runqe;
1744 int mcse;
1745 int ntflg;
1746 char nti[17];
1747 char nto[17];
1748 int mapflg;
1749 char mi[PATH_MAX1024];
1750 char mo[PATH_MAX1024];
1751 } proxstruct, tmpstruct;
1752 struct comvars *ip, *op;
1753
1754 abrtflag = 0;
1755 oldintr = signal(SIGINT2, psabort);
1756 if (flag) {
1757 if (proxy)
1758 return;
1759 ip = &tmpstruct;
1760 op = &proxstruct;
1761 proxy++;
1762 } else {
1763 if (!proxy)
1764 return;
1765 ip = &proxstruct;
1766 op = &tmpstruct;
1767 proxy = 0;
1768 }
1769 ip->connect = connected;
1770 connected = op->connect;
1771 if (hostname) {
1772 (void)strlcpy(ip->name, hostname, sizeof(ip->name));
1773 } else
1774 ip->name[0] = '\0';
1775 hostname = op->name;
1776 ip->hctl = hisctladdr;
1777 hisctladdr = op->hctl;
1778 ip->mctl = myctladdr;
1779 myctladdr = op->mctl;
1780 ip->in = cin;
1781 cin = op->in;
1782 ip->out = cout;
1783 cout = op->out;
1784 ip->tpe = type;
1785 type = op->tpe;
1786 ip->curtpe = curtype;
1787 curtype = op->curtpe;
1788 ip->cpnd = cpend;
1789 cpend = op->cpnd;
1790 ip->sunqe = sunique;
1791 sunique = op->sunqe;
1792 ip->runqe = runique;
1793 runique = op->runqe;
1794 ip->mcse = mcase;
1795 mcase = op->mcse;
1796 ip->ntflg = ntflag;
1797 ntflag = op->ntflg;
1798 (void)strlcpy(ip->nti, ntin, sizeof(ip->nti));
1799 (void)strlcpy(ntin, op->nti, sizeof ntin);
1800 (void)strlcpy(ip->nto, ntout, sizeof(ip->nto));
1801 (void)strlcpy(ntout, op->nto, sizeof ntout);
1802 ip->mapflg = mapflag;
1803 mapflag = op->mapflg;
1804 (void)strlcpy(ip->mi, mapin, sizeof(ip->mi));
1805 (void)strlcpy(mapin, op->mi, sizeof mapin);
1806 (void)strlcpy(ip->mo, mapout, sizeof(ip->mo));
1807 (void)strlcpy(mapout, op->mo, sizeof mapout);
1808 (void)signal(SIGINT2, oldintr);
1809 if (abrtflag) {
1810 abrtflag = 0;
1811 (*oldintr)(SIGINT2);
1812 }
1813}
1814
1815/* ARGSUSED */
1816void
1817abortpt(int signo)
1818{
1819
1820 alarmtimer(0);
1821 putc('\n', ttyout)(!__isthreaded ? __sputc('\n', ttyout) : (putc)('\n', ttyout)
)
;
1822 (void)fflush(ttyout);
1823 ptabflg++;
1824 mflag = 0;
1825 abrtflag = 0;
1826 longjmp(ptabort, 1);
1827}
1828
1829void
1830proxtrans(const char *cmd, const char *local, const char *remote)
1831{
1832 volatile sig_t oldintr;
1833 int prox_type, nfnd;
1834 volatile int secndflag;
1835 char * volatile cmd2;
1836 struct pollfd pfd[1];
1837
1838 oldintr = NULL((void*)0);
1839 secndflag = 0;
1840 if (strcmp(cmd, "RETR"))
1841 cmd2 = "RETR";
1842 else
1843 cmd2 = runique ? "STOU" : "STOR";
1844 if ((prox_type = type) == 0) {
1845 if (unix_server && unix_proxy)
1846 prox_type = TYPE_I3;
1847 else
1848 prox_type = TYPE_A1;
1849 }
1850 if (curtype != prox_type)
1851 changetype(prox_type, 1);
1852 if (command("PASV") != COMPLETE2) {
1853 fputs("proxy server does not support third party transfers.\n",
1854 ttyout);
1855 return;
1856 }
1857 pswitch(0);
1858 if (!connected) {
1859 fputs("No primary connection.\n", ttyout);
1860 pswitch(1);
1861 code = -1;
1862 return;
1863 }
1864 if (curtype != prox_type)
1865 changetype(prox_type, 1);
1866 if (command("PORT %s", pasv) != COMPLETE2) {
1867 pswitch(1);
1868 return;
1869 }
1870 if (setjmp(ptabort))
1871 goto abort;
1872 oldintr = signal(SIGINT2, abortpt);
1873 if (command("%s %s", cmd, remote) != PRELIM1) {
1874 (void)signal(SIGINT2, oldintr);
1875 pswitch(1);
1876 return;
1877 }
1878 sleep(2);
1879 pswitch(1);
1880 secndflag++;
1881 if (command("%s %s", cmd2, local) != PRELIM1)
1882 goto abort;
1883 ptflag++;
1884 (void)getreply(0);
1885 pswitch(0);
1886 (void)getreply(0);
1887 (void)signal(SIGINT2, oldintr);
1888 pswitch(1);
1889 ptflag = 0;
1890 fprintf(ttyout, "local: %s remote: %s\n", local, remote);
1891 return;
1892abort:
1893 (void)signal(SIGINT2, SIG_IGN(void (*)(int))1);
1894 ptflag = 0;
1895 if (strcmp(cmd, "RETR") && !proxy)
1896 pswitch(1);
1897 else if (!strcmp(cmd, "RETR") && proxy)
1898 pswitch(0);
1899 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1900 if (command("%s %s", cmd2, local) != PRELIM1) {
1901 pswitch(0);
1902 if (cpend)
1903 abort_remote(NULL((void*)0));
1904 }
1905 pswitch(1);
1906 if (ptabflg)
1907 code = -1;
1908 (void)signal(SIGINT2, oldintr);
1909 return;
1910 }
1911 if (cpend)
1912 abort_remote(NULL((void*)0));
1913 pswitch(!proxy);
1914 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1915 if (command("%s %s", cmd2, local) != PRELIM1) {
1916 pswitch(0);
1917 if (cpend)
1918 abort_remote(NULL((void*)0));
1919 pswitch(1);
1920 if (ptabflg)
1921 code = -1;
1922 (void)signal(SIGINT2, oldintr);
1923 return;
1924 }
1925 }
1926 if (cpend)
1927 abort_remote(NULL((void*)0));
1928 pswitch(!proxy);
1929 if (cpend) {
1930 pfd[0].fd = fileno(cin)(!__isthreaded ? ((cin)->_file) : (fileno)(cin));
1931 pfd[0].events = POLLIN0x0001;
1932 if ((nfnd = poll(pfd, 1, 10 * 1000)) <= 0) {
1933 if (nfnd == -1)
1934 warn("abort");
1935 if (ptabflg)
1936 code = -1;
1937 lostpeer();
1938 }
1939 (void)getreply(0);
1940 (void)getreply(0);
1941 }
1942 if (proxy)
1943 pswitch(0);
1944 pswitch(1);
1945 if (ptabflg)
1946 code = -1;
1947 (void)signal(SIGINT2, oldintr);
1948}
1949
1950#ifndef SMALL
1951/* ARGSUSED */
1952void
1953reset(int argc, char *argv[])
1954{
1955 struct pollfd pfd[1];
1956 int nfnd = 1;
1957
1958 pfd[0].fd = fileno(cin)(!__isthreaded ? ((cin)->_file) : (fileno)(cin));
1959 pfd[0].events = POLLIN0x0001;
1960 while (nfnd > 0) {
1961 if ((nfnd = poll(pfd, 1, 0)) == -1) {
1962 warn("reset");
1963 code = -1;
1964 lostpeer();
1965 } else if (nfnd) {
1966 (void)getreply(0);
1967 }
1968 }
1969}
1970#endif
1971
1972char *
1973gunique(const char *local)
1974{
1975 static char new[PATH_MAX1024];
1976 char *cp = strrchr(local, '/');
1977 int d, count=0;
1978 char ext = '1';
1979
1980 if (cp)
1981 *cp = '\0';
1982 d = access(cp == local ? "/" : cp ? local : ".", W_OK0x02);
1983 if (cp)
1984 *cp = '/';
1985 if (d == -1) {
1986 warn("local: %s", local);
1987 return ((char *) 0);
1988 }
1989 (void)strlcpy(new, local, sizeof new);
1990 cp = new + strlen(new);
1991 *cp++ = '.';
1992 while (!d) {
1993 if (++count == 100) {
1994 fputs("runique: can't find unique file name.\n", ttyout);
1995 return ((char *) 0);
1996 }
1997 *cp++ = ext;
1998 *cp = '\0';
1999 if (ext == '9')
2000 ext = '0';
2001 else
2002 ext++;
2003 if ((d = access(new, F_OK0)) == -1)
2004 break;
2005 if (ext != '0')
2006 cp--;
2007 else if (*(cp - 2) == '.')
2008 *(cp - 1) = '1';
2009 else {
2010 *(cp - 2) = *(cp - 2) + 1;
2011 cp--;
2012 }
2013 }
2014 return (new);
2015}
2016
2017jmp_buf forceabort;
2018
2019/* ARGSUSED */
2020static void
2021abortforce(int signo)
2022{
2023 int save_errno = errno(*__errno());
2024
2025#define MSG "Forced abort. The connection will be closed.\n"
2026 (void) write(fileno(ttyout)(!__isthreaded ? ((ttyout)->_file) : (fileno)(ttyout)), MSG, strlen(MSG));
2027#undef MSG
2028
2029 errno(*__errno()) = save_errno;
2030 longjmp(forceabort, 1);
2031}
2032
2033void
2034abort_remote(FILE *din)
2035{
2036 char buf[BUFSIZ1024];
2037 nfds_t nfds;
2038 int nfnd;
2039 struct pollfd pfd[2];
2040 sig_t oldintr;
2041
2042 if (cout == NULL((void*)0) || setjmp(forceabort)) {
2043 if (cout)
2044 fclose(cout);
2045 warnx("Lost control connection for abort.");
2046 if (ptabflg)
2047 code = -1;
2048 lostpeer();
2049 return;
2050 }
2051
2052 oldintr = signal(SIGINT2, abortforce);
2053
2054 /*
2055 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
2056 * after urgent byte rather than before as is protocol now
2057 */
2058 snprintf(buf, sizeof buf, "%c%c%c", IAC255, IP244, IAC255);
2059 if (send(fileno(cout)(!__isthreaded ? ((cout)->_file) : (fileno)(cout)), buf, 3, MSG_OOB0x1) != 3)
2060 warn("abort");
2061 fprintf(cout, "%cABOR\r\n", DM242);
2062 (void)fflush(cout);
2063 pfd[0].fd = fileno(cin)(!__isthreaded ? ((cin)->_file) : (fileno)(cin));
2064 pfd[0].events = POLLIN0x0001;
2065 nfds = 1;
2066 if (din) {
2067 pfd[1].fd = fileno(din)(!__isthreaded ? ((din)->_file) : (fileno)(din));
2068 pfd[1].events = POLLIN0x0001;
2069 nfds++;
2070 }
2071 if ((nfnd = poll(pfd, nfds, 10 * 1000)) <= 0) {
2072 if (nfnd == -1)
2073 warn("abort");
2074 if (ptabflg)
2075 code = -1;
2076 lostpeer();
2077 }
2078 if (din && (pfd[1].revents & POLLIN0x0001)) {
2079 while (read(fileno(din)(!__isthreaded ? ((din)->_file) : (fileno)(din)), buf, BUFSIZ1024) > 0)
2080 /* LOOP */;
2081 }
2082 if (getreply(0) == ERROR5 && code == 552) {
2083 /* 552 needed for nic style abort */
2084 (void)getreply(0);
2085 }
2086 (void)getreply(0);
2087 (void)signal(SIGINT2, oldintr);
2088}