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