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