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