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