Deleted Added
full compact
ftpio.c (60051) ftpio.c (62649)
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 * Major Changelog:
10 *
11 * Jordan K. Hubbard
12 * 17 Jan 1996
13 *
14 * Turned inside out. Now returns xfers as new file ids, not as a special
15 * `state' of FTP_t
16 *
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 * Major Changelog:
10 *
11 * Jordan K. Hubbard
12 * 17 Jan 1996
13 *
14 * Turned inside out. Now returns xfers as new file ids, not as a special
15 * `state' of FTP_t
16 *
17 * $FreeBSD: head/lib/libftpio/ftpio.c 60051 2000-05-05 17:02:32Z billf $
17 * $FreeBSD: head/lib/libftpio/ftpio.c 62649 2000-07-05 19:34:43Z ume $
18 *
19 */
20
21#include <sys/types.h>
22#include <sys/socket.h>
23
24#include <netinet/in.h>
25

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

53static int ftp_read_method(void *n, char *buf, int nbytes);
54static int ftp_write_method(void *n, const char *buf, int nbytes);
55static int ftp_close_method(void *n);
56static int writes(int fd, char *s);
57static __inline char *get_a_line(FTP_t ftp);
58static int get_a_number(FTP_t ftp, char **q);
59static int botch(char *func, char *botch_state);
60static int cmd(FTP_t ftp, const char *fmt, ...);
18 *
19 */
20
21#include <sys/types.h>
22#include <sys/socket.h>
23
24#include <netinet/in.h>
25

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

