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