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