Bug Summary

File:src/usr.bin/ftp/ftp.c
Warning:line 1438, column 6
Value stored to 'error' is never read

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)) {
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;
Value stored to 'error' is never read
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}