Bug Summary

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