Deleted Added
full compact
ftp.c (84203) ftp.c (85093)
1/*-
2 * Copyright (c) 1998 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 13 unchanged lines hidden (view full) ---

22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1998 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 13 unchanged lines hidden (view full) ---

22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/lib/libfetch/ftp.c 84203 2001-09-30 21:36:09Z dillon $");
30__FBSDID("$FreeBSD: head/lib/libfetch/ftp.c 85093 2001-10-18 08:29:26Z des $");
31
32/*
33 * Portions of this code were taken from or based on ftpio.c:
34 *
35 * ----------------------------------------------------------------------------
36 * "THE BEER-WARE LICENSE" (Revision 42):
37 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
38 * can do whatever you want with this stuff. If we meet some day, and you think

--- 223 unchanged lines hidden (view full) ---

262 us->size = us->size * 10 + *ln - '0';
263 if (*ln && !isspace(*ln)) {
264 _ftp_seterr(FTP_PROTOCOL_ERROR);
265 us->size = -1;
266 return -1;
267 }
268 if (us->size == 0)
269 us->size = -1;
31
32/*
33 * Portions of this code were taken from or based on ftpio.c:
34 *
35 * ----------------------------------------------------------------------------
36 * "THE BEER-WARE LICENSE" (Revision 42):
37 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
38 * can do whatever you want with this stuff. If we meet some day, and you think

--- 223 unchanged lines hidden (view full) ---

262 us->size = us->size * 10 + *ln - '0';
263 if (*ln && !isspace(*ln)) {
264 _ftp_seterr(FTP_PROTOCOL_ERROR);
265 us->size = -1;
266 return -1;
267 }
268 if (us->size == 0)
269 us->size = -1;
270 DEBUG(fprintf(stderr, "size: [\033[1m%lld\033[m]\n", us->size));
270 DEBUG(fprintf(stderr, "size: [\033[1m%lld\033[m]\n", (long long)us->size));
271
272 if ((e = _ftp_cmd(cd, "MDTM %s", s)) != FTP_FILE_STATUS) {
273 _ftp_seterr(e);
274 return -1;
275 }
276 for (ln = last_reply + 4; *ln && isspace(*ln); ln++)
277 /* nothing */ ;
278 switch (strspn(ln, "0123456789")) {

--- 101 unchanged lines hidden (view full) ---

380 if (w >= 0)
381 return w;
382 if (errno != EINTR)
383 io->err = errno;
384 return -1;
385}
386
387static fpos_t
271
272 if ((e = _ftp_cmd(cd, "MDTM %s", s)) != FTP_FILE_STATUS) {
273 _ftp_seterr(e);
274 return -1;
275 }
276 for (ln = last_reply + 4; *ln && isspace(*ln); ln++)
277 /* nothing */ ;
278 switch (strspn(ln, "0123456789")) {

--- 101 unchanged lines hidden (view full) ---

380 if (w >= 0)
381 return w;
382 if (errno != EINTR)
383 io->err = errno;
384 return -1;
385}
386
387static fpos_t
388_ftp_seekfn(void *v, fpos_t pos, int whence)
388_ftp_seekfn(void *v, fpos_t pos __unused, int whence __unused)
389{
390 struct ftpio *io;
391
392 io = (struct ftpio *)v;
393 if (io == NULL) {
394 errno = EBADF;
395 return -1;
396 }

--- 48 unchanged lines hidden (view full) ---

445
446/*
447 * Transfer file
448 */
449static FILE *
450_ftp_transfer(int cd, const char *oper, const char *file,
451 int mode, off_t offset, const char *flags)
452{
389{
390 struct ftpio *io;
391
392 io = (struct ftpio *)v;
393 if (io == NULL) {
394 errno = EBADF;
395 return -1;
396 }

--- 48 unchanged lines hidden (view full) ---

445
446/*
447 * Transfer file
448 */
449static FILE *
450_ftp_transfer(int cd, const char *oper, const char *file,
451 int mode, off_t offset, const char *flags)
452{
453 struct sockaddr_storage sin;
453 struct sockaddr_storage sa;
454 struct sockaddr_in6 *sin6;
455 struct sockaddr_in *sin4;
456 int low, pasv, verbose;
457 int e, sd = -1;
458 socklen_t l;
459 char *s;
460 FILE *df;
461
462 /* check flags */
463 low = CHECK_FLAG('l');
464 pasv = CHECK_FLAG('p');
465 verbose = CHECK_FLAG('v');
466
467 /* passive mode */
468 if (!pasv)
469 pasv = ((s = getenv("FTP_PASSIVE_MODE")) != NULL &&
470 strncasecmp(s, "no", 2) != 0);
471
472 /* find our own address, bind, and listen */
454 struct sockaddr_in6 *sin6;
455 struct sockaddr_in *sin4;
456 int low, pasv, verbose;
457 int e, sd = -1;
458 socklen_t l;
459 char *s;
460 FILE *df;
461
462 /* check flags */
463 low = CHECK_FLAG('l');
464 pasv = CHECK_FLAG('p');
465 verbose = CHECK_FLAG('v');
466
467 /* passive mode */
468 if (!pasv)
469 pasv = ((s = getenv("FTP_PASSIVE_MODE")) != NULL &&
470 strncasecmp(s, "no", 2) != 0);
471
472 /* find our own address, bind, and listen */
473 l = sizeof sin;
474 if (getsockname(cd, (struct sockaddr *)&sin, &l) == -1)
473 l = sizeof sa;
474 if (getsockname(cd, (struct sockaddr *)&sa, &l) == -1)
475 goto sysouch;
475 goto sysouch;
476 if (sin.ss_family == AF_INET6)
477 unmappedaddr((struct sockaddr_in6 *)&sin);
476 if (sa.ss_family == AF_INET6)
477 unmappedaddr((struct sockaddr_in6 *)&sa);
478
479 /* open data socket */
478
479 /* open data socket */
480 if ((sd = socket(sin.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
480 if ((sd = socket(sa.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
481 _fetch_syserr();
482 return NULL;
483 }
484
485 if (pasv) {
486 u_char addr[64];
487 char *ln, *p;
481 _fetch_syserr();
482 return NULL;
483 }
484
485 if (pasv) {
486 u_char addr[64];
487 char *ln, *p;
488 int i;
488 unsigned int i;
489 int port;
490
491 /* send PASV command */
492 if (verbose)
493 _fetch_info("setting passive mode");
489 int port;
490
491 /* send PASV command */
492 if (verbose)
493 _fetch_info("setting passive mode");
494 switch (sin.ss_family) {
494 switch (sa.ss_family) {
495 case AF_INET:
496 if ((e = _ftp_cmd(cd, "PASV")) != FTP_PASSIVE_MODE)
497 goto ouch;
498 break;
499 case AF_INET6:
500 if ((e = _ftp_cmd(cd, "EPSV")) != FTP_EPASSIVE_MODE) {
501 if (e == -1)
502 goto ouch;

--- 47 unchanged lines hidden (view full) ---

550 }
551
552 /* seek to required offset */
553 if (offset)
554 if (_ftp_cmd(cd, "REST %lu", (u_long)offset) != FTP_FILE_OK)
555 goto sysouch;
556
557 /* construct sockaddr for data socket */
495 case AF_INET:
496 if ((e = _ftp_cmd(cd, "PASV")) != FTP_PASSIVE_MODE)
497 goto ouch;
498 break;
499 case AF_INET6:
500 if ((e = _ftp_cmd(cd, "EPSV")) != FTP_EPASSIVE_MODE) {
501 if (e == -1)
502 goto ouch;

--- 47 unchanged lines hidden (view full) ---

550 }
551
552 /* seek to required offset */
553 if (offset)
554 if (_ftp_cmd(cd, "REST %lu", (u_long)offset) != FTP_FILE_OK)
555 goto sysouch;
556
557 /* construct sockaddr for data socket */
558 l = sizeof sin;
559 if (getpeername(cd, (struct sockaddr *)&sin, &l) == -1)
558 l = sizeof sa;
559 if (getpeername(cd, (struct sockaddr *)&sa, &l) == -1)
560 goto sysouch;
560 goto sysouch;
561 if (sin.ss_family == AF_INET6)
562 unmappedaddr((struct sockaddr_in6 *)&sin);
563 switch (sin.ss_family) {
561 if (sa.ss_family == AF_INET6)
562 unmappedaddr((struct sockaddr_in6 *)&sa);
563 switch (sa.ss_family) {
564 case AF_INET6:
564 case AF_INET6:
565 sin6 = (struct sockaddr_in6 *)&sin;
565 sin6 = (struct sockaddr_in6 *)&sa;
566 if (e == FTP_EPASSIVE_MODE)
567 sin6->sin6_port = htons(port);
568 else {
569 bcopy(addr + 2, (char *)&sin6->sin6_addr, 16);
570 bcopy(addr + 19, (char *)&sin6->sin6_port, 2);
571 }
572 break;
573 case AF_INET:
566 if (e == FTP_EPASSIVE_MODE)
567 sin6->sin6_port = htons(port);
568 else {
569 bcopy(addr + 2, (char *)&sin6->sin6_addr, 16);
570 bcopy(addr + 19, (char *)&sin6->sin6_port, 2);
571 }
572 break;
573 case AF_INET:
574 sin4 = (struct sockaddr_in *)&sin;
574 sin4 = (struct sockaddr_in *)&sa;
575 if (e == FTP_EPASSIVE_MODE)
576 sin4->sin_port = htons(port);
577 else {
578 bcopy(addr, (char *)&sin4->sin_addr, 4);
579 bcopy(addr + 4, (char *)&sin4->sin_port, 2);
580 }
581 break;
582 default:
583 e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */
584 break;
585 }
586
587 /* connect to data port */
588 if (verbose)
589 _fetch_info("opening data connection");
575 if (e == FTP_EPASSIVE_MODE)
576 sin4->sin_port = htons(port);
577 else {
578 bcopy(addr, (char *)&sin4->sin_addr, 4);
579 bcopy(addr + 4, (char *)&sin4->sin_port, 2);
580 }
581 break;
582 default:
583 e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */
584 break;
585 }
586
587 /* connect to data port */
588 if (verbose)
589 _fetch_info("opening data connection");
590 if (connect(sd, (struct sockaddr *)&sin, sin.ss_len) == -1)
590 if (connect(sd, (struct sockaddr *)&sa, sa.ss_len) == -1)
591 goto sysouch;
592
593 /* make the server initiate the transfer */
594 if (verbose)
595 _fetch_info("initiating transfer");
596 e = _ftp_cmd(cd, "%s %s", oper, _ftp_filename(file));
597 if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION)
598 goto ouch;
599
600 } else {
601 u_int32_t a;
602 u_short p;
603 int arg, d;
604 char *ap;
605 char hname[INET6_ADDRSTRLEN];
606
591 goto sysouch;
592
593 /* make the server initiate the transfer */
594 if (verbose)
595 _fetch_info("initiating transfer");
596 e = _ftp_cmd(cd, "%s %s", oper, _ftp_filename(file));
597 if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION)
598 goto ouch;
599
600 } else {
601 u_int32_t a;
602 u_short p;
603 int arg, d;
604 char *ap;
605 char hname[INET6_ADDRSTRLEN];
606
607 switch (sin.ss_family) {
607 switch (sa.ss_family) {
608 case AF_INET6:
608 case AF_INET6:
609 ((struct sockaddr_in6 *)&sin)->sin6_port = 0;
609 ((struct sockaddr_in6 *)&sa)->sin6_port = 0;
610#ifdef IPV6_PORTRANGE
611 arg = low ? IPV6_PORTRANGE_DEFAULT : IPV6_PORTRANGE_HIGH;
612 if (setsockopt(sd, IPPROTO_IPV6, IPV6_PORTRANGE,
613 (char *)&arg, sizeof(arg)) == -1)
614 goto sysouch;
615#endif
616 break;
617 case AF_INET:
610#ifdef IPV6_PORTRANGE
611 arg = low ? IPV6_PORTRANGE_DEFAULT : IPV6_PORTRANGE_HIGH;
612 if (setsockopt(sd, IPPROTO_IPV6, IPV6_PORTRANGE,
613 (char *)&arg, sizeof(arg)) == -1)
614 goto sysouch;
615#endif
616 break;
617 case AF_INET:
618 ((struct sockaddr_in *)&sin)->sin_port = 0;
618 ((struct sockaddr_in *)&sa)->sin_port = 0;
619 arg = low ? IP_PORTRANGE_DEFAULT : IP_PORTRANGE_HIGH;
620 if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
621 (char *)&arg, sizeof arg) == -1)
622 goto sysouch;
623 break;
624 }
625 if (verbose)
626 _fetch_info("binding data socket");
619 arg = low ? IP_PORTRANGE_DEFAULT : IP_PORTRANGE_HIGH;
620 if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
621 (char *)&arg, sizeof arg) == -1)
622 goto sysouch;
623 break;
624 }
625 if (verbose)
626 _fetch_info("binding data socket");
627 if (bind(sd, (struct sockaddr *)&sin, sin.ss_len) == -1)
627 if (bind(sd, (struct sockaddr *)&sa, sa.ss_len) == -1)
628 goto sysouch;
629 if (listen(sd, 1) == -1)
630 goto sysouch;
631
632 /* find what port we're on and tell the server */
628 goto sysouch;
629 if (listen(sd, 1) == -1)
630 goto sysouch;
631
632 /* find what port we're on and tell the server */
633 if (getsockname(sd, (struct sockaddr *)&sin, &l) == -1)
633 if (getsockname(sd, (struct sockaddr *)&sa, &l) == -1)
634 goto sysouch;
634 goto sysouch;
635 switch (sin.ss_family) {
635 switch (sa.ss_family) {
636 case AF_INET:
636 case AF_INET:
637 sin4 = (struct sockaddr_in *)&sin;
637 sin4 = (struct sockaddr_in *)&sa;
638 a = ntohl(sin4->sin_addr.s_addr);
639 p = ntohs(sin4->sin_port);
640 e = _ftp_cmd(cd, "PORT %d,%d,%d,%d,%d,%d",
641 (a >> 24) & 0xff, (a >> 16) & 0xff,
642 (a >> 8) & 0xff, a & 0xff,
643 (p >> 8) & 0xff, p & 0xff);
644 break;
645 case AF_INET6:
646#define UC(b) (((int)b)&0xff)
647 e = -1;
638 a = ntohl(sin4->sin_addr.s_addr);
639 p = ntohs(sin4->sin_port);
640 e = _ftp_cmd(cd, "PORT %d,%d,%d,%d,%d,%d",
641 (a >> 24) & 0xff, (a >> 16) & 0xff,
642 (a >> 8) & 0xff, a & 0xff,
643 (p >> 8) & 0xff, p & 0xff);
644 break;
645 case AF_INET6:
646#define UC(b) (((int)b)&0xff)
647 e = -1;
648 sin6 = (struct sockaddr_in6 *)&sin;
649 if (getnameinfo((struct sockaddr *)&sin, sin.ss_len,
648 sin6 = (struct sockaddr_in6 *)&sa;
649 if (getnameinfo((struct sockaddr *)&sa, sa.ss_len,
650 hname, sizeof(hname),
651 NULL, 0, NI_NUMERICHOST) == 0) {
652 e = _ftp_cmd(cd, "EPRT |%d|%s|%d|", 2, hname,
653 htons(sin6->sin6_port));
654 if (e == -1)
655 goto ouch;
656 }
657 if (e != FTP_OK) {

--- 55 unchanged lines hidden (view full) ---

713}
714
715/*
716 * Authenticate
717 */
718static int
719_ftp_authenticate(int cd, struct url *url, struct url *purl)
720{
650 hname, sizeof(hname),
651 NULL, 0, NI_NUMERICHOST) == 0) {
652 e = _ftp_cmd(cd, "EPRT |%d|%s|%d|", 2, hname,
653 htons(sin6->sin6_port));
654 if (e == -1)
655 goto ouch;
656 }
657 if (e != FTP_OK) {

--- 55 unchanged lines hidden (view full) ---

713}
714
715/*
716 * Authenticate
717 */
718static int
719_ftp_authenticate(int cd, struct url *url, struct url *purl)
720{
721 char *user, *pwd, *logname;
721 const char *user, *pwd, *logname;
722 char pbuf[MAXHOSTNAMELEN + MAXLOGNAME + 1];
723 int e, len;
724
725 /* XXX FTP_AUTH, and maybe .netrc */
726
727 /* send user name and password */
728 user = url->user;
729 if (!user || !*user)

--- 293 unchanged lines hidden (view full) ---

1023 /* stat file */
1024 return _ftp_stat(cd, url->doc, us);
1025}
1026
1027/*
1028 * List a directory
1029 */
1030struct url_ent *
722 char pbuf[MAXHOSTNAMELEN + MAXLOGNAME + 1];
723 int e, len;
724
725 /* XXX FTP_AUTH, and maybe .netrc */
726
727 /* send user name and password */
728 user = url->user;
729 if (!user || !*user)

--- 293 unchanged lines hidden (view full) ---

1023 /* stat file */
1024 return _ftp_stat(cd, url->doc, us);
1025}
1026
1027/*
1028 * List a directory
1029 */
1030struct url_ent *
1031fetchListFTP(struct url *url, const char *flags)
1031fetchListFTP(struct url *url __unused, const char *flags __unused)
1032{
1033 warnx("fetchListFTP(): not implemented");
1034 return NULL;
1035}
1032{
1033 warnx("fetchListFTP(): not implemented");
1034 return NULL;
1035}