1 /* $NetBSD: ftp.c,v 1.114 2001/02/19 18:15:29 lukem Exp $ */ 2 3 /*- 4 * Copyright (c) 1996-2000 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.114 2001/02/19 18:15:29 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 = AF_UNSPEC; 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 = fseek(fin, (long) 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 long i, n; 1171 1172 if (fseek(fout, 0L, SEEK_SET) < 0) 1173 goto done; 1174 n = (long)restart_point; 1175 for (i = 0; i++ < n;) { 1176 if ((ch = getc(fout)) == EOF) 1177 goto done; 1178 if (ch == '\n') 1179 i++; 1180 } 1181 if (fseek(fout, 0L, SEEK_CUR) < 0) { 1182 done: 1183 warn("local: %s", local); 1184 goto cleanuprecv; 1185 } 1186 } 1187 while ((c = getc(din)) != EOF) { 1188 if (c == '\n') 1189 bare_lfs++; 1190 while (c == '\r') { 1191 while (hash && (!progress || filesize < 0) && 1192 (bytes >= hashbytes)) { 1193 (void)putc('#', ttyout); 1194 (void)fflush(ttyout); 1195 hashbytes += mark; 1196 } 1197 bytes++; 1198 if ((c = getc(din)) != '\n' || tcrflag) { 1199 if (ferror(fout)) 1200 goto break2; 1201 (void)putc('\r', fout); 1202 if (c == '\0') { 1203 bytes++; 1204 goto contin2; 1205 } 1206 if (c == EOF) 1207 goto contin2; 1208 } 1209 } 1210 (void)putc(c, fout); 1211 bytes++; 1212 contin2: ; 1213 } 1214 break2: 1215 if (hash && (!progress || filesize < 0)) { 1216 if (bytes < hashbytes) 1217 (void)putc('#', ttyout); 1218 (void)putc('\n', ttyout); 1219 } 1220 if (ferror(din)) { 1221 if (errno != EPIPE) 1222 warn("netin"); 1223 bytes = -1; 1224 } 1225 if (ferror(fout)) 1226 warn("local: %s", local); 1227 break; 1228 } 1229 1230 progressmeter(1); 1231 if (closefunc != NULL) { 1232 (*closefunc)(fout); 1233 fout = NULL; 1234 } 1235 (void)fclose(din); 1236 din = NULL; 1237 (void)getreply(0); 1238 if (bare_lfs) { 1239 fprintf(ttyout, 1240 "WARNING! %d bare linefeeds received in ASCII mode.\n", 1241 bare_lfs); 1242 fputs("File may not have transferred correctly.\n", ttyout); 1243 } 1244 if (bytes >= 0 && is_retr) { 1245 if (bytes > 0) 1246 ptransfer(0); 1247 if (preserve && (closefunc == fclose)) { 1248 mtime = remotemodtime(remote, 0); 1249 if (mtime != -1) { 1250 (void)gettimeofday(&tval[0], NULL); 1251 tval[1].tv_sec = mtime; 1252 tval[1].tv_usec = 0; 1253 if (utimes(local, tval) == -1) { 1254 fprintf(ttyout, 1255 "Can't change modification time on %s to %s", 1256 local, asctime(localtime(&mtime))); 1257 } 1258 } 1259 } 1260 } 1261 goto cleanuprecv; 1262 1263 abort: 1264 /* 1265 * abort using RFC 959 recommended IP,SYNC sequence 1266 */ 1267 if (! sigsetjmp(xferabort, 1)) { 1268 /* this is the first call */ 1269 (void)xsignal(SIGINT, abort_squared); 1270 if (!cpend) { 1271 code = -1; 1272 goto cleanuprecv; 1273 } 1274 abort_remote(din); 1275 } 1276 code = -1; 1277 if (bytes > 0) 1278 ptransfer(0); 1279 1280 cleanuprecv: 1281 if (oldintr) 1282 (void)xsignal(SIGINT, oldintr); 1283 if (oldintp) 1284 (void)xsignal(SIGPIPE, oldintp); 1285 if (data >= 0) { 1286 (void)close(data); 1287 data = -1; 1288 } 1289 if (closefunc != NULL && fout != NULL) 1290 (*closefunc)(fout); 1291 if (din) 1292 (void)fclose(din); 1293 progress = oprogress; 1294 preserve = opreserve; 1295 bytes = 0; 1296 } 1297 1298 /* 1299 * Need to start a listen on the data channel before we send the command, 1300 * otherwise the server's connect may fail. 1301 */ 1302 int 1303 initconn(void) 1304 { 1305 char *p, *a; 1306 int result, len, tmpno = 0; 1307 int on = 1; 1308 int error; 1309 u_int addr[16], port[2]; 1310 u_int af, hal, pal; 1311 char *pasvcmd = NULL; 1312 1313 #ifdef INET6 1314 if (myctladdr.su_family == AF_INET6 && debug && 1315 (IN6_IS_ADDR_LINKLOCAL(&myctladdr.si_su.su_sin6.sin6_addr) || 1316 IN6_IS_ADDR_SITELOCAL(&myctladdr.si_su.su_sin6.sin6_addr))) { 1317 warnx("use of scoped address can be troublesome"); 1318 } 1319 #endif 1320 reinit: 1321 if (passivemode) { 1322 data_addr = myctladdr; 1323 data = socket(data_addr.su_family, SOCK_STREAM, 0); 1324 if (data < 0) { 1325 warn("socket"); 1326 return (1); 1327 } 1328 if ((options & SO_DEBUG) && 1329 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, 1330 sizeof(on)) < 0) 1331 warn("setsockopt (ignored)"); 1332 result = COMPLETE + 1; 1333 switch (data_addr.su_family) { 1334 case AF_INET: 1335 if (epsv4 && !epsv4bad) { 1336 pasvcmd = "EPSV"; 1337 result = command("EPSV"); 1338 if (!connected) 1339 return (1); 1340 /* 1341 * this code is to be friendly with broken 1342 * BSDI ftpd 1343 */ 1344 if (code / 10 == 22 && code != 229) { 1345 fputs( 1346 "wrong server: return code must be 229\n", 1347 ttyout); 1348 result = COMPLETE + 1; 1349 } 1350 if (result != COMPLETE) { 1351 epsv4bad = 1; 1352 if (debug) 1353 fputs( 1354 "disabling epsv4 for this connection\n", 1355 ttyout); 1356 } 1357 } 1358 if (result != COMPLETE) { 1359 pasvcmd = "PASV"; 1360 result = command("PASV"); 1361 if (!connected) 1362 return (1); 1363 } 1364 break; 1365 #ifdef INET6 1366 case AF_INET6: 1367 pasvcmd = "EPSV"; 1368 result = command("EPSV"); 1369 if (!connected) 1370 return (1); 1371 /* this code is to be friendly with broken BSDI ftpd */ 1372 if (code / 10 == 22 && code != 229) { 1373 fputs( 1374 "wrong server: return code must be 229\n", 1375 ttyout); 1376 result = COMPLETE + 1; 1377 } 1378 if (result != COMPLETE) { 1379 pasvcmd = "LPSV"; 1380 result = command("LPSV"); 1381 } 1382 if (!connected) 1383 return (1); 1384 break; 1385 #endif 1386 default: 1387 result = COMPLETE + 1; 1388 break; 1389 } 1390 if (result != COMPLETE) { 1391 if (activefallback) { 1392 (void)close(data); 1393 data = -1; 1394 passivemode = 0; 1395 #if 0 1396 activefallback = 0; 1397 #endif 1398 goto reinit; 1399 } 1400 fputs("Passive mode refused.\n", ttyout); 1401 goto bad; 1402 } 1403 1404 #define pack2(var, off) \ 1405 (((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0)) 1406 #define pack4(var, off) \ 1407 (((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \ 1408 ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0)) 1409 #define UC(b) (((int)b)&0xff) 1410 1411 /* 1412 * What we've got at this point is a string of comma separated 1413 * one-byte unsigned integer values, separated by commas. 1414 */ 1415 if (strcmp(pasvcmd, "PASV") == 0) { 1416 if (data_addr.su_family != AF_INET) { 1417 fputs( 1418 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); 1419 error = 1; 1420 goto bad; 1421 } 1422 if (code / 10 == 22 && code != 227) { 1423 fputs("wrong server: return code must be 227\n", 1424 ttyout); 1425 error = 1; 1426 goto bad; 1427 } 1428 error = sscanf(pasv, "%u,%u,%u,%u,%u,%u", 1429 &addr[0], &addr[1], &addr[2], &addr[3], 1430 &port[0], &port[1]); 1431 if (error != 6) { 1432 fputs( 1433 "Passive mode address scan failure. Shouldn't happen!\n", ttyout); 1434 error = 1; 1435 goto bad; 1436 } 1437 error = 0; 1438 memset(&data_addr, 0, sizeof(data_addr)); 1439 data_addr.su_family = AF_INET; 1440 data_addr.su_len = sizeof(struct sockaddr_in); 1441 data_addr.si_su.su_sin.sin_addr.s_addr = 1442 htonl(pack4(addr, 0)); 1443 data_addr.su_port = htons(pack2(port, 0)); 1444 } else if (strcmp(pasvcmd, "LPSV") == 0) { 1445 if (code / 10 == 22 && code != 228) { 1446 fputs("wrong server: return code must be 228\n", 1447 ttyout); 1448 error = 1; 1449 goto bad; 1450 } 1451 switch (data_addr.su_family) { 1452 case AF_INET: 1453 error = sscanf(pasv, 1454 "%u,%u,%u,%u,%u,%u,%u,%u,%u", 1455 &af, &hal, 1456 &addr[0], &addr[1], &addr[2], &addr[3], 1457 &pal, &port[0], &port[1]); 1458 if (error != 9) { 1459 fputs( 1460 "Passive mode address scan failure. Shouldn't happen!\n", ttyout); 1461 error = 1; 1462 goto bad; 1463 } 1464 if (af != 4 || hal != 4 || pal != 2) { 1465 fputs( 1466 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); 1467 error = 1; 1468 goto bad; 1469 } 1470 1471 error = 0; 1472 memset(&data_addr, 0, sizeof(data_addr)); 1473 data_addr.su_family = AF_INET; 1474 data_addr.su_len = sizeof(struct sockaddr_in); 1475 data_addr.si_su.su_sin.sin_addr.s_addr = 1476 htonl(pack4(addr, 0)); 1477 data_addr.su_port = htons(pack2(port, 0)); 1478 break; 1479 #ifdef INET6 1480 case AF_INET6: 1481 error = sscanf(pasv, 1482 "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", 1483 &af, &hal, 1484 &addr[0], &addr[1], &addr[2], &addr[3], 1485 &addr[4], &addr[5], &addr[6], &addr[7], 1486 &addr[8], &addr[9], &addr[10], 1487 &addr[11], &addr[12], &addr[13], 1488 &addr[14], &addr[15], 1489 &pal, &port[0], &port[1]); 1490 if (error != 21) { 1491 fputs( 1492 "Passive mode address scan failure. Shouldn't happen!\n", ttyout); 1493 error = 1; 1494 goto bad; 1495 } 1496 if (af != 6 || hal != 16 || pal != 2) { 1497 fputs( 1498 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); 1499 error = 1; 1500 goto bad; 1501 } 1502 1503 error = 0; 1504 memset(&data_addr, 0, sizeof(data_addr)); 1505 data_addr.su_family = AF_INET6; 1506 data_addr.su_len = sizeof(struct sockaddr_in6); 1507 { 1508 int i; 1509 for (i = 0; i < sizeof(struct in6_addr); i++) { 1510 data_addr.si_su.su_sin6.sin6_addr.s6_addr[i] = 1511 UC(addr[i]); 1512 } 1513 } 1514 data_addr.su_port = htons(pack2(port, 0)); 1515 break; 1516 #endif 1517 default: 1518 error = 1; 1519 } 1520 } else if (strcmp(pasvcmd, "EPSV") == 0) { 1521 char delim[4]; 1522 1523 port[0] = 0; 1524 if (code / 10 == 22 && code != 229) { 1525 fputs("wrong server: return code must be 229\n", 1526 ttyout); 1527 error = 1; 1528 goto bad; 1529 } 1530 if (sscanf(pasv, "%c%c%c%d%c", &delim[0], 1531 &delim[1], &delim[2], &port[1], 1532 &delim[3]) != 5) { 1533 fputs("parse error!\n", ttyout); 1534 error = 1; 1535 goto bad; 1536 } 1537 if (delim[0] != delim[1] || delim[0] != delim[2] 1538 || delim[0] != delim[3]) { 1539 fputs("parse error!\n", ttyout); 1540 error = 1; 1541 goto bad; 1542 } 1543 data_addr = hisctladdr; 1544 data_addr.su_port = htons(port[1]); 1545 } else 1546 goto bad; 1547 1548 while (xconnect(data, (struct sockaddr *)&data_addr.si_su, 1549 data_addr.su_len) < 0) { 1550 if (errno == EINTR) 1551 continue; 1552 if (activefallback) { 1553 (void)close(data); 1554 data = -1; 1555 passivemode = 0; 1556 #if 0 1557 activefallback = 0; 1558 #endif 1559 goto reinit; 1560 } 1561 warn("connect"); 1562 goto bad; 1563 } 1564 #ifdef IPTOS_THROUGHPUT 1565 if (data_addr.su_family == AF_INET) { 1566 on = IPTOS_THROUGHPUT; 1567 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, 1568 sizeof(int)) < 0) 1569 warn("setsockopt TOS (ignored)"); 1570 } 1571 #endif 1572 return (0); 1573 } 1574 1575 noport: 1576 data_addr = myctladdr; 1577 if (sendport) 1578 data_addr.su_port = 0; /* let system pick one */ 1579 if (data != -1) 1580 (void)close(data); 1581 data = socket(data_addr.su_family, SOCK_STREAM, 0); 1582 if (data < 0) { 1583 warn("socket"); 1584 if (tmpno) 1585 sendport = 1; 1586 return (1); 1587 } 1588 if (!sendport) 1589 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, 1590 sizeof(on)) < 0) { 1591 warn("setsockopt (reuse address)"); 1592 goto bad; 1593 } 1594 if (bind(data, (struct sockaddr *)&data_addr.si_su, 1595 data_addr.su_len) < 0) { 1596 warn("bind"); 1597 goto bad; 1598 } 1599 if (options & SO_DEBUG && 1600 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, 1601 sizeof(on)) < 0) 1602 warn("setsockopt (ignored)"); 1603 len = sizeof(data_addr.si_su); 1604 memset((char *)&data_addr, 0, sizeof (data_addr)); 1605 if (getsockname(data, (struct sockaddr *)&data_addr.si_su, &len) < 0) { 1606 warn("getsockname"); 1607 goto bad; 1608 } 1609 data_addr.su_len = len; 1610 if (xlisten(data, 1) < 0) 1611 warn("listen"); 1612 1613 if (sendport) { 1614 char hname[NI_MAXHOST], sname[NI_MAXSERV]; 1615 int af; 1616 struct sockinet tmp; 1617 1618 switch (data_addr.su_family) { 1619 case AF_INET: 1620 if (!epsv4 || epsv4bad) { 1621 result = COMPLETE + 1; 1622 break; 1623 } 1624 /* FALLTHROUGH */ 1625 #ifdef INET6 1626 case AF_INET6: 1627 #endif 1628 af = (data_addr.su_family == AF_INET) ? 1 : 2; 1629 tmp = data_addr; 1630 #ifdef INET6 1631 if (tmp.su_family == AF_INET6) 1632 tmp.si_su.su_sin6.sin6_scope_id = 0; 1633 #endif 1634 if (getnameinfo((struct sockaddr *)&tmp.si_su, 1635 tmp.su_len, hname, sizeof(hname), sname, 1636 sizeof(sname), NI_NUMERICHOST | NI_NUMERICSERV)) { 1637 result = ERROR; 1638 } else { 1639 result = command("EPRT |%d|%s|%s|", af, hname, 1640 sname); 1641 if (!connected) 1642 return (1); 1643 if (result != COMPLETE) { 1644 epsv4bad = 1; 1645 if (debug) 1646 fputs( 1647 "disabling epsv4 for this connection\n", 1648 ttyout); 1649 } 1650 } 1651 break; 1652 default: 1653 result = COMPLETE + 1; 1654 break; 1655 } 1656 if (result == COMPLETE) 1657 goto skip_port; 1658 1659 switch (data_addr.su_family) { 1660 case AF_INET: 1661 a = (char *)&data_addr.si_su.su_sin.sin_addr; 1662 p = (char *)&data_addr.su_port; 1663 result = command("PORT %d,%d,%d,%d,%d,%d", 1664 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 1665 UC(p[0]), UC(p[1])); 1666 break; 1667 #ifdef INET6 1668 case AF_INET6: 1669 a = (char *)&data_addr.si_su.su_sin6.sin6_addr; 1670 p = (char *)&data_addr.su_port; 1671 result = command( 1672 "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", 1673 6, 16, 1674 UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]), 1675 UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]), 1676 UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]), 1677 UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]), 1678 2, UC(p[0]), UC(p[1])); 1679 break; 1680 #endif 1681 default: 1682 result = COMPLETE + 1; /* xxx */ 1683 } 1684 if (!connected) 1685 return (1); 1686 skip_port: 1687 1688 if (result == ERROR && sendport == -1) { 1689 sendport = 0; 1690 tmpno = 1; 1691 goto noport; 1692 } 1693 return (result != COMPLETE); 1694 } 1695 if (tmpno) 1696 sendport = 1; 1697 #ifdef IPTOS_THROUGHPUT 1698 if (data_addr.su_family == AF_INET) { 1699 on = IPTOS_THROUGHPUT; 1700 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, 1701 sizeof(int)) < 0) 1702 warn("setsockopt TOS (ignored)"); 1703 } 1704 #endif 1705 return (0); 1706 bad: 1707 (void)close(data), data = -1; 1708 if (tmpno) 1709 sendport = 1; 1710 return (1); 1711 } 1712 1713 FILE * 1714 dataconn(const char *lmode) 1715 { 1716 struct sockinet from; 1717 int s, fromlen = myctladdr.su_len; 1718 1719 if (passivemode) 1720 return (fdopen(data, lmode)); 1721 1722 s = accept(data, (struct sockaddr *) &from.si_su, &fromlen); 1723 if (s < 0) { 1724 warn("accept"); 1725 (void)close(data), data = -1; 1726 return (NULL); 1727 } 1728 (void)close(data); 1729 data = s; 1730 #ifdef IPTOS_THROUGHPUT 1731 if (from.su_family == AF_INET) { 1732 int tos = IPTOS_THROUGHPUT; 1733 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 1734 sizeof(int)) < 0) { 1735 warn("setsockopt TOS (ignored)"); 1736 } 1737 } 1738 #endif 1739 return (fdopen(data, lmode)); 1740 } 1741 1742 void 1743 psabort(int notused) 1744 { 1745 int oerrno = errno; 1746 1747 alarmtimer(0); 1748 abrtflag++; 1749 errno = oerrno; 1750 } 1751 1752 void 1753 pswitch(int flag) 1754 { 1755 sigfunc oldintr; 1756 static struct comvars { 1757 int connect; 1758 char name[MAXHOSTNAMELEN]; 1759 struct sockinet mctl; 1760 struct sockinet hctl; 1761 FILE *in; 1762 FILE *out; 1763 int tpe; 1764 int curtpe; 1765 int cpnd; 1766 int sunqe; 1767 int runqe; 1768 int mcse; 1769 int ntflg; 1770 char nti[17]; 1771 char nto[17]; 1772 int mapflg; 1773 char mi[MAXPATHLEN]; 1774 char mo[MAXPATHLEN]; 1775 } proxstruct, tmpstruct; 1776 struct comvars *ip, *op; 1777 1778 abrtflag = 0; 1779 oldintr = xsignal(SIGINT, psabort); 1780 if (flag) { 1781 if (proxy) 1782 return; 1783 ip = &tmpstruct; 1784 op = &proxstruct; 1785 proxy++; 1786 } else { 1787 if (!proxy) 1788 return; 1789 ip = &proxstruct; 1790 op = &tmpstruct; 1791 proxy = 0; 1792 } 1793 ip->connect = connected; 1794 connected = op->connect; 1795 if (hostname) 1796 (void)strlcpy(ip->name, hostname, sizeof(ip->name)); 1797 else 1798 ip->name[0] = '\0'; 1799 hostname = op->name; 1800 ip->hctl = hisctladdr; 1801 hisctladdr = op->hctl; 1802 ip->mctl = myctladdr; 1803 myctladdr = op->mctl; 1804 ip->in = cin; 1805 cin = op->in; 1806 ip->out = cout; 1807 cout = op->out; 1808 ip->tpe = type; 1809 type = op->tpe; 1810 ip->curtpe = curtype; 1811 curtype = op->curtpe; 1812 ip->cpnd = cpend; 1813 cpend = op->cpnd; 1814 ip->sunqe = sunique; 1815 sunique = op->sunqe; 1816 ip->runqe = runique; 1817 runique = op->runqe; 1818 ip->mcse = mcase; 1819 mcase = op->mcse; 1820 ip->ntflg = ntflag; 1821 ntflag = op->ntflg; 1822 (void)strlcpy(ip->nti, ntin, sizeof(ip->nti)); 1823 (void)strlcpy(ntin, op->nti, sizeof(ntin)); 1824 (void)strlcpy(ip->nto, ntout, sizeof(ip->nto)); 1825 (void)strlcpy(ntout, op->nto, sizeof(ntout)); 1826 ip->mapflg = mapflag; 1827 mapflag = op->mapflg; 1828 (void)strlcpy(ip->mi, mapin, sizeof(ip->mi)); 1829 (void)strlcpy(mapin, op->mi, sizeof(mapin)); 1830 (void)strlcpy(ip->mo, mapout, sizeof(ip->mo)); 1831 (void)strlcpy(mapout, op->mo, sizeof(mapout)); 1832 (void)xsignal(SIGINT, oldintr); 1833 if (abrtflag) { 1834 abrtflag = 0; 1835 (*oldintr)(SIGINT); 1836 } 1837 } 1838 1839 void 1840 abortpt(int notused) 1841 { 1842 1843 alarmtimer(0); 1844 if (fromatty) 1845 write(fileno(ttyout), "\n", 1); 1846 ptabflg++; 1847 mflag = 0; 1848 abrtflag = 0; 1849 siglongjmp(ptabort, 1); 1850 } 1851 1852 void 1853 proxtrans(const char *cmd, const char *local, const char *remote) 1854 { 1855 sigfunc oldintr; 1856 int prox_type, nfnd; 1857 volatile int secndflag; 1858 char *cmd2; 1859 1860 #ifdef __GNUC__ /* to shut up gcc warnings */ 1861 (void)&oldintr; 1862 (void)&cmd2; 1863 #endif 1864 1865 oldintr = NULL; 1866 secndflag = 0; 1867 if (strcmp(cmd, "RETR")) 1868 cmd2 = "RETR"; 1869 else 1870 cmd2 = runique ? "STOU" : "STOR"; 1871 if ((prox_type = type) == 0) { 1872 if (unix_server && unix_proxy) 1873 prox_type = TYPE_I; 1874 else 1875 prox_type = TYPE_A; 1876 } 1877 if (curtype != prox_type) 1878 changetype(prox_type, 1); 1879 if (command("PASV") != COMPLETE) { 1880 fputs("proxy server does not support third party transfers.\n", 1881 ttyout); 1882 return; 1883 } 1884 pswitch(0); 1885 if (!connected) { 1886 fputs("No primary connection.\n", ttyout); 1887 pswitch(1); 1888 code = -1; 1889 return; 1890 } 1891 if (curtype != prox_type) 1892 changetype(prox_type, 1); 1893 if (command("PORT %s", pasv) != COMPLETE) { 1894 pswitch(1); 1895 return; 1896 } 1897 if (sigsetjmp(ptabort, 1)) 1898 goto abort; 1899 oldintr = xsignal(SIGINT, abortpt); 1900 if ((restart_point && 1901 (command("REST " LLF, (LLT) restart_point) != CONTINUE)) 1902 || (command("%s %s", cmd, remote) != PRELIM)) { 1903 (void)xsignal(SIGINT, oldintr); 1904 pswitch(1); 1905 return; 1906 } 1907 sleep(2); 1908 pswitch(1); 1909 secndflag++; 1910 if ((restart_point && 1911 (command("REST " LLF, (LLT) restart_point) != CONTINUE)) 1912 || (command("%s %s", cmd2, local) != PRELIM)) 1913 goto abort; 1914 ptflag++; 1915 (void)getreply(0); 1916 pswitch(0); 1917 (void)getreply(0); 1918 (void)xsignal(SIGINT, oldintr); 1919 pswitch(1); 1920 ptflag = 0; 1921 fprintf(ttyout, "local: %s remote: %s\n", local, remote); 1922 return; 1923 abort: 1924 if (sigsetjmp(xferabort, 1)) { 1925 (void)xsignal(SIGINT, oldintr); 1926 return; 1927 } 1928 (void)xsignal(SIGINT, abort_squared); 1929 ptflag = 0; 1930 if (strcmp(cmd, "RETR") && !proxy) 1931 pswitch(1); 1932 else if (!strcmp(cmd, "RETR") && proxy) 1933 pswitch(0); 1934 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1935 if (command("%s %s", cmd2, local) != PRELIM) { 1936 pswitch(0); 1937 if (cpend) 1938 abort_remote(NULL); 1939 } 1940 pswitch(1); 1941 if (ptabflg) 1942 code = -1; 1943 (void)xsignal(SIGINT, oldintr); 1944 return; 1945 } 1946 if (cpend) 1947 abort_remote(NULL); 1948 pswitch(!proxy); 1949 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1950 if (command("%s %s", cmd2, local) != PRELIM) { 1951 pswitch(0); 1952 if (cpend) 1953 abort_remote(NULL); 1954 pswitch(1); 1955 if (ptabflg) 1956 code = -1; 1957 (void)xsignal(SIGINT, oldintr); 1958 return; 1959 } 1960 } 1961 if (cpend) 1962 abort_remote(NULL); 1963 pswitch(!proxy); 1964 if (cpend) { 1965 if ((nfnd = empty(cin, NULL, 10)) <= 0) { 1966 if (nfnd < 0) 1967 warn("abort"); 1968 if (ptabflg) 1969 code = -1; 1970 lostpeer(0); 1971 } 1972 (void)getreply(0); 1973 (void)getreply(0); 1974 } 1975 if (proxy) 1976 pswitch(0); 1977 pswitch(1); 1978 if (ptabflg) 1979 code = -1; 1980 (void)xsignal(SIGINT, oldintr); 1981 } 1982 1983 void 1984 reset(int argc, char *argv[]) 1985 { 1986 int nfnd = 1; 1987 1988 if (argc == 0 && argv != NULL) { 1989 fprintf(ttyout, "usage: %s\n", argv[0]); 1990 code = -1; 1991 return; 1992 } 1993 while (nfnd > 0) { 1994 if ((nfnd = empty(cin, NULL, 0)) < 0) { 1995 warn("reset"); 1996 code = -1; 1997 lostpeer(0); 1998 } else if (nfnd) 1999 (void)getreply(0); 2000 } 2001 } 2002 2003 char * 2004 gunique(const char *local) 2005 { 2006 static char new[MAXPATHLEN]; 2007 char *cp = strrchr(local, '/'); 2008 int d, count=0, len; 2009 char ext = '1'; 2010 2011 if (cp) 2012 *cp = '\0'; 2013 d = access(cp == local ? "/" : cp ? local : ".", W_OK); 2014 if (cp) 2015 *cp = '/'; 2016 if (d < 0) { 2017 warn("local: %s", local); 2018 return (NULL); 2019 } 2020 len = strlcpy(new, local, sizeof(new)); 2021 cp = &new[len]; 2022 *cp++ = '.'; 2023 while (!d) { 2024 if (++count == 100) { 2025 fputs("runique: can't find unique file name.\n", 2026 ttyout); 2027 return (NULL); 2028 } 2029 *cp++ = ext; 2030 *cp = '\0'; 2031 if (ext == '9') 2032 ext = '0'; 2033 else 2034 ext++; 2035 if ((d = access(new, F_OK)) < 0) 2036 break; 2037 if (ext != '0') 2038 cp--; 2039 else if (*(cp - 2) == '.') 2040 *(cp - 1) = '1'; 2041 else { 2042 *(cp - 2) = *(cp - 2) + 1; 2043 cp--; 2044 } 2045 } 2046 return (new); 2047 } 2048 2049 /* 2050 * abort_squared -- 2051 * aborts abort_remote(). lostpeer() is called because if the user is 2052 * too impatient to wait or there's another problem then ftp really 2053 * needs to get back to a known state. 2054 */ 2055 void 2056 abort_squared(int dummy) 2057 { 2058 char msgbuf[100]; 2059 int len; 2060 2061 alarmtimer(0); 2062 len = strlcpy(msgbuf, "\nremote abort aborted; closing connection.\n", 2063 sizeof(msgbuf)); 2064 write(fileno(ttyout), msgbuf, len); 2065 lostpeer(0); 2066 siglongjmp(xferabort, 1); 2067 } 2068 2069 void 2070 abort_remote(FILE *din) 2071 { 2072 char buf[BUFSIZ]; 2073 int nfnd; 2074 2075 if (cout == NULL) { 2076 warnx("Lost control connection for abort."); 2077 if (ptabflg) 2078 code = -1; 2079 lostpeer(0); 2080 return; 2081 } 2082 /* 2083 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 2084 * after urgent byte rather than before as is protocol now 2085 */ 2086 buf[0] = IAC; 2087 buf[1] = IP; 2088 buf[2] = IAC; 2089 if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 2090 warn("abort"); 2091 fprintf(cout, "%cABOR\r\n", DM); 2092 (void)fflush(cout); 2093 if ((nfnd = empty(cin, din, 10)) <= 0) { 2094 if (nfnd < 0) 2095 warn("abort"); 2096 if (ptabflg) 2097 code = -1; 2098 lostpeer(0); 2099 } 2100 if (din && (nfnd & 2)) { 2101 while (read(fileno(din), buf, BUFSIZ) > 0) 2102 continue; 2103 } 2104 if (getreply(0) == ERROR && code == 552) { 2105 /* 552 needed for nic style abort */ 2106 (void)getreply(0); 2107 } 2108 (void)getreply(0); 2109 } 2110 2111 void 2112 ai_unmapped(struct addrinfo *ai) 2113 { 2114 #ifdef INET6 2115 struct sockaddr_in6 *sin6; 2116 struct sockaddr_in sin; 2117 int len; 2118 2119 if (ai->ai_family != AF_INET6) 2120 return; 2121 if (ai->ai_addrlen != sizeof(struct sockaddr_in6) || 2122 sizeof(sin) > ai->ai_addrlen) 2123 return; 2124 sin6 = (struct sockaddr_in6 *)ai->ai_addr; 2125 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 2126 return; 2127 2128 memset(&sin, 0, sizeof(sin)); 2129 sin.sin_family = AF_INET; 2130 len = sizeof(struct sockaddr_in); 2131 memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12], 2132 sizeof(sin.sin_addr)); 2133 sin.sin_port = sin6->sin6_port; 2134 2135 ai->ai_family = AF_INET; 2136 #if HAVE_SOCKADDR_SA_LEN 2137 sin.sin_len = len; 2138 #endif 2139 memcpy(ai->ai_addr, &sin, len); 2140 ai->ai_addrlen = len; 2141 #endif 2142 } 2143