53static int ftp_read_method(void *n, char *buf, int nbytes);
54static int ftp_write_method(void *n, const char *buf, int nbytes);
55static int ftp_close_method(void *n);
56static int writes(int fd, char *s);
57static __inline char *get_a_line(FTP_t ftp);
58static int get_a_number(FTP_t ftp, char **q);
59static int botch(char *func, char *botch_state);
60static int cmd(FTP_t ftp, const char *fmt, ...);
61static int ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int verbose);
61static int ftp_login_session(FTP_t ftp, char *host, int af, char *user, char *passwd, int port, int verbose);
62static int ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto);
63static int ftp_close(FTP_t ftp);
64static int get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret);
65static void ftp_timeout(int sig);
66static void ftp_set_timeout(void);
67static void ftp_clear_timeout(void);
62static int ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto);
63static int ftp_close(FTP_t ftp);
64static int get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret);
65static void ftp_timeout(int sig);
66static void ftp_set_timeout(void);
67static void ftp_clear_timeout(void);
68static void ai_unmapped(struct addrinfo *);
68
69
70/* Global status variable - ick */
71int FtpTimedOut;
72
73/* FTP happy status codes */
74#define FTP_GENERALLY_HAPPY 200
75#define FTP_ASCII_HAPPY FTP_GENERALLY_HAPPY
76#define FTP_BINARY_HAPPY FTP_GENERALLY_HAPPY
77#define FTP_PORT_HAPPY FTP_GENERALLY_HAPPY
78#define FTP_HAPPY_COMMENT 220
79#define FTP_QUIT_HAPPY 221
80#define FTP_TRANSFER_HAPPY 226
81#define FTP_PASSIVE_HAPPY 227
69
70
71/* Global status variable - ick */
72int FtpTimedOut;
73
74/* FTP happy status codes */
75#define FTP_GENERALLY_HAPPY 200
76#define FTP_ASCII_HAPPY FTP_GENERALLY_HAPPY
77#define FTP_BINARY_HAPPY FTP_GENERALLY_HAPPY
78#define FTP_PORT_HAPPY FTP_GENERALLY_HAPPY
79#define FTP_HAPPY_COMMENT 220
80#define FTP_QUIT_HAPPY 221
81#define FTP_TRANSFER_HAPPY 226
82#define FTP_PASSIVE_HAPPY 227
83#define FTP_LPASSIVE_HAPPY 228
84#define FTP_EPASSIVE_HAPPY 229
82#define FTP_CHDIR_HAPPY 250
83
84/* FTP unhappy status codes */
85#define FTP_TIMED_OUT 421
86
87/*
88 * XXX
89 * gross! evil! bad! We really need an access primitive for cookie in stdio itself.

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

262 return fp2;
263 return NULL;
264}
265
266/* Returns a standard FILE pointer type representing an open control connection */
267FILE *
268ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode)
269{
85#define FTP_CHDIR_HAPPY 250
86
87/* FTP unhappy status codes */
88#define FTP_TIMED_OUT 421
89
90/*
91 * XXX
92 * gross! evil! bad! We really need an access primitive for cookie in stdio itself.

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

265 return fp2;
266 return NULL;
267}
268
269/* Returns a standard FILE pointer type representing an open control connection */
270FILE *
271ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode)
272{
273#ifdef INET6
274 return ftpLoginAf(host, AF_UNSPEC, user, passwd, port, verbose, retcode);
275#else
276 return ftpLoginAf(host, AF_INET, user, passwd, port, verbose, retcode);
277#endif
278}
279
280FILE *
281ftpLoginAf(char *host, int af, char *user, char *passwd, int port, int verbose, int *retcode)
282{
270 FTP_t n;
271 FILE *fp;
272
273 if (retcode)
274 *retcode = 0;
275 if (networkInit() != SUCCESS)
276 return NULL;
277
278 n = ftp_new();
279 fp = NULL;
283 FTP_t n;
284 FILE *fp;
285
286 if (retcode)
287 *retcode = 0;
288 if (networkInit() != SUCCESS)
289 return NULL;
290
291 n = ftp_new();
292 fp = NULL;
280 if (n && ftp_login_session(n, host, user, passwd, port, verbose) == SUCCESS) {
293 if (n && ftp_login_session(n, host, af, user, passwd, port, verbose) == SUCCESS) {
281 fp = funopen(n, ftp_read_method, ftp_write_method, NULL, ftp_close_method); /* BSD 4.4 function! */
282 fp->_file = n->fd_ctrl;
283 }
284 if (retcode) {
285 if (!n)
286 *retcode = (FtpTimedOut ? FTP_TIMED_OUT : -1);
287 /* Poor attempt at mapping real errnos to FTP error codes */
288 else switch(n->error) {

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

318int
319ftpPassive(FILE *fp, int st)
320{
321 FTP_t ftp = fcookie(fp);
322 int i;
323
324 if (ftp->is_passive == st)
325 return SUCCESS;
294 fp = funopen(n, ftp_read_method, ftp_write_method, NULL, ftp_close_method); /* BSD 4.4 function! */
295 fp->_file = n->fd_ctrl;
296 }
297 if (retcode) {
298 if (!n)
299 *retcode = (FtpTimedOut ? FTP_TIMED_OUT : -1);
300 /* Poor attempt at mapping real errnos to FTP error codes */
301 else switch(n->error) {

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

331int
332ftpPassive(FILE *fp, int st)
333{
334 FTP_t ftp = fcookie(fp);
335 int i;
336
337 if (ftp->is_passive == st)
338 return SUCCESS;
326 i = cmd(ftp, "PASV");
327 if (i < 0)
328 return i;
329 if (i != FTP_PASSIVE_HAPPY)
330 return FAILURE;
339 switch (ftp->addrtype) {
340 case AF_INET:
341 i = cmd(ftp, "PASV");
342 if (i < 0)
343 return i;
344 if (i != FTP_PASSIVE_HAPPY)
345 return FAILURE;
346 break;
347 case AF_INET6:
348 i = cmd(ftp, "EPSV");
349 if (i < 0)
350 return i;
351 if (i != FTP_EPASSIVE_HAPPY) {
352 i = cmd(ftp, "LPSV");
353 if (i < 0)
354 return i;
355 if (i != FTP_LPASSIVE_HAPPY)
356 return FAILURE;
357 }
358 break;
359 }
331 ftp->is_passive = !ftp->is_passive;
332 return SUCCESS;
333}
334
335FILE *
336ftpGetURL(char *url, char *user, char *passwd, int *retcode)
337{
360 ftp->is_passive = !ftp->is_passive;
361 return SUCCESS;
362}
363
364FILE *
365ftpGetURL(char *url, char *user, char *passwd, int *retcode)
366{
367#ifdef INET6
368 return ftpGetURLAf(url, AF_UNSPEC, user, passwd, retcode);
369#else
370 return ftpGetURLAf(url, AF_INET, user, passwd, retcode);
371#endif
372}
373
374FILE *
375ftpGetURLAf(char *url, int af, char *user, char *passwd, int *retcode)
376{
338 char host[255], name[255];
339 int port;
340 FILE *fp2;
341 static FILE *fp = NULL;
342 static char *prev_host;
343
344 if (retcode)
345 *retcode = 0;

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

359 }
360 else {
361 /* It's a different host now, flush old */
362 fclose(fp);
363 free(prev_host);
364 prev_host = NULL;
365 }
366 }
377 char host[255], name[255];
378 int port;
379 FILE *fp2;
380 static FILE *fp = NULL;
381 static char *prev_host;
382
383 if (retcode)
384 *retcode = 0;

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

398 }
399 else {
400 /* It's a different host now, flush old */
401 fclose(fp);
402 free(prev_host);
403 prev_host = NULL;
404 }
405 }
367 fp = ftpLogin(host, user, passwd, port, 0, retcode);
406 fp = ftpLoginAf(host, af, user, passwd, port, 0, retcode);
368 if (fp) {
369 fp2 = ftpGet(fp, name, NULL);
370 if (!fp2) {
371 /* Connection timed out or was no longer valid */
372 if (retcode)
373 *retcode = ftpErrno(fp);
374 fclose(fp);
375 fp = NULL;

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

380 }
381 }
382 return NULL;
383}
384
385FILE *
386ftpPutURL(char *url, char *user, char *passwd, int *retcode)
387{
407 if (fp) {
408 fp2 = ftpGet(fp, name, NULL);
409 if (!fp2) {
410 /* Connection timed out or was no longer valid */
411 if (retcode)
412 *retcode = ftpErrno(fp);
413 fclose(fp);
414 fp = NULL;

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

419 }
420 }
421 return NULL;
422}
423
424FILE *
425ftpPutURL(char *url, char *user, char *passwd, int *retcode)
426{
427#ifdef INET6
428 return ftpPutURLAf(url, AF_UNSPEC, user, passwd, retcode);
429#else
430 return ftpPutURLAf(url, AF_INET, user, passwd, retcode);
431#endif
432
433}
434
435FILE *
436ftpPutURLAf(char *url, int af, char *user, char *passwd, int *retcode)
437{
388 char host[255], name[255];
389 int port;
390 static FILE *fp = NULL;
391 FILE *fp2;
392
393 if (retcode)
394 *retcode = 0;
395 if (fp) { /* Close previous managed connection */
396 fclose(fp);
397 fp = NULL;
398 }
399 if (get_url_info(url, host, &port, name) == SUCCESS) {
438 char host[255], name[255];
439 int port;
440 static FILE *fp = NULL;
441 FILE *fp2;
442
443 if (retcode)
444 *retcode = 0;
445 if (fp) { /* Close previous managed connection */
446 fclose(fp);
447 fp = NULL;
448 }
449 if (get_url_info(url, host, &port, name) == SUCCESS) {
400 fp = ftpLogin(host, user, passwd, port, 0, retcode);
450 fp = ftpLoginAf(host, af, user, passwd, port, 0, retcode);
401 if (fp) {
402 fp2 = ftpPut(fp, name);
403 if (!fp2) {
404 if (retcode)
405 *retcode = ftpErrno(fp);
406 fclose(fp);
407 fp = NULL;
408 }

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

667 return FTP_TIMED_OUT;
668 return FAILURE;
669 }
670 while ((i = get_a_number(ftp, NULL)) == FTP_HAPPY_COMMENT);
671 return i;
672}
673
674static int
451 if (fp) {
452 fp2 = ftpPut(fp, name);
453 if (!fp2) {
454 if (retcode)
455 *retcode = ftpErrno(fp);
456 fclose(fp);
457 fp = NULL;
458 }

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

717 return FTP_TIMED_OUT;
718 return FAILURE;
719 }
720 while ((i = get_a_number(ftp, NULL)) == FTP_HAPPY_COMMENT);
721 return i;
722}
723
724static int
675ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int verbose)
725ftp_login_session(FTP_t ftp, char *host, int af,
726 char *user, char *passwd, int port, int verbose)
676{
727{
677 struct hostent *he = NULL;
678 struct sockaddr_in sin;
728 char pbuf[10];
729 struct addrinfo hints, *res, *res0;
730 int err;
679 int s;
731 int s;
680 unsigned long temp;
681 int i;
682
683 if (networkInit() != SUCCESS)
684 return FAILURE;
685
686 if (ftp->con_state != init) {
687 ftp_close(ftp);
688 ftp->error = -1;

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

693 user = "ftp";
694
695 if (!passwd)
696 passwd = "setup@";
697
698 if (!port)
699 port = 21;
700
732 int i;
733
734 if (networkInit() != SUCCESS)
735 return FAILURE;
736
737 if (ftp->con_state != init) {
738 ftp_close(ftp);
739 ftp->error = -1;

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

744 user = "ftp";
745
746 if (!passwd)
747 passwd = "setup@";
748
749 if (!port)
750 port = 21;
751
701 temp = inet_addr(host);
702 if (temp != INADDR_NONE) {
703 ftp->addrtype = sin.sin_family = AF_INET;
704 sin.sin_addr.s_addr = temp;
752 snprintf(pbuf, sizeof(pbuf), "%d", port);
753 memset(&hints, 0, sizeof(hints));
754 hints.ai_family = af;
755 hints.ai_socktype = SOCK_STREAM;
756 hints.ai_protocol = 0;
757 err = getaddrinfo(host, pbuf, &hints, &res0);
758 if (err) {
759 ftp->error = 0;
760 return FAILURE;
705 }
761 }
706 else {
707 he = gethostbyname(host);
708 if (!he) {
709 ftp->error = 0;
710 return FAILURE;
711 }
712 ftp->addrtype = sin.sin_family = he->h_addrtype;
713 bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
714 }
715
762
716 sin.sin_port = htons(port);
763 s = -1;
764 for (res = res0; res; res = res->ai_next) {
765 ai_unmapped(res);
766 ftp->addrtype = res->ai_family;
717
767
718 if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0) {
719 ftp->error = -1;
720 return FAILURE;
721 }
768 if ((s = socket(res->ai_family, res->ai_socktype,
769 res->ai_protocol)) < 0)
770 continue;
722
771
723 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
724 (void)close(s);
772 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
773 (void)close(s);
774 s = -1;
775 continue;
776 }
777
778 break;
779 }
780 freeaddrinfo(res0);
781 if (s < 0) {
725 ftp->error = errno;
726 return FAILURE;
727 }
728
729 ftp->fd_ctrl = s;
730 ftp->con_state = isopen;
731 ftp->is_verbose = verbose;
732

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

740 return FAILURE;
741 }
742 return SUCCESS;
743}
744
745static int
746ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto)
747{
782 ftp->error = errno;
783 return FAILURE;
784 }
785
786 ftp->fd_ctrl = s;
787 ftp->con_state = isopen;
788 ftp->is_verbose = verbose;
789

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

797 return FAILURE;
798 }
799 return SUCCESS;
800}
801
802static int
803ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto)
804{
748 int i,s;
805 int i,l,s;
749 char *q;
750 unsigned char addr[64];
806 char *q;
807 unsigned char addr[64];
751 struct sockaddr_in sin;
752 u_long a;
808 union sockaddr_cmn {
809 struct sockaddr_in sin4;
810 struct sockaddr_in6 sin6;
811 } sin;
812 char *cmdstr;
753
754 if (!fp)
755 return FAILURE;
756 *fp = NULL;
757
758 if (ftp->con_state != isopen)
759 return botch("ftp_file_op", "open");
760
761 if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0) {
762 ftp->error = errno;
763 return FAILURE;
764 }
765
766 if (ftp->is_passive) {
813
814 if (!fp)
815 return FAILURE;
816 *fp = NULL;
817
818 if (ftp->con_state != isopen)
819 return botch("ftp_file_op", "open");
820
821 if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0) {
822 ftp->error = errno;
823 return FAILURE;
824 }
825
826 if (ftp->is_passive) {
767 if (ftp->is_verbose)
768 fprintf(stderr, "Sending PASV\n");
769 if (writes(ftp->fd_ctrl, "PASV\r\n")) {
770 ftp_close(ftp);
771 if (FtpTimedOut)
772 ftp->error = FTP_TIMED_OUT;
773 return FTP_TIMED_OUT;
827 if (ftp->addrtype == AF_INET) {
828 if (ftp->is_verbose)
829 fprintf(stderr, "Sending PASV\n");
830 if (writes(ftp->fd_ctrl, "PASV\r\n")) {
831 ftp_close(ftp);
832 if (FtpTimedOut)
833 ftp->error = FTP_TIMED_OUT;
834 return FTP_TIMED_OUT;
835 }
836 i = get_a_number(ftp, &q);
837 if (check_code(ftp, i, FTP_PASSIVE_HAPPY)) {
838 ftp_close(ftp);
839 return i;
840 }
841 cmdstr = "PASV";
842 } else {
843 if (ftp->is_verbose)
844 fprintf(stderr, "Sending EPSV\n");
845 if (writes(ftp->fd_ctrl, "EPSV\r\n")) {
846 ftp_close(ftp);
847 if (FtpTimedOut)
848 ftp->error = FTP_TIMED_OUT;
849 return FTP_TIMED_OUT;
850 }
851 i = get_a_number(ftp, &q);
852 if (check_code(ftp, i, FTP_EPASSIVE_HAPPY)) {
853 if (ftp->is_verbose)
854 fprintf(stderr, "Sending LPSV\n");
855 if (writes(ftp->fd_ctrl, "LPSV\r\n")) {
856 ftp_close(ftp);
857 if (FtpTimedOut)
858 ftp->error = FTP_TIMED_OUT;
859 return FTP_TIMED_OUT;
860 }
861 i = get_a_number(ftp, &q);
862 if (check_code(ftp, i, FTP_LPASSIVE_HAPPY)) {
863 ftp_close(ftp);
864 return i;
865 }
866 cmdstr = "LPSV";
867 } else
868 cmdstr = "EPSV";
774 }
869 }
775 i = get_a_number(ftp, &q);
776 if (check_code(ftp, i, FTP_PASSIVE_HAPPY)) {
777 ftp_close(ftp);
778 return i;
779 }
780 while (*q && !isdigit(*q))
870 while (*q && *q != '(') /* ) */
781 q++;
782 if (!*q) {
783 ftp_close(ftp);
784 return FAILURE;
785 }
871 q++;
872 if (!*q) {
873 ftp_close(ftp);
874 return FAILURE;
875 }
786 q--;
787 for (i = 0; i < 6; i++) {
876 if (strcmp(cmdstr, "PASV") == 0 || strcmp(cmdstr, "LPSV") == 0) {
877 l = (ftp->addrtype == AF_INET ? 6 : 21);
878 for (i = 0; i < l; i++) {
879 q++;
880 addr[i] = strtol(q, &q, 10);
881 }
882
883 sin.sin4.sin_family = ftp->addrtype;
884 if (ftp->addrtype == AF_INET6) {
885 sin.sin6.sin6_len = sizeof(struct sockaddr_in6);
886 bcopy(addr + 2, (char *)&sin.sin6.sin6_addr, 16);
887 bcopy(addr + 19, (char *)&sin.sin6.sin6_port, 2);
888 } else {
889 sin.sin4.sin_len = sizeof(struct sockaddr_in);
890 bcopy(addr, (char *)&sin.sin4.sin_addr, 4);
891 bcopy(addr + 4, (char *)&sin.sin4.sin_port, 2);
892 }
893 } else if (strcmp(cmdstr, "EPSV") == 0) {
894 int port;
895 int sinlen;
788 q++;
896 q++;
789 addr[i] = strtol(q, &q, 10);
897 if (sscanf(q, "%c%c%c%d%c", &addr[0], &addr[1], &addr[2],
898 &port, &addr[3]) != 5
899 || addr[0] != addr[1] || addr[0] != addr[2] || addr[0] != addr[3]) {
900 ftp_close(ftp);
901 return FAILURE;
902 }
903 sinlen = sizeof(sin);
904 if (getpeername(ftp->fd_ctrl, (struct sockaddr *)&sin, &sinlen) < 0) {
905 ftp_close(ftp);
906 return FAILURE;
907 }
908 switch (sin.sin4.sin_family) {
909 case AF_INET:
910 sin.sin4.sin_port = htons(port);
911 break;
912 case AF_INET6:
913 sin.sin6.sin6_port = htons(port);
914 break;
915 default:
916 ftp_close(ftp);
917 return FAILURE;
918 }
790 }
791
919 }
920
792 sin.sin_family = ftp->addrtype;
793 bcopy(addr, (char *)&sin.sin_addr, 4);
794 bcopy(addr + 4, (char *)&sin.sin_port, 2);
795 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
921 if (connect(s, (struct sockaddr *)&sin, sin.sin4.sin_len) < 0) {
796 (void)close(s);
797 return FAILURE;
798 }
799
800 if (seekto && *seekto) {
801 i = cmd(ftp, "REST %d", *seekto);
802 if (i < 0 || FTP_TIMEOUT(i)) {
803 close(s);

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

812 ftp->error = i;
813 return i;
814 }
815 *fp = fdopen(s, mode);
816 }
817 else {
818 int fd,portrange;
819
922 (void)close(s);
923 return FAILURE;
924 }
925
926 if (seekto && *seekto) {
927 i = cmd(ftp, "REST %d", *seekto);
928 if (i < 0 || FTP_TIMEOUT(i)) {
929 close(s);

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

938 ftp->error = i;
939 return i;
940 }
941 *fp = fdopen(s, mode);
942 }
943 else {
944 int fd,portrange;
945
946#ifdef IPV6_PORTRANGE
947 if (ftp->addrtype == AF_INET6) {
948 portrange = IPV6_PORTRANGE_HIGH;
949 if (setsockopt(s, IPPROTO_IPV6, IPV6_PORTRANGE, (char *)
950 &portrange, sizeof(portrange)) < 0) {
951 close(s);
952 return FAILURE;
953 }
954 }
955#endif
820#ifdef IP_PORTRANGE
956#ifdef IP_PORTRANGE
821 portrange = IP_PORTRANGE_HIGH;
822 if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, (char *)
823 &portrange, sizeof(portrange)) < 0) {
824 close(s);
825 return FAILURE;
826 };
957 if (ftp->addrtype == AF_INET) {
958 portrange = IP_PORTRANGE_HIGH;
959 if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, (char *)
960 &portrange, sizeof(portrange)) < 0) {
961 close(s);
962 return FAILURE;
963 }
964 }
827#endif
828
829 i = sizeof sin;
830 getsockname(ftp->fd_ctrl, (struct sockaddr *)&sin, &i);
965#endif
966
967 i = sizeof sin;
968 getsockname(ftp->fd_ctrl, (struct sockaddr *)&sin, &i);
831 sin.sin_port = 0;
832 i = sizeof sin;
969 sin.sin4.sin_port = 0;
970 i = ((struct sockaddr *)&sin)->sa_len;
833 if (bind(s, (struct sockaddr *)&sin, i) < 0) {
834 close(s);
835 return FAILURE;
836 }
971 if (bind(s, (struct sockaddr *)&sin, i) < 0) {
972 close(s);
973 return FAILURE;
974 }
975 i = sizeof sin;
837 getsockname(s,(struct sockaddr *)&sin,&i);
838 if (listen(s, 1) < 0) {
839 close(s);
840 return FAILURE;
841 }
976 getsockname(s,(struct sockaddr *)&sin,&i);
977 if (listen(s, 1) < 0) {
978 close(s);
979 return FAILURE;
980 }
842 a = ntohl(sin.sin_addr.s_addr);
843 i = cmd(ftp, "PORT %d,%d,%d,%d,%d,%d",
844 (a >> 24) & 0xff,
845 (a >> 16) & 0xff,
846 (a >> 8) & 0xff,
847 a & 0xff,
848 (ntohs(sin.sin_port) >> 8) & 0xff,
849 ntohs(sin.sin_port) & 0xff);
850 if (check_code(ftp, i, FTP_PORT_HAPPY)) {
851 close(s);
852 return i;
981 if (sin.sin4.sin_family == AF_INET) {
982 u_long a;
983 a = ntohl(sin.sin4.sin_addr.s_addr);
984 i = cmd(ftp, "PORT %d,%d,%d,%d,%d,%d",
985 (a >> 24) & 0xff,
986 (a >> 16) & 0xff,
987 (a >> 8) & 0xff,
988 a & 0xff,
989 (ntohs(sin.sin4.sin_port) >> 8) & 0xff,
990 ntohs(sin.sin4.sin_port) & 0xff);
991 if (check_code(ftp, i, FTP_PORT_HAPPY)) {
992 close(s);
993 return i;
994 }
995 } else {
996#define UC(b) (((int)b)&0xff)
997 char *a;
998 char hname[INET6_ADDRSTRLEN];
999
1000 if (getnameinfo((struct sockaddr *)&sin, sin.sin6.sin6_len,
1001 hname, sizeof(hname),
1002 NULL, 0, NI_NUMERICHOST) != 0) {
1003 goto try_lprt;
1004 }
1005 i = cmd(ftp, "EPRT |%d|%s|%d|", 2, hname,
1006 htons(sin.sin6.sin6_port));
1007 if (check_code(ftp, i, FTP_PORT_HAPPY)) {
1008try_lprt:
1009 a = (char *)&sin.sin6.sin6_addr;
1010 i = cmd(ftp,
1011"LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
1012 6, 16,
1013 UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
1014 UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
1015 UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
1016 UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
1017 2,
1018 (ntohs(sin.sin4.sin_port) >> 8) & 0xff,
1019 ntohs(sin.sin4.sin_port) & 0xff);
1020 if (check_code(ftp, i, FTP_PORT_HAPPY)) {
1021 close(s);
1022 return i;
1023 }
1024 }
853 }
854 if (seekto && *seekto) {
855 i = cmd(ftp, "REST %d", *seekto);
856 if (i < 0 || FTP_TIMEOUT(i)) {
857 close(s);
858 ftp->error = i;
859 return i;
860 }

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

876 close(s);
877 *fp = fdopen(fd, mode);
878 }
879 if (*fp)
880 return SUCCESS;
881 else
882 return FAILURE;
883}
1025 }
1026 if (seekto && *seekto) {
1027 i = cmd(ftp, "REST %d", *seekto);
1028 if (i < 0 || FTP_TIMEOUT(i)) {
1029 close(s);
1030 ftp->error = i;
1031 return i;
1032 }

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

1048 close(s);
1049 *fp = fdopen(fd, mode);
1050 }
1051 if (*fp)
1052 return SUCCESS;
1053 else
1054 return FAILURE;
1055}
1056
1057static void
1058ai_unmapped(struct addrinfo *ai)
1059{
1060 struct sockaddr_in6 *sin6;
1061 struct sockaddr_in sin;
1062
1063 if (ai->ai_family != AF_INET6)
1064 return;
1065 if (ai->ai_addrlen != sizeof(struct sockaddr_in6) ||
1066 sizeof(sin) > ai->ai_addrlen)
1067 return;
1068 sin6 = (struct sockaddr_in6 *)ai->ai_addr;
1069 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
1070 return;
1071
1072 memset(&sin, 0, sizeof(sin));
1073 sin.sin_family = AF_INET;
1074 sin.sin_len = sizeof(struct sockaddr_in);
1075 memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
1076 sizeof(sin.sin_addr));
1077 sin.sin_port = sin6->sin6_port;
1078
1079 ai->ai_family = AF_INET;
1080 memcpy(ai->ai_addr, &sin, sin.sin_len);
1081 ai->ai_addrlen = sin.sin_len;
1082}