]>
Commit | Line | Data |
---|---|---|
37a2e2e3 | 1 | diff -uNr netkit-ftp-0.17/CVS/Entries netkit-ftp/CVS/Entries |
2 | diff -uNr netkit-ftp-0.17/ChangeLog netkit-ftp/ChangeLog | |
3 | --- netkit-ftp-0.17/ChangeLog Sun Jul 23 04:38:08 2000 | |
4 | +++ netkit-ftp/ChangeLog Tue Nov 28 03:50:10 2000 | |
5 | @@ -1,3 +1,6 @@ | |
6 | +28-Nov-2000: | |
7 | + IPv6 support. (Hiroyuki YAMAMORI <h-yamamo@db3.so-net.ne.jp>) | |
8 | + | |
9 | 8-Jul-2000: | |
10 | Fix misused printf-function call (not %n-exploitable though). | |
11 | ||
12 | diff -uNr netkit-ftp-0.17/configure netkit-ftp/configure | |
13 | --- netkit-ftp-0.17/configure Sat Jul 29 21:00:28 2000 | |
14 | +++ netkit-ftp/configure Sat Jan 27 06:14:54 2001 | |
15 | @@ -24,6 +24,7 @@ | |
16 | --binmode=mode Mode for binaries [755] | |
17 | --manmode=mode Mode for manual pages [644] | |
18 | --with-c-compiler=cc Program for compiling C source [guessed] | |
19 | + --enable-ipv6 Enable IPv6 support | |
20 | EOF | |
21 | exit 0;; | |
22 | --verbose) ;; | |
23 | @@ -39,6 +40,11 @@ | |
24 | --manmode=*) MANMODE=`echo $1 | sed 's/^[^=]*=//'` ;; | |
25 | --with-c-compiler=*) CC=`echo $1 | sed 's/^[^=]*=//'` ;; | |
26 | --without-readline|--disable-readline) WITHOUT_READLINE=1;; | |
27 | + | |
28 | + --disable-ipv6) ENABLE_IPV6=no;; | |
29 | + --enable-ipv6=*) ENABLE_IPV6=`echo $1 | sed 's/^[^=]*=//'`;; | |
30 | + --enable-ipv6) ENABLE_IPV6=yes;; | |
31 | + | |
32 | *) echo "Unrecognized option: $1"; exit 1;; | |
33 | esac | |
34 | shift | |
35 | @@ -142,6 +148,42 @@ | |
36 | ||
37 | LDFLAGS= | |
38 | LIBS= | |
39 | + | |
40 | +rm -f __conftest* | |
41 | + | |
42 | +################################################## | |
43 | +## Enable IPv6 | |
44 | +echo -n "Whether to enable IPv6 support... " | |
45 | +if [ x"$ENABLE_IPV6" = x"yes" ]; then | |
46 | + echo yes | |
47 | + CFLAGS="$CFLAGS -DINET6" | |
48 | +else | |
49 | + echo no | |
50 | +fi | |
51 | + | |
52 | +rm -f __conftest* | |
53 | + | |
54 | +## Search IPv6 Library / Headers | |
55 | +if [ x"$ENABLE_IPV6" = x"yes" ]; then | |
56 | + echo -n "Search for IPv6 library... " | |
57 | + inet6libdirs="/usr/local/v6/lib /usr/local/lib /usr /usr/inet6/lib" | |
58 | + inet6libs="inet6" | |
59 | + inet6found=no | |
60 | + for inet6libdir in $inet6libdirs; do | |
61 | + for inet6lib in $inet6libs; do | |
62 | + if [ -d $inet6libdir ] && [ -f $inet6libdir/lib$inet6lib.a ]; then | |
63 | + inet6found=yes | |
64 | + break 2 | |
65 | + fi | |
66 | + done | |
67 | + done | |
68 | + if [ x"$inet6found" = x"yes" ]; then | |
69 | + echo "$inet6libdir/lib$inet6lib.a" | |
70 | + LIBS="$LIBS -L$inet6libdir -l$inet6lib" | |
71 | + else | |
72 | + echo "not found" | |
73 | + fi | |
74 | +fi | |
75 | ||
76 | rm -f __conftest* | |
77 | ||
78 | diff -uNr netkit-ftp-0.17/ftp/CVS/Entries netkit-ftp/ftp/CVS/Entries | |
79 | --- netkit-ftp-0.17/ftp/CVS/Entries Thu Jan 1 02:00:00 1970 | |
80 | +++ netkit-ftp/ftp/CVS/Entries Mon Feb 19 06:50:49 2001 | |
81 | @@ -0,0 +1,16 @@ | |
82 | +/.cvsignore/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
83 | +/Makefile/1.4/Sat Jan 27 05:57:08 2001// | |
84 | +/cmds.c/1.3/Fri Jan 12 21:36:27 2001// | |
85 | +/cmds.h/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
86 | +/cmdtab.c/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
87 | +/domacro.c/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
88 | +/ftp.1/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
89 | +/ftp.c/1.11/Sun Feb 11 12:26:59 2001// | |
90 | +/ftp_var.h/1.3/Fri Jan 12 21:36:27 2001// | |
91 | +/glob.c/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
92 | +/glob.h/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
93 | +/main.c/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
94 | +/netrc.5/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
95 | +/pathnames.h/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
96 | +/ruserpass.c/1.1.1.1/Fri Nov 3 19:18:15 2000// | |
97 | +D | |
98 | diff -uNr netkit-ftp-0.17/ftp/CVS/Repository netkit-ftp/ftp/CVS/Repository | |
99 | --- netkit-ftp-0.17/ftp/CVS/Repository Thu Jan 1 02:00:00 1970 | |
100 | +++ netkit-ftp/ftp/CVS/Repository Mon Feb 19 06:50:49 2001 | |
101 | @@ -0,0 +1 @@ | |
102 | +usagi/src/netkit-ftp/ftp | |
103 | diff -uNr netkit-ftp-0.17/ftp/CVS/Root netkit-ftp/ftp/CVS/Root | |
104 | --- netkit-ftp-0.17/ftp/CVS/Root Thu Jan 1 02:00:00 1970 | |
105 | +++ netkit-ftp/ftp/CVS/Root Mon Feb 19 06:50:49 2001 | |
106 | @@ -0,0 +1 @@ | |
107 | +:pserver:anoncvs@anoncvs.linux-ipv6.org:/cvsroot/usagi | |
108 | diff -uNr netkit-ftp-0.17/ftp/Makefile netkit-ftp/ftp/Makefile | |
109 | --- netkit-ftp-0.17/ftp/Makefile Sun Aug 1 09:00:12 1999 | |
110 | +++ netkit-ftp/ftp/Makefile Sat Jan 27 07:57:08 2001 | |
111 | @@ -16,10 +16,13 @@ | |
112 | cmds.o glob.o: glob.h | |
113 | ||
114 | install: ftp | |
115 | + install -d $(INSTALLROOT)$(BINDIR) | |
116 | install -s -m$(BINMODE) ftp $(INSTALLROOT)$(BINDIR) | |
117 | ln -sf ftp $(INSTALLROOT)$(BINDIR)/pftp | |
118 | + install -d $(INSTALLROOT)$(MANDIR)/man1 | |
119 | install -m$(MANMODE) ftp.1 $(INSTALLROOT)$(MANDIR)/man1 | |
120 | ln -sf ftp.1 $(INSTALLROOT)$(MANDIR)/man1/pftp.1 | |
121 | + install -d $(INSTALLROOT)$(MANDIR)/man5 | |
122 | install -m$(MANMODE) netrc.5 $(INSTALLROOT)$(MANDIR)/man5 | |
123 | ||
124 | clean: | |
125 | diff -uNr netkit-ftp-0.17/ftp/cmds.c netkit-ftp/ftp/cmds.c | |
126 | --- netkit-ftp-0.17/ftp/cmds.c Sun Jul 23 04:36:59 2000 | |
127 | +++ netkit-ftp/ftp/cmds.c Fri Jan 12 23:36:27 2001 | |
128 | @@ -1,3 +1,5 @@ | |
129 | +/* $USAGI$ */ | |
130 | + | |
131 | /* | |
132 | * Copyright (c) 1985, 1989 Regents of the University of California. | |
133 | * All rights reserved. | |
37a2e2e3 | 134 | @@ -190,7 +192,7 @@ |
135 | setpeer(int argc, char *argv[]) | |
136 | { | |
137 | char *host; | |
138 | - unsigned short port; | |
139 | + char *port; | |
140 | ||
141 | if (connected) { | |
142 | printf("Already connected to %s, use close first.\n", | |
143 | @@ -205,22 +207,17 @@ | |
144 | code = -1; | |
145 | return; | |
146 | } | |
147 | - port = ftp_port; | |
148 | + port = NULL; | |
149 | if (argc > 2) { | |
150 | - port = atoi(argv[2]); | |
151 | - if (port < 1) { | |
152 | - printf("%s: bad port number-- %s\n", argv[1], argv[2]); | |
153 | - printf ("usage: %s host-name [port]\n", argv[0]); | |
154 | - code = -1; | |
155 | - return; | |
156 | - } | |
157 | - port = htons(port); | |
158 | + port = argv[2]; | |
159 | } | |
160 | host = hookup(argv[1], port); | |
161 | if (host) { | |
162 | int overbose; | |
163 | ||
164 | connected = 1; | |
165 | + try_epsv = 1; | |
166 | + try_eprt = 1; | |
167 | /* | |
168 | * Set up defaults for FTP. | |
169 | */ | |
37a2e2e3 | 170 | diff -uNr netkit-ftp-0.17/ftp/ftp.c netkit-ftp/ftp/ftp.c |
171 | --- netkit-ftp-0.17/ftp/ftp.c Mon Dec 13 22:33:20 1999 | |
172 | +++ netkit-ftp/ftp/ftp.c Sun Feb 11 14:26:59 2001 | |
173 | @@ -1,3 +1,34 @@ | |
174 | +/* $USAGI$ */ | |
175 | + | |
176 | +/* | |
177 | + * Copyright (C) 1997 and 1998 WIDE Project. | |
178 | + * All rights reserved. | |
179 | + * | |
180 | + * Redistribution and use in source and binary forms, with or without | |
181 | + * modification, are permitted provided that the following conditions | |
182 | + * are met: | |
183 | + * 1. Redistributions of source code must retain the above copyright | |
184 | + * notice, this list of conditions and the following disclaimer. | |
185 | + * 2. Redistributions in binary form must reproduce the above copyright | |
186 | + * notice, this list of conditions and the following disclaimer in the | |
187 | + * documentation and/or other materials provided with the distribution. | |
188 | + * 3. Neither the name of the project nor the names of its contributors | |
189 | + * may be used to endorse or promote products derived from this software | |
190 | + * without specific prior written permission. | |
191 | + * | |
192 | + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
193 | + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
194 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
195 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
196 | + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
197 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
198 | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
199 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
200 | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
201 | + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
202 | + * SUCH DAMAGE. | |
203 | + */ | |
204 | + | |
205 | /* | |
206 | * Copyright (c) 1985, 1989 Regents of the University of California. | |
207 | * All rights reserved. | |
37a2e2e3 | 208 | @@ -63,14 +94,38 @@ |
209 | #include "ftp_var.h" | |
210 | #include "cmds.h" | |
211 | ||
212 | +#ifdef _USAGI | |
213 | +#include "version.h" | |
214 | +#else | |
215 | #include "../version.h" | |
216 | +#endif | |
217 | + | |
218 | +union sockunion { | |
219 | + struct sockinet { | |
220 | + u_short si_family; | |
221 | + u_short si_port; | |
222 | + } su_si; | |
223 | + struct sockaddr su_sa; | |
224 | + struct sockaddr_in su_sin; | |
225 | +#ifdef INET6 | |
226 | + struct sockaddr_in6 su_sin6; | |
227 | +#endif | |
228 | +}; | |
229 | +#define su_family su_sa.sa_family | |
230 | +#define su_port su_si.si_port | |
231 | + | |
232 | +#ifdef INET6 | |
233 | +#define ex_af2prot(a) (a == AF_INET ? 1 : (a == AF_INET6 ? 2 : 0)) | |
234 | +#else | |
235 | +#define ex_af2prot(a) (a == AF_INET ? 1 : 0) | |
236 | +#endif | |
237 | ||
238 | int data = -1; | |
239 | off_t restart_point = 0; | |
240 | ||
241 | -static struct sockaddr_in hisctladdr; | |
242 | -static struct sockaddr_in data_addr; | |
243 | -static struct sockaddr_in myctladdr; | |
244 | +static union sockunion hisctladdr; | |
245 | +static union sockunion data_addr; | |
246 | +static union sockunion myctladdr; | |
247 | static int ptflag = 0; | |
248 | static sigjmp_buf recvabort; | |
249 | static sigjmp_buf sendabort; | |
250 | @@ -96,79 +151,119 @@ | |
251 | static FILE *dataconn(const char *); | |
252 | ||
253 | char * | |
254 | -hookup(char *host, int port) | |
255 | +hookup(const char *host, const char *port) | |
256 | { | |
257 | - register struct hostent *hp = 0; | |
258 | - int s, tos; | |
259 | + int s, tos, error; | |
260 | socklen_t len; | |
261 | static char hostnamebuf[256]; | |
262 | - | |
263 | + struct addrinfo hints, *res, *res0; | |
264 | + char hbuf[MAXHOSTNAMELEN], pbuf[NI_MAXSERV]; | |
265 | + char *cause = "ftp: unknown"; | |
266 | + | |
267 | + if (port) { | |
268 | + strncpy(pbuf, port, sizeof(pbuf) - 1); | |
269 | + pbuf[sizeof(pbuf) - 1] = '\0'; | |
270 | + } else { | |
271 | + sprintf(pbuf, "%d", ntohs(ftp_port)); | |
272 | + } | |
273 | memset(&hisctladdr, 0, sizeof(hisctladdr)); | |
274 | - if (inet_aton(host, &hisctladdr.sin_addr)) { | |
275 | - hisctladdr.sin_family = AF_INET; | |
276 | - strncpy(hostnamebuf, host, sizeof(hostnamebuf)); | |
277 | - hostnamebuf[sizeof(hostnamebuf)-1]=0; | |
278 | - } | |
279 | - else { | |
280 | - hp = gethostbyname(host); | |
281 | - if (hp == NULL) { | |
282 | - fprintf(stderr, "ftp: %s: ", host); | |
283 | - herror((char *)NULL); | |
284 | - code = -1; | |
285 | - return((char *) 0); | |
286 | + memset(&hints, 0, sizeof(hints)); | |
287 | + hints.ai_flags = AI_CANONNAME; | |
288 | + hints.ai_socktype = SOCK_STREAM; | |
289 | + error = getaddrinfo(host, pbuf, &hints, &res0); | |
290 | + if (error) { | |
291 | + if (port) { | |
292 | + strcpy(hbuf, " "); | |
293 | + } else { | |
294 | + hbuf[0] = '\0'; | |
295 | + pbuf[0] = '\0'; | |
296 | } | |
297 | - hisctladdr.sin_family = hp->h_addrtype; | |
298 | - if (hp->h_length > (int)sizeof(hisctladdr.sin_addr)) { | |
299 | - hp->h_length = sizeof(hisctladdr.sin_addr); | |
300 | - } | |
301 | - memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], hp->h_length); | |
302 | - (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); | |
303 | - hostnamebuf[sizeof(hostnamebuf)-1] = 0; | |
304 | - } | |
305 | - hostname = hostnamebuf; | |
306 | - s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); | |
307 | - if (s < 0) { | |
308 | - perror("ftp: socket"); | |
309 | + fprintf(stderr, "ftp: %s%s%s: %s\n", host, hbuf, pbuf, | |
310 | + gai_strerror(error)); | |
311 | code = -1; | |
312 | return (0); | |
313 | } | |
314 | - hisctladdr.sin_port = port; | |
315 | - while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { | |
316 | - if (hp && hp->h_addr_list[1]) { | |
317 | - int oerrno = errno; | |
318 | - | |
319 | - fprintf(stderr, "ftp: connect to address %s: ", | |
320 | - inet_ntoa(hisctladdr.sin_addr)); | |
321 | - errno = oerrno; | |
322 | - perror((char *) 0); | |
323 | - hp->h_addr_list++; | |
324 | - memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], | |
325 | - hp->h_length); | |
326 | - fprintf(stdout, "Trying %s...\n", | |
327 | - inet_ntoa(hisctladdr.sin_addr)); | |
328 | - (void) close(s); | |
329 | - s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); | |
330 | - if (s < 0) { | |
331 | - perror("ftp: socket"); | |
332 | - code = -1; | |
333 | - return (0); | |
334 | + | |
335 | + if (res0->ai_canonname) { | |
336 | + struct addrinfo h, *a; | |
337 | + memset(&h, 0, sizeof(h)); | |
338 | + h.ai_family = PF_UNSPEC; | |
339 | + h.ai_socktype = SOCK_STREAM; | |
340 | + h.ai_flags = AI_NUMERICHOST; | |
341 | + if (!getaddrinfo(res0->ai_canonname, NULL, &h, &a)) { | |
342 | + strncpy(hostnamebuf, res0->ai_canonname, sizeof(hostnamebuf)); | |
343 | + freeaddrinfo(a); | |
344 | + } else | |
345 | + strncpy(hostnamebuf, host, sizeof(hostnamebuf)); | |
346 | + } | |
347 | + else | |
348 | + strncpy(hostnamebuf, host, sizeof(hostnamebuf)); | |
349 | + hostnamebuf[sizeof(hostnamebuf) - 1] = '\0'; | |
350 | + hostname = hostnamebuf; | |
351 | + | |
352 | + s = -1; | |
353 | + for (res = res0; res; res = res->ai_next) { | |
354 | + if (!ex_af2prot(res->ai_family)) { | |
355 | + cause = "ftp: mismatch address family"; | |
356 | + errno = EPROTONOSUPPORT; | |
357 | + continue; | |
358 | + } | |
359 | + if ((size_t)res->ai_addrlen > sizeof(hisctladdr)) { | |
360 | + cause = "ftp: mismatch struct sockaddr size"; | |
361 | + errno = EPROTO; | |
362 | + continue; | |
363 | + } | |
364 | + if (getnameinfo(res->ai_addr, res->ai_addrlen, | |
365 | + hbuf, sizeof(hbuf), NULL, 0, | |
366 | + NI_NUMERICHOST)) | |
367 | + strcpy(hbuf, "???"); | |
368 | + if (res0->ai_next) /* if we have multiple possibilities */ | |
369 | + fprintf(stdout, "Trying %s...\n", hbuf); | |
370 | + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | |
371 | + if (s < 0) { | |
372 | + cause = "ftp: socket"; | |
373 | + continue; | |
374 | + } | |
375 | + while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0 | |
376 | + && errno == EINTR) { | |
377 | + ; | |
378 | + } | |
379 | + if (error) { | |
380 | + /* this "if" clause is to prevent print warning twice */ | |
381 | + if (res->ai_next) { | |
382 | + fprintf(stderr, | |
383 | + "ftp: connect to address %s", hbuf); | |
384 | + perror(""); | |
385 | } | |
386 | + cause = "ftp: connect"; | |
387 | + close(s); | |
388 | + s = -1; | |
389 | continue; | |
390 | } | |
391 | - perror("ftp: connect"); | |
392 | + /* finally we got one */ | |
393 | + break; | |
394 | + } | |
395 | + if (s < 0) { | |
396 | + perror(cause); | |
397 | code = -1; | |
398 | - goto bad; | |
399 | + freeaddrinfo(res0); | |
400 | + return NULL; | |
401 | } | |
402 | - len = sizeof (myctladdr); | |
403 | + len = res->ai_addrlen; | |
404 | + memcpy(&hisctladdr, res->ai_addr, len); | |
405 | + freeaddrinfo(res0); | |
406 | if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { | |
407 | perror("ftp: getsockname"); | |
408 | code = -1; | |
409 | goto bad; | |
410 | } | |
411 | #ifdef IP_TOS | |
412 | + if (hisctladdr.su_family == AF_INET) | |
413 | + { | |
414 | tos = IPTOS_LOWDELAY; | |
415 | if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) | |
416 | perror("ftp: setsockopt TOS (ignored)"); | |
417 | + } | |
418 | #endif | |
419 | cin = fdopen(s, "r"); | |
420 | cout = fdopen(s, "w"); | |
421 | @@ -182,7 +277,7 @@ | |
422 | goto bad; | |
423 | } | |
424 | if (verbose) | |
425 | - printf("Connected to %s.\n", hostname); | |
426 | + printf("Connected to %s (%s).\n", hostname, hbuf); | |
427 | if (getreply(0) > 2) { /* read startup message from server */ | |
428 | if (cin) | |
429 | (void) fclose(cin); | |
430 | @@ -392,8 +487,10 @@ | |
431 | } | |
432 | if (dig < 4 && isdigit(c)) | |
433 | code = code * 10 + (c - '0'); | |
434 | - if (!pflag && code == 227) | |
435 | + if (!pflag && (code == 227 || code == 228)) | |
436 | pflag = 1; | |
437 | + else if (!pflag && code == 229) | |
438 | + pflag = 100; | |
439 | if (dig > 4 && pflag == 1 && isdigit(c)) | |
440 | pflag = 2; | |
441 | if (pflag == 2) { | |
442 | @@ -405,6 +502,8 @@ | |
443 | pflag = 3; | |
444 | } | |
445 | } | |
446 | + if (pflag == 100 && c == '(') | |
447 | + pflag = 2; | |
448 | if (dig == 4 && c == '-') { | |
449 | if (continuation) | |
450 | code = 0; | |
451 | @@ -1083,15 +1182,25 @@ | |
452 | static int | |
453 | initconn(void) | |
454 | { | |
455 | - register char *p, *a; | |
456 | + u_char *p, *a; | |
457 | int result, tmpno = 0; | |
458 | socklen_t len; | |
459 | int on = 1; | |
460 | - int tos; | |
461 | - u_long a1,a2,a3,a4,p1,p2; | |
462 | - | |
463 | + int tos, error = 0; | |
464 | + u_int ad[16], po[2], af, alen, plen; | |
465 | + char *pasvcmd = NULL; | |
466 | + char hbuf[MAXHOSTNAMELEN], pbuf[NI_MAXSERV]; | |
467 | + | |
468 | +#ifdef INET6 | |
469 | + if (myctladdr.su_family == AF_INET6 | |
470 | + && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr) | |
471 | + || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) { | |
472 | + fprintf(stderr, "use of scoped address can be troublesome\n"); | |
473 | + } | |
474 | +#endif | |
475 | if (passivemode) { | |
476 | - data = socket(AF_INET, SOCK_STREAM, 0); | |
477 | + data_addr = hisctladdr; | |
478 | + data = socket(data_addr.su_family, SOCK_STREAM, 0); | |
479 | if (data < 0) { | |
480 | perror("ftp: socket"); | |
481 | return(1); | |
482 | @@ -1100,52 +1209,201 @@ | |
483 | setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, | |
484 | sizeof (on)) < 0) | |
485 | perror("ftp: setsockopt (ignored)"); | |
486 | - if (command("PASV") != COMPLETE) { | |
487 | + switch (data_addr.su_family) { | |
488 | + case AF_INET: | |
489 | +#if 0 | |
490 | + if (try_epsv) { | |
491 | + result = command(pasvcmd = "EPSV 1"); | |
492 | + if (code / 10 == 22 && code != 229) { | |
493 | + fprintf(stderr, | |
494 | + "wrong server: return code must be 229\n"); | |
495 | + result = COMPLETE + 1; | |
496 | + } | |
497 | + } else { | |
498 | +#endif | |
499 | + result = COMPLETE + 1; | |
500 | + | |
501 | + if (result != COMPLETE) { | |
502 | + try_epsv = 0; | |
503 | + result = command(pasvcmd = "PASV"); | |
504 | + } | |
505 | + break; | |
506 | +#ifdef INET6 | |
507 | + case AF_INET6: | |
508 | + if (try_epsv) { | |
509 | + result = command(pasvcmd = "EPSV 2"); | |
510 | + if (code / 10 == 22 && code != 229) { | |
511 | + fprintf(stderr, | |
512 | + "wrong server: return code must be 229\n"); | |
513 | + result = COMPLETE + 1; | |
514 | + } | |
515 | + } else { | |
516 | + result = COMPLETE + 1; | |
517 | + } | |
518 | + if (result != COMPLETE) { | |
519 | + try_epsv = 0; | |
520 | + result = command(pasvcmd = "LPSV"); | |
521 | + } | |
522 | + break; | |
523 | +#endif | |
524 | + default: | |
525 | + result = COMPLETE + 1; | |
526 | + break; | |
527 | + } | |
528 | + if (result != COMPLETE) { | |
529 | printf("Passive mode refused.\n"); | |
530 | - return(1); | |
531 | + goto bad; | |
532 | } | |
533 | ||
534 | +#define pack2(var) \ | |
535 | + (((var[0] & 0xff) << 8) | ((var[1] & 0xff) << 0)) | |
536 | +#define pack4(var) \ | |
537 | + ((((var)[0] & 0xff) << 24) | (((var)[1] & 0xff) << 16) | \ | |
538 | + (((var)[2] & 0xff) << 8) | (((var)[3] & 0xff) << 0)) | |
539 | + | |
540 | /* | |
541 | * What we've got at this point is a string of comma separated | |
542 | * one-byte unsigned integer values, separated by commas. | |
543 | - * The first four are the an IP address. The fifth is the MSB | |
544 | - * of the port number, the sixth is the LSB. From that we'll | |
545 | - * prepare a sockaddr_in. | |
546 | */ | |
547 | - | |
548 | - if (sscanf(pasv,"%ld,%ld,%ld,%ld,%ld,%ld", | |
549 | - &a1,&a2,&a3,&a4,&p1,&p2) | |
550 | - != 6) | |
551 | - { | |
552 | - printf("Passive mode address scan failure. Shouldn't happen!\n"); | |
553 | - return(1); | |
554 | + error = 0; | |
555 | + if (strcmp(pasvcmd, "PASV") == 0) { | |
556 | + if (data_addr.su_family != AF_INET) { | |
557 | + error = 2; | |
558 | + goto psv_done; | |
559 | + } | |
560 | + if (code / 10 == 22 && code != 227) { | |
561 | + error = 227; | |
562 | + goto psv_done; | |
563 | + } | |
564 | + if (sscanf(pasv, "%u,%u,%u,%u,%u,%u", | |
565 | + &ad[0], &ad[1], &ad[2], &ad[3], | |
566 | + &po[0], &po[1]) != 6) { | |
567 | + error = 1; | |
568 | + goto psv_done; | |
569 | + } | |
570 | + data_addr.su_sin.sin_addr.s_addr = htonl(pack4(ad)); | |
571 | + data_addr.su_port = htons(pack2(po)); | |
572 | + } else | |
573 | + if (strcmp(pasvcmd, "LPSV") == 0) { | |
574 | + if (code / 10 == 22 && code != 228) { | |
575 | + error = 228; | |
576 | + goto psv_done; | |
577 | + } | |
578 | + switch (data_addr.su_family) { | |
579 | + case AF_INET: | |
580 | + if (sscanf(pasv, "%u,%u,%u,%u,%u,%u,%u,%u,%u", | |
581 | + &af, &alen, | |
582 | + &ad[0], &ad[1], &ad[2], &ad[3], | |
583 | + &plen, &po[0], &po[1]) != 9) { | |
584 | + error = 1; | |
585 | + goto psv_done; | |
586 | + } | |
587 | + if (af != 4 || alen != 4 || plen != 2) { | |
588 | + error = 2; | |
589 | + goto psv_done; | |
590 | + } | |
591 | + data_addr.su_sin.sin_addr.s_addr = | |
592 | + htonl(pack4(ad)); | |
593 | + data_addr.su_port = htons(pack2(po)); | |
594 | + break; | |
595 | +#ifdef INET6 | |
596 | + case AF_INET6: | |
597 | + if (sscanf(pasv, | |
598 | + "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", | |
599 | + &af, &alen, | |
600 | + &ad[0], &ad[1], &ad[2], &ad[3], | |
601 | + &ad[4], &ad[5], &ad[6], &ad[7], | |
602 | + &ad[8], &ad[9], &ad[10], &ad[11], | |
603 | + &ad[12], &ad[13], &ad[14], &ad[15], | |
604 | + &plen, &po[0], &po[1]) != 21) { | |
605 | + error = 1; | |
606 | + goto psv_done; | |
607 | + } | |
608 | + if (af != 6 || alen != 16 || plen != 2) { | |
609 | + error = 2; | |
610 | + goto psv_done; | |
611 | + } | |
612 | + data_addr.su_sin6.sin6_addr.s6_addr32[0] = | |
613 | + htonl(pack4(ad)); | |
614 | + data_addr.su_sin6.sin6_addr.s6_addr32[1] = | |
615 | + htonl(pack4(ad+4)); | |
616 | + data_addr.su_sin6.sin6_addr.s6_addr32[2] = | |
617 | + htonl(pack4(ad+8)); | |
618 | + data_addr.su_sin6.sin6_addr.s6_addr32[3] = | |
619 | + htonl(pack4(ad+12)); | |
620 | + data_addr.su_port = htons(pack2(po)); | |
621 | + break; | |
622 | +#endif | |
623 | + default: | |
624 | + error = 1; | |
625 | + } | |
626 | + } else if (strncmp(pasvcmd, "EPSV", 4) == 0) { | |
627 | + char delim[4]; | |
628 | + u_int epsvpo; | |
629 | + | |
630 | + if (code / 10 == 22 && code != 229) { | |
631 | + error = 229; | |
632 | + goto psv_done; | |
633 | + } | |
634 | + if (sscanf(pasv, "%c%c%c%u%c", &delim[0], &delim[1], | |
635 | + &delim[2], &epsvpo, &delim[3]) != 5) { | |
636 | + error = 1; | |
637 | + goto psv_done; | |
638 | + } | |
639 | + if (delim[0] != delim[1] || delim[0] != delim[2] | |
640 | + || delim[0] != delim[3]) { | |
641 | + error = 1; | |
642 | + goto psv_done; | |
643 | + } | |
644 | + data_addr.su_port = htons(epsvpo); | |
645 | + } else { | |
646 | + error = 1; | |
647 | + } | |
648 | +psv_done: | |
649 | + switch (error) { | |
650 | + case 0: | |
651 | + break; | |
652 | + case 1: | |
653 | + fprintf(stderr, | |
654 | + "Passive mode address scan failure. Shouldn't happen!\n"); | |
655 | + goto bad; | |
656 | + case 2: | |
657 | + fprintf(stderr, | |
658 | + "Passive mode AF mismatch. Shouldn't happen!\n"); | |
659 | + goto bad; | |
660 | + case 227: | |
661 | + case 228: | |
662 | + case 229: | |
663 | + fprintf(stderr, | |
664 | + "wrong server: return code must be %d\n", error); | |
665 | + goto bad; | |
666 | + default: | |
667 | + fprintf(stderr, "Bug\n"); | |
668 | } | |
669 | ||
670 | - data_addr.sin_family = AF_INET; | |
671 | - data_addr.sin_addr.s_addr = htonl((a1 << 24) | (a2 << 16) | | |
672 | - (a3 << 8) | a4); | |
673 | - data_addr.sin_port = htons((p1 << 8) | p2); | |
674 | - | |
675 | if (connect(data, (struct sockaddr *) &data_addr, | |
676 | sizeof(data_addr))<0) { | |
677 | perror("ftp: connect"); | |
678 | return(1); | |
679 | } | |
680 | #ifdef IP_TOS | |
681 | + if (data_addr.su_family == AF_INET) | |
682 | + { | |
683 | tos = IPTOS_THROUGHPUT; | |
684 | if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&tos, | |
685 | sizeof(tos)) < 0) | |
686 | perror("ftp: setsockopt TOS (ignored)"); | |
687 | + } | |
688 | #endif | |
689 | return(0); | |
690 | } | |
691 | noport: | |
692 | data_addr = myctladdr; | |
693 | if (sendport) | |
694 | - data_addr.sin_port = 0; /* let system pick one */ | |
695 | + data_addr.su_port = 0; /* let system pick one */ | |
696 | if (data != -1) | |
697 | (void) close(data); | |
698 | - data = socket(AF_INET, SOCK_STREAM, 0); | |
699 | + data = socket(data_addr.su_family, SOCK_STREAM, 0); | |
700 | if (data < 0) { | |
701 | perror("ftp: socket"); | |
702 | if (tmpno) | |
703 | @@ -1172,13 +1430,47 @@ | |
704 | if (listen(data, 1) < 0) | |
705 | perror("ftp: listen"); | |
706 | if (sendport) { | |
707 | - a = (char *)&data_addr.sin_addr; | |
708 | - p = (char *)&data_addr.sin_port; | |
709 | -#define UC(b) (((int)b)&0xff) | |
710 | - result = | |
711 | - command("PORT %d,%d,%d,%d,%d,%d", | |
712 | - UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), | |
713 | - UC(p[0]), UC(p[1])); | |
714 | + af = ex_af2prot(data_addr.su_family); | |
715 | + if (try_eprt && af > 1) { /* only IPv6 */ | |
716 | + if (getnameinfo((struct sockaddr *)&data_addr, len, | |
717 | + hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), | |
718 | + NI_NUMERICHOST | NI_NUMERICSERV) == 0) { | |
719 | + result = command("EPRT |%d|%s|%s|", | |
720 | + af, hbuf, pbuf); | |
721 | + if (result != COMPLETE) { | |
722 | + try_eprt = 0; | |
723 | + } | |
724 | + } else { | |
725 | + result = ERROR; | |
726 | + } | |
727 | + } else { | |
728 | + result = COMPLETE + 1; | |
729 | + } | |
730 | + if (result == COMPLETE) | |
731 | + goto prt_done; | |
732 | + | |
733 | + p = (u_char *)&data_addr.su_port; | |
734 | + switch (data_addr.su_family) { | |
735 | + case AF_INET: | |
736 | + a = (u_char *)&data_addr.su_sin.sin_addr; | |
737 | + result = command("PORT %u,%u,%u,%u,%u,%u", | |
738 | + a[0], a[1], a[2], a[3], p[0], p[1]); | |
739 | + break; | |
740 | +#ifdef INET6 | |
741 | + case AF_INET6: | |
742 | + a = (u_char *)&data_addr.su_sin6.sin6_addr; | |
743 | + result = command( | |
744 | + "LPRT 6,16,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,2,%d,%d", | |
745 | + a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], | |
746 | + a[8], a[9],a[10],a[11],a[12],a[13],a[14],a[15], | |
747 | + p[0], p[1]); | |
748 | + break; | |
749 | +#endif | |
750 | + default: | |
751 | + result = COMPLETE + 1; /* xxx */ | |
752 | + } | |
753 | + | |
754 | + prt_done: | |
755 | if (result == ERROR && sendport == -1) { | |
756 | sendport = 0; | |
757 | tmpno = 1; | |
758 | @@ -1189,9 +1481,12 @@ | |
759 | if (tmpno) | |
760 | sendport = 1; | |
761 | #ifdef IP_TOS | |
762 | + if (data_addr.su_family == AF_INET) | |
763 | + { | |
764 | on = IPTOS_THROUGHPUT; | |
765 | if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) | |
766 | perror("ftp: setsockopt TOS (ignored)"); | |
767 | + } | |
768 | #endif | |
769 | return (0); | |
770 | bad: | |
771 | @@ -1204,7 +1499,7 @@ | |
772 | static FILE * | |
773 | dataconn(const char *lmode) | |
774 | { | |
775 | - struct sockaddr_in from; | |
776 | + union sockunion from; | |
777 | int s, tos; | |
778 | socklen_t fromlen = sizeof(from); | |
779 | ||
780 | @@ -1220,9 +1515,12 @@ | |
781 | (void) close(data); | |
782 | data = s; | |
783 | #ifdef IP_TOS | |
784 | + if (from.su_family == AF_INET) | |
785 | + { | |
786 | tos = IPTOS_THROUGHPUT; | |
787 | if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) | |
788 | perror("ftp: setsockopt TOS (ignored)"); | |
789 | + } | |
790 | #endif | |
791 | return (fdopen(data, lmode)); | |
792 | } | |
793 | @@ -1284,8 +1582,8 @@ | |
794 | static struct comvars { | |
795 | int connect; | |
796 | char name[MAXHOSTNAMELEN]; | |
797 | - struct sockaddr_in mctl; | |
798 | - struct sockaddr_in hctl; | |
799 | + union sockunion mctl; | |
800 | + union sockunion hctl; | |
801 | FILE *in; | |
802 | FILE *out; | |
803 | int tpe; | |
804 | @@ -1323,7 +1621,7 @@ | |
805 | connected = op->connect; | |
806 | if (hostname) { | |
807 | (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); | |
808 | - ip->name[strlen(ip->name)] = '\0'; | |
809 | + ip->name[sizeof(ip->name) - 1] = '\0'; | |
810 | } | |
811 | else { | |
812 | ip->name[0] = 0; | |
813 | @@ -1352,18 +1650,18 @@ | |
814 | ip->ntflg = ntflag; | |
815 | ntflag = op->ntflg; | |
816 | (void) strncpy(ip->nti, ntin, 16); | |
817 | - (ip->nti)[strlen(ip->nti)] = '\0'; | |
818 | + (ip->nti)[16] = '\0'; /* shouldn't use strlen */ | |
819 | (void) strcpy(ntin, op->nti); | |
820 | (void) strncpy(ip->nto, ntout, 16); | |
821 | - (ip->nto)[strlen(ip->nto)] = '\0'; | |
822 | + (ip->nto)[16] = '\0'; | |
823 | (void) strcpy(ntout, op->nto); | |
824 | ip->mapflg = mapflag; | |
825 | mapflag = op->mapflg; | |
826 | (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); | |
827 | - (ip->mi)[strlen(ip->mi)] = '\0'; | |
828 | + (ip->mi)[MAXPATHLEN - 1] = '\0'; | |
829 | (void) strcpy(mapin, op->mi); | |
830 | (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); | |
831 | - (ip->mo)[strlen(ip->mo)] = '\0'; | |
832 | + (ip->mo)[MAXPATHLEN - 1] = '\0'; | |
833 | (void) strcpy(mapout, op->mo); | |
834 | (void) signal(SIGINT, oldintr); | |
835 | if (abrtflag) { | |
836 | diff -uNr netkit-ftp-0.17/ftp/ftp_var.h netkit-ftp/ftp/ftp_var.h | |
837 | --- netkit-ftp-0.17/ftp/ftp_var.h Sat Oct 2 21:39:17 1999 | |
838 | +++ netkit-ftp/ftp/ftp_var.h Fri Jan 12 23:36:27 2001 | |
839 | @@ -1,3 +1,5 @@ | |
840 | +/* $USAGI$ */ | |
841 | + | |
842 | /* | |
843 | * Copyright (c) 1985, 1989 Regents of the University of California. | |
844 | * All rights reserved. | |
37a2e2e3 | 845 | @@ -112,6 +114,8 @@ |
846 | Extern int mflag; /* flag: if != 0, then active multi command */ | |
847 | ||
848 | Extern int options; /* used during socket creation */ | |
849 | +Extern int try_epsv; /* try EPSV for this session */ | |
850 | +Extern int try_eprt; /* try EPRT for this session */ | |
851 | ||
852 | /* | |
853 | * Format of command table. | |
854 | @@ -140,7 +144,7 @@ | |
855 | Extern char macbuf[4096]; | |
856 | #define MACBUF_SIZE 4096 | |
857 | ||
858 | -char *hookup(char *host, int port); | |
859 | +char *hookup(const char *host, const char *port); | |
860 | struct cmd *getcmd(const char *); | |
861 | char **makeargv(int *pargc, char **parg); | |
862 | int dologin(const char *host); |