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