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