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