1 /* $FreeBSD: src/usr.bin/ftp/ftp.c,v 1.28.2.5 2002/07/25 15:29:18 ume Exp $ */
2 /* $DragonFly: src/usr.bin/ftp/Attic/ftp.c,v 1.5 2004/01/22 19:39:13 dillon Exp $ */
3 /* $NetBSD: ftp.c,v 1.29.2.1 1997/11/18 01:01:04 mellon Exp $ */
6 * Copyright (c) 1985, 1989, 1993, 1994
7 * The Regents of the University of California. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * @(#)ftp.c 8.6 (Berkeley) 10/27/94
38 * $NetBSD: ftp.c,v 1.29.2.1 1997/11/18 01:01:04 mellon Exp $
39 * $FreeBSD: src/usr.bin/ftp/ftp.c,v 1.28.2.5 2002/07/25 15:29:18 ume Exp $
42 #include <sys/cdefs.h>
44 #include <sys/types.h>
46 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <netinet/in_systm.h>
51 #include <netinet/ip.h>
52 #include <arpa/inet.h>
54 #include <arpa/telnet.h>
86 struct sockaddr_in su_sin;
87 struct sockaddr_in6 su_sin6;
89 #define su_len su_si.si_len
90 #define su_family su_si.si_family
91 #define su_port su_si.si_port
93 union sockunion myctladdr, hisctladdr, data_addr;
96 hookup(const char *host0, char *port)
98 int s, len, tos, error;
99 struct addrinfo hints, *res, *res0;
100 static char hostnamebuf[MAXHOSTNAMELEN];
103 if (*host0 == '[' && strrchr(host0, ']') != NULL) { /*IPv6 addr in []*/
104 strncpy(hostnamebuf, host0 + 1, strlen(host0) - 2);
105 hostnamebuf[strlen(host0) - 2] = '\0';
107 strncpy(hostnamebuf, host0, strlen(host0));
108 hostnamebuf[strlen(host0)] = '\0';
111 memset(&hints, 0, sizeof(hints));
112 hints.ai_flags = AI_CANONNAME;
113 hints.ai_family = family;
114 hints.ai_socktype = SOCK_STREAM;
115 hints.ai_protocol = 0;
116 error = getaddrinfo(host, port, &hints, &res0);
118 warnx("%s: %s", host, gai_strerror(error));
119 if (error == EAI_SYSTEM)
120 warnx("%s: %s", host, strerror(errno));
126 if (res->ai_canonname)
127 (void) strncpy(hostnamebuf, res->ai_canonname,
128 sizeof(hostnamebuf));
129 hostname = hostnamebuf;
132 * make sure that ai_addr is NOT an IPv4 mapped address.
133 * IPv4 mapped address complicates too many things in FTP
134 * protocol handling, as FTP protocol is defined differently
135 * between IPv4 and IPv6.
138 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
148 struct addrinfo *bindres;
151 for (bindres = bindres0;
153 bindres = bindres->ai_next)
154 if (bindres->ai_family == res->ai_family)
158 binderr = bind(s, bindres->ai_addr,
159 bindres->ai_addrlen);
172 if (connect(s, res->ai_addr, res->ai_addrlen) == 0)
175 char hname[NI_MAXHOST];
176 getnameinfo(res->ai_addr, res->ai_addrlen,
177 hname, sizeof(hname) - 1, NULL, 0,
179 warn("connect to address %s", hname);
181 getnameinfo(res->ai_addr, res->ai_addrlen,
182 hname, sizeof(hname) - 1, NULL, 0,
184 printf("Trying %s...\n", hname);
192 memcpy(&hisctladdr, res->ai_addr, res->ai_addrlen);
194 len = sizeof(myctladdr);
195 if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
201 if (myctladdr.su_family == AF_INET)
203 tos = IPTOS_LOWDELAY;
204 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
205 warn("setsockopt TOS (ignored)");
208 cin = fdopen(s, "r");
209 cout = fdopen(s, "w");
210 if (cin == NULL || cout == NULL) {
211 warnx("fdopen failed.");
220 printf("Connected to %s.\n", hostname);
221 if (getreply(0) > 2) { /* read startup message from server */
233 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
238 #endif /* SO_OOBINLINE */
247 cmdabort(int notused)
252 (void)fflush(stdout);
260 command(const char *fmt, ...)
267 fputs("---> ", stdout);
269 if (strncmp("PASS ", fmt, 5) == 0)
270 fputs("PASS XXXX", stdout);
271 else if (strncmp("ACCT ", fmt, 5) == 0)
272 fputs("ACCT XXXX", stdout);
277 (void)fflush(stdout);
280 warnx("No control connection for command.");
284 oldintr = signal(SIGINT, cmdabort);
286 vfprintf(cout, fmt, ap);
291 r = getreply(!strcmp(fmt, "QUIT"));
292 if (abrtflag && oldintr != SIG_IGN)
294 (void)signal(SIGINT, oldintr);
298 char reply_string[BUFSIZ]; /* first line of previous reply */
301 getreply(int expecteof)
303 char current_line[BUFSIZ]; /* last line of previous reply */
306 int originalcode = 0, continuation = 0;
309 char *cp, *pt = pasv;
311 oldintr = signal(SIGINT, cmdabort);
312 for (line = 0 ;; line++) {
315 while ((c = getc(cin)) != '\n') {
316 if (c == IAC) { /* handle telnet commands */
317 switch (c = getc(cin)) {
321 fprintf(cout, "%c%c%c", IAC, DONT, c);
327 fprintf(cout, "%c%c%c", IAC, WONT, c);
338 (void)signal(SIGINT, oldintr);
345 "421 Service not available, remote server has closed connection.");
346 (void)fflush(stdout);
351 if (c != '\r' && (verbose > 0 ||
352 (verbose > -1 && n == '5' && dig > 4))) {
354 (dig == 1 || (dig == 5 && verbose == 0)))
355 printf("%s:", hostname);
358 if (dig < 4 && isdigit((unsigned char)c))
359 code = code * 10 + (c - '0');
362 if (code == 227 || code == 228) {
363 /* result for PASV/LPSV */
366 } else if (code == 229) {
367 /* result for EPSV */
373 if (!(dig > 4 && isdigit((unsigned char)c)))
378 if (c != '\r' && c != ')' &&
379 pt < &pasv[sizeof(pasv)-1])
387 if (dig > 4 && c == '(')
391 if (dig == 4 && c == '-') {
398 if (cp < ¤t_line[sizeof(current_line) - 1])
401 if (verbose > 0 || (verbose > -1 && n == '5')) {
403 (void)fflush (stdout);
406 size_t len = cp - current_line;
408 if (len > sizeof(reply_string))
409 len = sizeof(reply_string);
411 (void)strncpy(reply_string, current_line, len);
412 reply_string[len] = '\0';
414 if (continuation && code != originalcode) {
415 if (originalcode == 0)
422 (void)signal(SIGINT, oldintr);
423 if (code == 421 || originalcode == 421)
425 if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
432 empty(fd_set *mask, int sec)
436 t.tv_sec = (long) sec;
438 return (select(32, mask, (fd_set *) 0, (fd_set *) 0, &t));
444 abortsend(int notused)
450 puts("\nsend aborted\nwaiting for remote to finish abort.");
451 (void)fflush(stdout);
452 longjmp(sendabort, 1);
456 sendrequest(const char *cmd, const char *local, const char *remote,
462 int (*closefunc)(FILE *);
463 sig_t oldinti, oldintr, oldintp;
464 volatile off_t hashbytes;
467 static size_t bufsize;
470 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */
485 oprogress = progress;
486 if (verbose && printnames) {
487 if (local && *local != '-')
488 printf("local: %s ", local);
490 printf("remote: %s\n", remote);
493 proxtrans(cmd, local, remote);
503 if (setjmp(sendabort)) {
512 (void)signal(SIGINT, oldintr);
514 (void)signal(SIGPIPE, oldintp);
516 (void)signal(SIGINFO, oldinti);
520 oldintr = signal(SIGINT, abortsend);
521 oldinti = signal(SIGINFO, psummary);
522 if (strcmp(local, "-") == 0) {
525 } else if (*local == '|') {
526 oldintp = signal(SIGPIPE, SIG_IGN);
527 fin = popen(local + 1, "r");
529 warn("%s", local + 1);
530 (void)signal(SIGINT, oldintr);
531 (void)signal(SIGPIPE, oldintp);
532 (void)signal(SIGINFO, oldinti);
539 fin = fopen(local, "r");
541 warn("local: %s", local);
542 (void)signal(SIGINT, oldintr);
543 (void)signal(SIGINFO, oldinti);
548 if (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) {
549 printf("%s: not a plain file.\n", local);
550 (void)signal(SIGINT, oldintr);
551 (void)signal(SIGINFO, oldinti);
556 filesize = st.st_size;
559 (void)signal(SIGINT, oldintr);
560 (void)signal(SIGINFO, oldinti);
562 (void)signal(SIGPIPE, oldintp);
564 if (closefunc != NULL)
568 if (fstat(fileno(fin), &st) < 0 || st.st_blksize < BUFSIZ)
569 st.st_blksize = BUFSIZ;
570 if (st.st_blksize > bufsize) {
573 buf = malloc((unsigned)st.st_blksize);
579 bufsize = st.st_blksize;
581 if (setjmp(sendabort))
585 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
591 rc = fseek(fin, (long) restart_point, SEEK_SET);
595 rc = lseek(fileno(fin), restart_point, SEEK_SET);
599 warn("local: %s", local);
600 if (closefunc != NULL)
604 if (command("REST %qd", (long long) restart_point) !=
606 if (closefunc != NULL)
613 if (command("%s %s", cmd, remote) != PRELIM) {
614 (void)signal(SIGINT, oldintr);
615 (void)signal(SIGINFO, oldinti);
617 (void)signal(SIGPIPE, oldintp);
618 if (closefunc != NULL)
623 if (command("%s", cmd) != PRELIM) {
624 (void)signal(SIGINT, oldintr);
625 (void)signal(SIGINFO, oldinti);
627 (void)signal(SIGPIPE, oldintp);
628 if (closefunc != NULL)
632 dout = dataconn(lmode);
636 oldintp = signal(SIGPIPE, SIG_IGN);
642 while ((c = read(fileno(fin), buf, bufsize)) > 0) {
644 for (bufp = buf; c > 0; c -= d, bufp += d)
645 if ((d = write(fileno(dout), bufp, c)) <= 0)
647 if (hash && (!progress || filesize < 0) ) {
648 while (bytes >= hashbytes) {
652 (void)fflush(stdout);
655 if (hash && (!progress || filesize < 0) && bytes > 0) {
659 (void)fflush(stdout);
662 warn("local: %s", local);
671 while ((c = getc(fin)) != EOF) {
673 while (hash && (!progress || filesize < 0) &&
674 (bytes >= hashbytes)) {
676 (void)fflush(stdout);
681 (void)putc('\r', dout);
686 #if 0 /* this violates RFC */
688 (void)putc('\0', dout);
693 if (hash && (!progress || filesize < 0)) {
694 if (bytes < hashbytes)
697 (void)fflush(stdout);
700 warn("local: %s", local);
709 if (closefunc != NULL)
713 (void)signal(SIGINT, oldintr);
714 (void)signal(SIGINFO, oldinti);
716 (void)signal(SIGPIPE, oldintp);
721 (void)signal(SIGINT, oldintr);
722 (void)signal(SIGINFO, oldinti);
724 (void)signal(SIGPIPE, oldintp);
737 if (closefunc != NULL && fin != NULL)
742 progress = oprogress;
749 abortrecv(int notused)
755 puts("\nreceive aborted\nwaiting for remote to finish abort.");
756 (void)fflush(stdout);
757 longjmp(recvabort, 1);
761 recvrequest(const char *cmd, const char *local, const char *remote,
762 const char *lmode, int printnames, int ignorespecial)
765 int (*closefunc)(FILE *);
766 sig_t oldinti, oldintr, oldintp;
768 volatile int is_retr, tcrflag, bare_lfs;
769 static size_t bufsize;
771 volatile off_t hashbytes;
774 struct timeval tval[2];
778 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */
792 direction = "received";
796 oprogress = progress;
797 opreserve = preserve;
798 is_retr = (strcmp(cmd, "RETR") == 0);
799 if (is_retr && verbose && printnames) {
800 if (local && (ignorespecial || *local != '-'))
801 printf("local: %s ", local);
803 printf("remote: %s\n", remote);
805 if (proxy && is_retr) {
806 proxtrans(cmd, local, remote);
812 tcrflag = !crflag && is_retr;
813 if (setjmp(recvabort)) {
822 (void)signal(SIGINT, oldintr);
824 (void)signal(SIGINFO, oldinti);
825 progress = oprogress;
826 preserve = opreserve;
830 oldintr = signal(SIGINT, abortrecv);
831 oldinti = signal(SIGINFO, psummary);
832 if (ignorespecial || (strcmp(local, "-") && *local != '|')) {
833 if (access(local, W_OK) < 0) {
834 char *dir = strrchr(local, '/');
836 if (errno != ENOENT && errno != EACCES) {
837 warn("local: %s", local);
838 (void)signal(SIGINT, oldintr);
839 (void)signal(SIGINFO, oldinti);
845 d = access(dir == local ? "/" : dir ? local : ".", W_OK);
849 warn("local: %s", local);
850 (void)signal(SIGINT, oldintr);
851 (void)signal(SIGINFO, oldinti);
855 if (!runique && errno == EACCES &&
856 chmod(local, 0600) < 0) {
857 warn("local: %s", local);
858 (void)signal(SIGINT, oldintr);
859 (void)signal(SIGINFO, oldinti);
863 if (runique && errno == EACCES &&
864 (local = gunique(local)) == NULL) {
865 (void)signal(SIGINT, oldintr);
866 (void)signal(SIGINFO, oldinti);
871 else if (runique && (local = gunique(local)) == NULL) {
872 (void)signal(SIGINT, oldintr);
873 (void)signal(SIGINFO, oldinti);
879 if (curtype != TYPE_A)
880 changetype(TYPE_A, 0);
884 filesize = remotesize(remote, 0);
887 (void)signal(SIGINT, oldintr);
888 (void)signal(SIGINFO, oldinti);
892 if (setjmp(recvabort))
894 if (is_retr && restart_point &&
895 command("REST %qd", (long long) restart_point) != CONTINUE)
898 if (command("%s %s", cmd, remote) != PRELIM) {
899 (void)signal(SIGINT, oldintr);
900 (void)signal(SIGINFO, oldinti);
904 if (command("%s", cmd) != PRELIM) {
905 (void)signal(SIGINT, oldintr);
906 (void)signal(SIGINFO, oldinti);
913 if (!ignorespecial && strcmp(local, "-") == 0) {
917 } else if (!ignorespecial && *local == '|') {
918 oldintp = signal(SIGPIPE, SIG_IGN);
919 fout = popen(local + 1, "w");
928 fout = fopen(local, lmode);
930 warn("local: %s", local);
935 if (fstat(fileno(fout), &st) < 0 || st.st_blksize < BUFSIZ)
936 st.st_blksize = BUFSIZ;
937 if (st.st_blksize > bufsize) {
940 buf = malloc((unsigned)st.st_blksize);
946 bufsize = st.st_blksize;
948 if (!S_ISREG(st.st_mode)) {
957 if (is_retr && restart_point &&
958 lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
959 warn("local: %s", local);
960 progress = oprogress;
961 preserve = opreserve;
962 if (closefunc != NULL)
967 while ((c = read(fileno(din), buf, bufsize)) > 0) {
968 if ((d = write(fileno(fout), buf, c)) != c)
971 if (hash && (!progress || filesize < 0)) {
972 while (bytes >= hashbytes) {
976 (void)fflush(stdout);
979 if (hash && (!progress || filesize < 0) && bytes > 0) {
983 (void)fflush(stdout);
992 warn("local: %s", local);
994 warnx("%s: short write", local);
999 if (is_retr && restart_point) {
1003 if (fseek(fout, 0L, SEEK_SET) < 0)
1005 n = (long)restart_point;
1006 for (i = 0; i++ < n;) {
1007 if ((ch = getc(fout)) == EOF)
1012 if (fseek(fout, 0L, SEEK_CUR) < 0) {
1014 warn("local: %s", local);
1015 progress = oprogress;
1016 preserve = opreserve;
1017 if (closefunc != NULL)
1022 while ((c = getc(din)) != EOF) {
1026 while (hash && (!progress || filesize < 0) &&
1027 (bytes >= hashbytes)) {
1029 (void)fflush(stdout);
1033 if ((c = getc(din)) != '\n' || tcrflag) {
1036 (void)putc('\r', fout);
1045 (void)putc(c, fout);
1052 "WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs);
1053 puts("File may not have transferred correctly.");
1055 if (hash && (!progress || filesize < 0)) {
1056 if (bytes < hashbytes)
1058 (void)putchar('\n');
1059 (void)fflush(stdout);
1067 warn("local: %s", local);
1071 progress = oprogress;
1072 preserve = opreserve;
1073 if (closefunc != NULL)
1075 (void)signal(SIGINT, oldintr);
1076 (void)signal(SIGINFO, oldinti);
1078 (void)signal(SIGPIPE, oldintp);
1081 if (bytes >= 0 && is_retr) {
1084 if (preserve && (closefunc == fclose)) {
1085 mtime = remotemodtime(remote, 0);
1087 (void)gettimeofday(&tval[0],
1088 (struct timezone *)0);
1089 tval[1].tv_sec = mtime;
1090 tval[1].tv_usec = 0;
1091 if (utimes(local, tval) == -1) {
1093 "Can't change modification time on %s to %s",
1094 local, asctime(localtime(&mtime)));
1103 /* abort using RFC959 recommended IP,SYNC sequence */
1105 progress = oprogress;
1106 preserve = opreserve;
1108 (void)signal(SIGPIPE, oldintp);
1109 (void)signal(SIGINT, SIG_IGN);
1112 (void)signal(SIGINT, oldintr);
1113 (void)signal(SIGINFO, oldinti);
1123 if (closefunc != NULL && fout != NULL)
1129 (void)signal(SIGINT, oldintr);
1130 (void)signal(SIGINFO, oldinti);
1134 * Need to start a listen on the data channel before we send the command,
1135 * otherwise the server's connect may fail.
1141 int result, len, tmpno = 0;
1150 if (myctladdr.su_family == AF_INET6
1151 && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr)
1152 || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) {
1153 warnx("use of scoped address can be troublesome");
1158 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */
1161 data_addr = myctladdr;
1162 data = socket(data_addr.su_family, SOCK_STREAM, 0);
1168 struct addrinfo *bindres;
1171 for (bindres = bindres0;
1173 bindres = bindres->ai_next)
1174 if (bindres->ai_family == data_addr.su_family)
1176 if (bindres == NULL)
1178 binderr = bind(data, bindres->ai_addr,
1179 bindres->ai_addrlen);
1186 if ((options & SO_DEBUG) &&
1187 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1189 warn("setsockopt (ignored)");
1190 switch (data_addr.su_family) {
1198 result = command(pasvcmd = "EPSV");
1200 if (code / 10 == 22 && code != 229) {
1201 puts("wrong server: EPSV return code must be 229");
1202 result = COMPLETE + 1;
1205 result = COMPLETE + 1;
1206 if (result != COMPLETE) {
1208 result = command(pasvcmd = "PASV");
1213 result = command(pasvcmd = "EPSV");
1214 if (code / 10 == 22 && code != 229) {
1215 puts("wrong server: EPSV return code must be 229");
1216 result = COMPLETE + 1;
1218 if (result != COMPLETE)
1219 result = command(pasvcmd = "LPSV");
1223 result = COMPLETE + 1;
1225 if (result != COMPLETE) {
1226 puts("Passive mode refused.");
1230 #define pack2(var, offset) \
1231 (((var[(offset) + 0] & 0xff) << 8) | ((var[(offset) + 1] & 0xff) << 0))
1232 #define pack4(var, offset) \
1233 (((var[(offset) + 0] & 0xff) << 24) | ((var[(offset) + 1] & 0xff) << 16) \
1234 | ((var[(offset) + 2] & 0xff) << 8) | ((var[(offset) + 3] & 0xff) << 0))
1236 * What we've got at this point is a string of comma
1237 * separated one-byte unsigned integer values.
1239 * The first four are the an IP address. The fifth is
1240 * the MSB of the port number, the sixth is the LSB.
1241 * From that we'll prepare a sockaddr_in.
1242 * In other case, the format is more complicated.
1244 if (strcmp(pasvcmd, "PASV") == 0) {
1245 if (code / 10 == 22 && code != 227) {
1246 puts("wrong server: return code must be 227");
1250 error = sscanf(pasv, "%d,%d,%d,%d,%d,%d",
1251 &h[0], &h[1], &h[2], &h[3],
1255 data_addr.su_sin.sin_addr.s_addr =
1259 } else if (strcmp(pasvcmd, "LPSV") == 0) {
1260 if (code / 10 == 22 && code != 228) {
1261 puts("wrong server: return code must be 228");
1265 switch (data_addr.su_family) {
1267 error = sscanf(pasv,
1268 "%d,%d,%d,%d,%d,%d,%d,%d,%d",
1270 &h[0], &h[1], &h[2], &h[3],
1271 &pal, &prt[0], &prt[1]);
1272 if (error == 9 && af == 4 && hal == 4 && pal == 2) {
1274 data_addr.su_sin.sin_addr.s_addr =
1281 error = sscanf(pasv,
1282 "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
1284 &h[0], &h[1], &h[2], &h[3],
1285 &h[4], &h[5], &h[6], &h[7],
1286 &h[8], &h[9], &h[10], &h[11],
1287 &h[12], &h[13], &h[14], &h[15],
1288 &pal, &prt[0], &prt[1]);
1289 if (error != 21 || af != 6 || hal != 16 || pal != 2) {
1297 p32 = (u_int32_t *)&data_addr.su_sin6.sin6_addr;
1298 p32[0] = htonl(pack4(h, 0));
1299 p32[1] = htonl(pack4(h, 4));
1300 p32[2] = htonl(pack4(h, 8));
1301 p32[3] = htonl(pack4(h, 12));
1308 } else if (strcmp(pasvcmd, "EPSV") == 0) {
1312 if (code / 10 == 22 && code != 229) {
1313 puts("wrong server: return code must be 229");
1317 error = sscanf(pasv, "%c%c%c%d%c",
1318 &delim[0], &delim[1], &delim[2],
1319 &prt[1], &delim[3]);
1324 if (delim[0] != delim[1] || delim[0] != delim[2]
1325 || delim[0] != delim[3]) {
1330 data_addr = hisctladdr;
1332 prt[0] = (prt[1] & 0xff00) >> 8;
1341 "Passive mode address scan failure. Shouldn't happen!");
1345 data_addr.su_port = htons(pack2(prt, 0));
1347 if (connect(data, (struct sockaddr *)&data_addr,
1348 data_addr.su_len) < 0) {
1353 if (data_addr.su_family == AF_INET)
1355 on = IPTOS_THROUGHPUT;
1356 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1358 warn("setsockopt TOS (ignored)");
1365 data_addr = myctladdr;
1367 data_addr.su_port = 0; /* let system pick one */
1370 data = socket(data_addr.su_family, SOCK_STREAM, 0);
1378 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
1380 warn("setsockopt (reuse address)");
1384 if (data_addr.su_family == AF_INET)
1387 ports = restricted_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
1388 if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE, (char *)&ports,
1390 warn("setsockopt PORTRANGE (ignored)");
1394 #ifdef IPV6_PORTRANGE
1395 if (data_addr.su_family == AF_INET6) {
1396 ports = restricted_data_ports ? IPV6_PORTRANGE_HIGH
1397 : IPV6_PORTRANGE_DEFAULT;
1398 if (setsockopt(data, IPPROTO_IPV6, IPV6_PORTRANGE,
1399 (char *)&ports, sizeof(ports)) < 0)
1400 warn("setsockopt PORTRANGE (ignored)");
1404 if (bind(data, (struct sockaddr *)&data_addr, data_addr.su_len) < 0) {
1408 if (options & SO_DEBUG &&
1409 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1411 warn("setsockopt (ignored)");
1412 len = sizeof(data_addr);
1413 if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
1414 warn("getsockname");
1417 if (listen(data, 1) < 0)
1420 char hname[INET6_ADDRSTRLEN];
1422 struct sockaddr_in data_addr4;
1423 union sockunion *daddr;
1426 if (data_addr.su_family == AF_INET6 &&
1427 IN6_IS_ADDR_V4MAPPED(&data_addr.su_sin6.sin6_addr)) {
1428 memset(&data_addr4, 0, sizeof(data_addr4));
1429 data_addr4.sin_len = sizeof(struct sockaddr_in);
1430 data_addr4.sin_family = AF_INET;
1431 data_addr4.sin_port = data_addr.su_port;
1432 memcpy((caddr_t)&data_addr4.sin_addr,
1433 (caddr_t)&data_addr.su_sin6.sin6_addr.s6_addr[12],
1434 sizeof(struct in_addr));
1435 daddr = (union sockunion *)&data_addr4;
1442 #define UC(b) (((int)b)&0xff)
1444 switch (daddr->su_family) {
1447 af = (daddr->su_family == AF_INET) ? 1 : 2;
1448 if (daddr->su_family == AF_INET6)
1449 daddr->su_sin6.sin6_scope_id = 0;
1450 if (getnameinfo((struct sockaddr *)daddr,
1451 daddr->su_len, hname,
1452 sizeof(hname) - 1, NULL, 0,
1456 result = command("EPRT |%d|%s|%d|",
1457 af, hname, ntohs(daddr->su_port));
1462 result = COMPLETE + 1;
1465 if (result == COMPLETE)
1468 p = (char *)&daddr->su_port;
1469 switch (daddr->su_family) {
1471 a = (char *)&daddr->su_sin.sin_addr;
1472 result = command("PORT %d,%d,%d,%d,%d,%d",
1473 UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
1474 UC(p[0]), UC(p[1]));
1478 a = (char *)&daddr->su_sin6.sin6_addr;
1480 "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
1482 UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
1483 UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
1484 UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
1485 UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
1486 2, UC(p[0]), UC(p[1]));
1490 result = COMPLETE + 1; /* xxx */
1494 if (result == ERROR && sendport == -1) {
1499 return (result != COMPLETE);
1504 if (data_addr.su_family == AF_INET)
1506 on = IPTOS_THROUGHPUT;
1507 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1508 warn("setsockopt TOS (ignored)");
1513 (void)close(data), data = -1;
1520 dataconn(const char *lmode)
1522 union sockunion from;
1523 int s, fromlen, tos;
1525 fromlen = myctladdr.su_len;
1528 return (fdopen(data, lmode));
1530 s = accept(data, (struct sockaddr *) &from, &fromlen);
1533 (void)close(data), data = -1;
1539 if (data_addr.su_family == AF_INET)
1541 tos = IPTOS_THROUGHPUT;
1542 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
1543 warn("setsockopt TOS (ignored)");
1546 return (fdopen(data, lmode));
1550 psummary(int notused)
1558 psabort(int notused)
1569 static struct comvars {
1571 char name[MAXHOSTNAMELEN];
1572 union sockunion mctl;
1573 union sockunion hctl;
1586 char mi[MAXPATHLEN];
1587 char mo[MAXPATHLEN];
1588 } proxstruct, tmpstruct;
1589 struct comvars *ip, *op;
1592 oldintr = signal(SIGINT, psabort);
1606 ip->connect = connected;
1607 connected = op->connect;
1609 (void)strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1610 ip->name[sizeof(ip->name) - 1] = '\0';
1613 hostname = op->name;
1614 ip->hctl = hisctladdr;
1615 hisctladdr = op->hctl;
1616 ip->mctl = myctladdr;
1617 myctladdr = op->mctl;
1624 ip->curtpe = curtype;
1625 curtype = op->curtpe;
1628 ip->sunqe = sunique;
1629 sunique = op->sunqe;
1630 ip->runqe = runique;
1631 runique = op->runqe;
1636 (void)strncpy(ip->nti, ntin, sizeof(ip->nti) - 1);
1637 (ip->nti)[sizeof(ip->nti) - 1] = '\0';
1638 (void)strcpy(ntin, op->nti);
1639 (void)strncpy(ip->nto, ntout, sizeof(ip->nto) - 1);
1640 (ip->nto)[sizeof(ip->nto) - 1] = '\0';
1641 (void)strcpy(ntout, op->nto);
1642 ip->mapflg = mapflag;
1643 mapflag = op->mapflg;
1644 (void)strncpy(ip->mi, mapin, sizeof(ip->mi) - 1);
1645 (ip->mi)[sizeof(ip->mi) - 1] = '\0';
1646 (void)strcpy(mapin, op->mi);
1647 (void)strncpy(ip->mo, mapout, sizeof(ip->mo) - 1);
1648 (ip->mo)[sizeof(ip->mo) - 1] = '\0';
1649 (void)strcpy(mapout, op->mo);
1650 (void)signal(SIGINT, oldintr);
1658 abortpt(int notused)
1663 (void)fflush(stdout);
1667 longjmp(ptabort, 1);
1671 proxtrans(const char *cmd, const char *local, const char *remote)
1674 int prox_type, nfnd;
1675 volatile int secndflag;
1679 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */
1686 if (strcmp(cmd, "RETR"))
1689 cmd2 = runique ? "STOU" : "STOR";
1690 if ((prox_type = type) == 0) {
1691 if (unix_server && unix_proxy)
1696 if (curtype != prox_type)
1697 changetype(prox_type, 1);
1698 if (try_epsv && command("EPSV") != COMPLETE)
1700 if (!try_epsv && command("PASV") != COMPLETE) {
1701 puts("proxy server does not support third party transfers.");
1706 puts("No primary connection.");
1711 if (curtype != prox_type)
1712 changetype(prox_type, 1);
1713 if (command("PORT %s", pasv) != COMPLETE) {
1717 if (setjmp(ptabort))
1719 oldintr = signal(SIGINT, abortpt);
1720 if (command("%s %s", cmd, remote) != PRELIM) {
1721 (void)signal(SIGINT, oldintr);
1728 if (command("%s %s", cmd2, local) != PRELIM)
1734 (void)signal(SIGINT, oldintr);
1737 printf("local: %s remote: %s\n", local, remote);
1740 (void)signal(SIGINT, SIG_IGN);
1742 if (strcmp(cmd, "RETR") && !proxy)
1744 else if (!strcmp(cmd, "RETR") && proxy)
1746 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1747 if (command("%s %s", cmd2, local) != PRELIM) {
1750 abort_remote((FILE *) NULL);
1755 (void)signal(SIGINT, oldintr);
1759 abort_remote((FILE *) NULL);
1761 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1762 if (command("%s %s", cmd2, local) != PRELIM) {
1765 abort_remote((FILE *) NULL);
1769 (void)signal(SIGINT, oldintr);
1774 abort_remote((FILE *) NULL);
1778 FD_SET(fileno(cin), &mask);
1779 if ((nfnd = empty(&mask, 10)) <= 0) {
1795 (void)signal(SIGINT, oldintr);
1799 reset(int argc, char **argv)
1806 FD_SET(fileno(cin), &mask);
1807 if ((nfnd = empty(&mask, 0)) < 0) {
1819 gunique(const char *local)
1821 static char new[MAXPATHLEN];
1822 char *cp = strrchr(local, '/');
1828 d = access(cp == local ? "/" : cp ? local : ".", W_OK);
1832 warn("local: %s", local);
1833 return ((char *) 0);
1835 (void)strcpy(new, local);
1836 cp = new + strlen(new);
1839 if (++count == 100) {
1840 puts("runique: can't find unique file name.");
1841 return ((char *) 0);
1849 if ((d = access(new, F_OK)) < 0)
1853 else if (*(cp - 2) == '.')
1856 *(cp - 2) = *(cp - 2) + 1;
1864 abort_remote(FILE *din)
1871 warnx("Lost control connection for abort.");
1878 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
1879 * after urgent byte rather than before as is protocol now
1881 sprintf(buf, "%c%c%c", IAC, IP, IAC);
1882 if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
1884 fprintf(cout, "%cABOR\r\n", DM);
1887 FD_SET(fileno(cin), &mask);
1889 FD_SET(fileno(din), &mask);
1891 if ((nfnd = empty(&mask, 10)) <= 0) {
1899 if (din && FD_ISSET(fileno(din), &mask)) {
1900 while (read(fileno(din), buf, BUFSIZ) > 0)
1903 if (getreply(0) == ERROR && code == 552) {
1904 /* 552 needed for nic style abort */
1911 ai_unmapped(struct addrinfo *ai)
1913 struct sockaddr_in6 *sin6;
1914 struct sockaddr_in sin;
1916 if (ai->ai_family != AF_INET6)
1918 if (ai->ai_addrlen != sizeof(struct sockaddr_in6) ||
1919 sizeof(sin) > ai->ai_addrlen)
1921 sin6 = (struct sockaddr_in6 *)ai->ai_addr;
1922 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
1925 memset(&sin, 0, sizeof(sin));
1926 sin.sin_family = AF_INET;
1927 sin.sin_len = sizeof(struct sockaddr_in);
1928 memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
1929 sizeof(sin.sin_addr));
1930 sin.sin_port = sin6->sin6_port;
1932 ai->ai_family = AF_INET;
1933 memcpy(ai->ai_addr, &sin, sin.sin_len);
1934 ai->ai_addrlen = sin.sin_len;