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