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