1 diff -urN proftpd-1.2.5/Make.rules.in proftpd-1.2.5.v6/Make.rules.in
2 --- proftpd-1.2.5/Make.rules.in Sat Mar 17 21:34:31 2001
3 +++ proftpd-1.2.5.v6/Make.rules.in Thu Aug 8 21:35:24 2002
6 OBJS=main.o timers.o sets.o pool.o regexp.o dirtree.o support.o inet.o \
7 log.o bindings.o scoreboard.o feat.o netio.o response.o ident.o \
8 - data.o modules.o auth.o fsio.o mkhome.o
9 + data.o modules.o auth.o fsio.o mkhome.o intoa.o
10 BUILD_OBJS=src/main.o src/timers.o src/sets.o src/pool.o src/regexp.o \
11 src/dirtree.o src/support.o src/inet.o src/log.o src/bindings.o \
12 src/scoreboard.o src/feat.o src/netio.o src/response.o \
13 src/ident.o src/data.o src/modules.o src/auth.o src/fsio.o \
15 + src/mkhome.o src/intoa.o
17 MODULE_OBJS=@MODULE_OBJS@
18 BUILD_MODULE_OBJS=@BUILD_MODULE_OBJS@ modules/module_glue.o
20 -FTPCOUNT_OBJS=ftpcount.o scoreboard.o
21 -BUILD_FTPCOUNT_OBJS=utils/ftpcount.o utils/scoreboard.o
22 +FTPCOUNT_OBJS=ftpcount.o scoreboard.o intoa.o
23 +BUILD_FTPCOUNT_OBJS=utils/ftpcount.o utils/scoreboard.o src/intoa.o
25 FTPSHUT_OBJS=ftpshut.o
26 BUILD_FTPSHUT_OBJS=utils/ftpshut.o
28 FTPTOP_OBJS=ftptop.o scoreboard.o
29 BUILD_FTPTOP_OBJS=utils/ftptop.o utils/scoreboard.o
31 -FTPWHO_OBJS=ftpwho.o scoreboard.o misc.o
32 -BUILD_FTPWHO_OBJS=utils/ftpwho.o utils/scoreboard.o utils/misc.o
33 +FTPWHO_OBJS=ftpwho.o scoreboard.o misc.o intoa.o
34 +BUILD_FTPWHO_OBJS=utils/ftpwho.o utils/scoreboard.o utils/misc.o src/intoa.o
35 diff -urN proftpd-1.2.5/README.IPv6 proftpd-1.2.5.v6/README.IPv6
36 --- proftpd-1.2.5/README.IPv6 Thu Jan 1 01:00:00 1970
37 +++ proftpd-1.2.5.v6/README.IPv6 Thu Aug 8 21:35:24 2002
39 +FTP Daemon with IPv6 support for PLD GNU/Linux (http://www.pld.org.pl/)
41 +IPv6 port by Jan Rekorajski <baggins@pld.org.pl>
43 +Proftpd program is an example of How NOT To write networking code.
45 +Fixes by Arkadiusz Miskiewicz <misiek@pld.org.pl>:
46 +- removed IPv4-mapped hell
47 +- don't duplicate connection code
48 +- fixed EPRT (parsing, address missmatch)
49 +- inet_validate() recognize colon address notation
50 +- "EPSV ALL" support as specified in RFC
51 +- recognize [v6addr]/mask in Class
54 +If you want to specify IPv6 addres, you may use '[' ']'
55 +notation ([::1] for example).
61 +- test fully VirtualHosts and IPv4 <-> IPv6 interoperability
62 diff -urN proftpd-1.2.5/acconfig.h proftpd-1.2.5.v6/acconfig.h
63 --- proftpd-1.2.5/acconfig.h Sat Mar 17 21:34:31 2001
64 +++ proftpd-1.2.5.v6/acconfig.h Thu Aug 8 21:35:24 2002
66 * configure should, we hope <wink>, detect this for you.
70 +/* Define if you want IPv6 support */
73 +/* Define if you have ss_family field in struct sockaddr_storage */
74 +#undef HAVE_SS_FAMILY_IN_SS
78 /* autoheader generated things inserted here. */
79 diff -urN proftpd-1.2.5/config.h.in proftpd-1.2.5.v6/config.h.in
80 --- proftpd-1.2.5/config.h.in Sun May 12 22:48:54 2002
81 +++ proftpd-1.2.5.v6/config.h.in Thu Aug 8 21:35:24 2002
86 +/* Define if you want IPv6 support */
89 +/* Define if you have ss_family field in struct sockaddr_storage */
90 +#undef HAVE_SS_FAMILY_IN_SS
93 /* Define if using alloca.c. */
96 diff -urN proftpd-1.2.5/configure.in proftpd-1.2.5.v6/configure.in
97 --- proftpd-1.2.5/configure.in Tue May 21 20:26:30 2002
98 +++ proftpd-1.2.5.v6/configure.in Thu Aug 8 21:35:24 2002
103 +dnl === part for IPv6 support ===
104 +AC_MSG_CHECKING([whether to enable ipv6])
106 +[ --enable-ipv6 Enable ipv6 support
107 + --disable-ipv6 Disable ipv6 support],
108 +[case "$enableval" in
109 + no) AC_MSG_RESULT(no)
111 + *) AC_MSG_RESULT(yes)
113 + CFLAGS="$CFLAGS -DINET6"
116 +AC_TRY_RUN([ /* PF_INET6 avalable check */
117 +#include <sys/types.h>
118 +#include <sys/socket.h>
119 +main(){if (socket(PF_INET6, SOCK_STREAM, 0) < 0) exit(1); else exit(0);}
120 +],[ AC_MSG_RESULT(yes)
122 +],[ AC_MSG_RESULT(no)
123 +],[ AC_MSG_RESULT(unknown)
125 +AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage],
126 + ac_cv_have_ss_family_in_struct_ss, [
129 +#include <sys/types.h>
130 +#include <sys/socket.h>
132 + [ struct sockaddr_storage s; s.ss_family = 1; ],
133 + [ ac_cv_have_ss_family_in_struct_ss="yes" ],
134 + [ ac_cv_have_ss_family_in_struct_ss="no" ],
137 +if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then
138 + AC_DEFINE(HAVE_SS_FAMILY_IN_SS)
140 +dnl === end of part for IPv6 support ===
142 dnl Check for various argv[] replacing functions on various OSs
143 AC_CHECK_FUNCS(setproctitle)
144 AC_CHECK_HEADERS(libutil.h)
145 diff -urN proftpd-1.2.5/contrib/mod_ratio.c proftpd-1.2.5.v6/contrib/mod_ratio.c
146 --- proftpd-1.2.5/contrib/mod_ratio.c Mon May 27 04:31:50 2002
147 +++ proftpd-1.2.5.v6/contrib/mod_ratio.c Thu Aug 8 21:35:24 2002
152 - char buf[1024] = {'\0'};
156 if (!(g.enable = get_param_int (main_server->conf, "Ratios", FALSE) == TRUE))
158 c = find_config (main_server->conf, CONF_PARAM, "HostRatio", TRUE);
162 - if (*(char *) c->argv[0] == '.')
165 - sstrncpy (mask, c->argv[0], sizeof (buf));
167 - else if (*(char *) ((char *) c->argv[0] + (strlen (c->argv[0]) - 1)) == '.')
169 - sstrncpy (mask, c->argv[0], sizeof(buf) - 2);
170 - sstrcat(buf, "*", sizeof(buf));
173 - sstrncpy (mask, c->argv[0], sizeof (buf));
175 - if (!pr_fnmatch (buf, session.c->remote_name, PR_FNM_NOESCAPE | PR_FNM_CASEFOLD) ||
176 - !pr_fnmatch (buf, inet_ntoa (*session.c->remote_ipaddr),
177 - PR_FNM_NOESCAPE | PR_FNM_CASEFOLD))
178 + if (match_ip(session.c->remote_ipaddr, session.c->remote_name, c->argv[0]))
180 _set_ratios (c->argv[1], c->argv[2], c->argv[3], c->argv[4]);
183 snprintf (buf, sizeof(buf), RATIO_STUFFS);
184 log_pri (LOG_NOTICE, "Ratio: %s/%s %s[%s]: %s.", g.user,
185 session.group, session.c->remote_name,
186 - inet_ntoa (*session.c->remote_ipaddr), buf);
187 + INET_NTOA (session.c->remote_ipaddr), buf);
189 return DECLINED (cmd);
191 diff -urN proftpd-1.2.5/contrib/mod_sql.c proftpd-1.2.5.v6/contrib/mod_sql.c
192 --- proftpd-1.2.5/contrib/mod_sql.c Sun Jun 9 04:38:27 2002
193 +++ proftpd-1.2.5.v6/contrib/mod_sql.c Thu Aug 8 21:35:24 2002
194 @@ -1314,7 +1314,7 @@
198 - sstrncpy(argp, inet_ntoa(*session.c->remote_ipaddr), sizeof(arg));
199 + sstrncpy(argp, INET_NTOA(session.c->remote_ipaddr), sizeof(arg));
203 diff -urN proftpd-1.2.5/include/conf.h proftpd-1.2.5.v6/include/conf.h
204 --- proftpd-1.2.5/include/conf.h Wed Sep 26 17:00:33 2001
205 +++ proftpd-1.2.5.v6/include/conf.h Thu Aug 8 21:35:24 2002
208 /* Generic typedefs */
210 -typedef struct in_addr p_in_addr_t;
217 #endif /* __PROFTPD_SUPPORT_LIBRARY */
219 +#ifdef HAVE_SS_FAMILY_IN_SS
220 +#define __ss_family ss_family
223 #endif /* PR_CONF_H */
224 diff -urN proftpd-1.2.5/include/dirtree.h proftpd-1.2.5.v6/include/dirtree.h
225 --- proftpd-1.2.5/include/dirtree.h Tue May 21 22:47:15 2002
226 +++ proftpd-1.2.5.v6/include/dirtree.h Thu Aug 8 21:35:24 2002
229 int AnonymousGreeting; /* Do not greet until after user login */
231 - p_in_addr_t *ipaddr; /* Internal address of this server */
232 + struct sockaddr_storage *ipaddr; /* Internal address of this server */
233 struct conn_struc *listen; /* Our listening connection */
234 xaset_t *conf; /* Configuration details */
237 config_rec *find_config(xaset_t *, int, const char *, int);
238 void find_config_set_top(config_rec *);
239 int remove_config(xaset_t *, const char *, int);
240 -class_t *find_class(p_in_addr_t *, char *);
241 +class_t *find_class(struct sockaddr_storage *, char *);
243 array_header *parse_group_expression(pool *, int *, char **);
244 array_header *parse_user_expression(pool *, int *, char **);
246 char *get_context_name(cmd_rec *);
247 int get_boolean(cmd_rec *, int);
248 char *get_full_cmd(cmd_rec *);
249 -int match_ip(p_in_addr_t *, char *, const char *);
250 +int match_ip(struct sockaddr_storage*, char*, const char *);
252 #endif /* __DIRTREE_H */
253 diff -urN proftpd-1.2.5/include/ftp.h proftpd-1.2.5.v6/include/ftp.h
254 --- proftpd-1.2.5/include/ftp.h Fri May 10 18:52:39 2002
255 +++ proftpd-1.2.5.v6/include/ftp.h Thu Aug 8 21:35:24 2002
257 #define C_MIC "MIC" /* Integrity protected command */
258 #define C_PBSZ "PBSZ" /* Protection buffer size */
259 #define C_PROT "PROT" /* Data channel protection level */
260 +#define C_EPSV "EPSV" /* Extended PASV */
261 +#define C_EPRT "EPRT" /* Extended PORT */
263 #define C_ANY "*" /* Special "wildcard" matching command */
266 #define R_225 "225" /* Data connection open; no transfer in progress */
267 #define R_226 "226" /* Closing data connection. File transfer/abort successful */
268 #define R_227 "227" /* Entering passive mode (h1,h2,h3,h4,p1,p2) */
269 +#define R_229 "229" /* Entering extended passive mode (|||p|) */
270 #define R_230 "230" /* User logged in, proceed */
271 #define R_232 "232" /* User logged in, authorized by security data */
272 #define R_234 "234" /* Security data exchange complete */
274 #define R_502 "502" /* Command not implemented */
275 #define R_503 "503" /* Bad sequence of commands */
276 #define R_504 "504" /* Command not implemented for that parameter */
277 +#define R_522 "522" /* Extended Port Failure - unknown network protocol */
278 #define R_530 "530" /* Not logged in */
279 #define R_532 "532" /* Need account for storing files */
280 #define R_533 "533" /* Integrity protected command required by policy */
281 diff -urN proftpd-1.2.5/include/inet.h proftpd-1.2.5.v6/include/inet.h
282 --- proftpd-1.2.5/include/inet.h Tue May 21 22:47:15 2002
283 +++ proftpd-1.2.5.v6/include/inet.h Thu Aug 8 21:35:24 2002
285 int rfd,wfd; /* Read and write fds */
286 pr_netio_stream_t *instrm, *outstrm; /* Input/Output streams */
288 - p_in_addr_t *remote_ipaddr; /* Remote address of connection */
289 + struct sockaddr_storage *remote_ipaddr; /* Remote address of connection */
290 int remote_port; /* Remote port of connection */
291 - p_in_addr_t *local_ipaddr; /* Local side of connection */
292 + struct sockaddr_storage *local_ipaddr; /* Local side of connection */
293 int local_port; /* Local port */
294 char *remote_name; /* Remote FQDN */
297 char *inet_validate(char *);
298 char *inet_gethostname(pool *);
299 char *inet_fqdn(pool *, const char *);
300 -p_in_addr_t *inet_getaddr(pool *, char *);
301 -char *inet_ascii(pool *, p_in_addr_t *);
302 -char *inet_getname(pool *, p_in_addr_t *);
303 +struct sockaddr_storage *inet_getaddr(pool*,char*);
304 +char *inet_ascii(pool*,struct sockaddr_storage*);
305 +char *inet_getname(pool*,struct sockaddr_storage*);
306 conn_t *inet_copy_connection(pool *, conn_t*);
308 int inet_prebind_socket(pool *, p_in_addr_t *, int);
309 -conn_t *inet_create_dup_connection(pool *, xaset_t *, int, p_in_addr_t *);
310 -conn_t *inet_create_connection(pool *, xaset_t *, int, p_in_addr_t *, int, int);
311 -conn_t *inet_create_connection_portrange(pool *, xaset_t *, p_in_addr_t *,
313 +conn_t *inet_create_dup_connection(pool*,xaset_t*,int,struct sockaddr_storage*);
314 +conn_t *inet_create_connection(pool *, xaset_t *, int, struct sockaddr_storage *, int, int);
315 +conn_t *inet_create_connection_portrange(pool *, xaset_t *, struct sockaddr_storage *,
317 void inet_close(pool *, conn_t *);
318 void inet_lingering_close(pool *, conn_t *, long);
319 @@ -104,13 +106,19 @@
320 int inet_listen(pool *, conn_t *, int);
321 int inet_resetlisten(pool *, conn_t *);
322 int inet_accept_nowait(pool *, conn_t *);
323 -int inet_connect(pool *, conn_t *, p_in_addr_t *, int);
324 -int inet_connect_nowait(pool*,conn_t*,p_in_addr_t*,int);
325 +int inet_connect(pool *, conn_t *, struct sockaddr_storage *, int);
326 +int inet_connect_nowait(pool*,conn_t*,struct sockaddr_storage*, int);
327 int inet_get_conn_info(conn_t *, int);
328 conn_t *inet_accept(pool *, conn_t *, conn_t *, int, int, unsigned char);
329 -conn_t *inet_associate(pool *, conn_t *, p_in_addr_t *,
330 - pr_netio_stream_t *, pr_netio_stream_t *, int);
331 -conn_t *inet_openrw(pool *, conn_t *, p_in_addr_t *, int, int, int, int, int);
332 +conn_t *inet_associate(pool *, conn_t *, struct sockaddr_storage *, IOFILE *, IOFILE *, int);
333 +conn_t *inet_openrw(pool *, conn_t *, struct sockaddr_storage *, int, int, int, int);
334 void inet_resolve_ip(pool *, conn_t *);
335 +int inet_address_match(struct sockaddr_storage *cp,struct sockaddr_storage *rp);
336 +int inet_prefix_match(struct sockaddr_storage *cp,struct sockaddr_storage *rp, int prefix);
338 +char *INET_NTOA(struct sockaddr_storage *ss);
340 +#define INET_NTOA(a) inet_ntoa(((struct sockaddr_in *)(a))->sin_addr)
343 #endif /* PR_INET_H */
344 diff -urN proftpd-1.2.5/include/log.h proftpd-1.2.5.v6/include/log.h
345 --- proftpd-1.2.5/include/log.h Tue May 21 22:47:15 2002
346 +++ proftpd-1.2.5.v6/include/log.h Thu Aug 8 21:35:24 2002
348 #define LOG_XFER_MODE 0644
350 char *fmt_time(time_t);
351 -int log_wtmp(char *, const char *, const char *, p_in_addr_t *);
352 +int log_wtmp(char *, char *, char *, struct sockaddr_storage *);
353 void log_setfacility(int);
354 int log_openfile(const char *, int *, mode_t);
355 int log_opensyslog(const char *);
356 diff -urN proftpd-1.2.5/include/proftpd.h proftpd-1.2.5.v6/include/proftpd.h
357 --- proftpd-1.2.5/include/proftpd.h Tue May 21 22:47:15 2002
358 +++ proftpd-1.2.5.v6/include/proftpd.h Thu Aug 8 21:35:24 2002
360 typedef struct cdir_struc {
361 struct cdir_struc *next;
365 + struct sockaddr_storage address;
371 volatile int sf_flags; /* Session/State flags */
372 volatile int sp_flags; /* Session/Protection flags */
374 - p_in_addr_t data_addr; /* Remote data address */
375 + struct sockaddr_storage data_addr; /* Remote data address */
376 unsigned short data_port; /* Remote data port */
378 unsigned char ident_lookups; /* Is RFC931 (ident) protocol used? */
380 #define SF_ANON (1 << 5) /* Anonymous (chroot) login */
381 #define SF_POST_ABORT (1 << 6) /* After abort has occured */
382 #define SF_PORT (1 << 7) /* Port command given */
383 +#define SF_EPSV_ALL (1 << 8) /* EPSV ALL command given */
385 #define SF_ALL (SF_PASSIVE|SF_ABORT|SF_XFER|SF_ASCII| \
386 - SF_ASCII_OVERRIDE|SF_ANON|SF_POST_ABORT|SF_PORT)
387 + SF_ASCII_OVERRIDE|SF_ANON|SF_POST_ABORT|SF_PORT| \
390 /* Session/Protection flags (RFC 2228) */
392 diff -urN proftpd-1.2.5/include/support.h proftpd-1.2.5.v6/include/support.h
393 --- proftpd-1.2.5/include/support.h Tue May 21 22:47:15 2002
394 +++ proftpd-1.2.5.v6/include/support.h Thu Aug 8 21:35:24 2002
396 char *sstrncpy(char *, const char *, size_t);
397 char *sreplace(pool *, char *, ...);
399 +void mappedtov4(struct sockaddr_storage *);
401 #endif /* PR_SUPPORT_H */
402 diff -urN proftpd-1.2.5/modules/mod_auth.c proftpd-1.2.5.v6/modules/mod_auth.c
403 --- proftpd-1.2.5/modules/mod_auth.c Tue May 21 22:47:16 2002
404 +++ proftpd-1.2.5.v6/modules/mod_auth.c Thu Aug 8 21:35:24 2002
405 @@ -1210,7 +1210,7 @@
407 while((l = log_read_run(NULL)) != NULL)
408 /* Make sure it matches our current server */
409 - if(l->server_ip.s_addr == main_server->ipaddr->s_addr &&
410 + if(inet_address_match(&l->server_ip, main_server->ipaddr) &&
411 l->server_port == main_server->ServerPort) {
414 @@ -1270,11 +1270,11 @@
416 /* Make sure it matches our current server.
418 - if(l->server_ip.s_addr == main_server->ipaddr->s_addr &&
419 + if(inet_address_match(&l->server_ip, main_server->ipaddr) &&
420 l->server_port == main_server->ServerPort) {
421 if((c && c->config_type == CONF_ANON && !strcmp(l->user, user)) ||
423 - char *s, *d, ip[32] = {'\0'};
424 + char *s, *d, ip[64] = {'\0'};
425 int mpos = sizeof(ip) - 1;
428 @@ -1292,7 +1292,7 @@
430 /* Count up sessions on a per-host basis.
432 - if(!strcmp(ip, inet_ntoa(*session.c->remote_ipaddr))) {
433 + if(!strcmp(ip, INET_NTOA(session.c->remote_ipaddr))) {
437 diff -urN proftpd-1.2.5/modules/mod_core.c proftpd-1.2.5.v6/modules/mod_core.c
438 --- proftpd-1.2.5/modules/mod_core.c Tue May 21 22:47:16 2002
439 +++ proftpd-1.2.5.v6/modules/mod_core.c Thu Aug 8 21:35:24 2002
441 { C_REIN, "is not implemented", FALSE },
442 { C_PORT, "<sp> h1,h2,h3,h4,p1,p2", TRUE },
443 { C_PASV, "(returns address/port)", TRUE },
444 + { C_EPRT, "<sp> |proto|addr|port|", TRUE },
445 + { C_EPSV, "(returns port |||port|)", TRUE },
446 { C_TYPE, "<sp> type-code (A, I, L 7, L 8)", TRUE },
447 { C_STRU, "is not implemented (always F)", TRUE },
448 { C_MODE, "is not implemented (always S)", TRUE },
451 MODRET add_masqueradeaddress(cmd_rec *cmd) {
452 config_rec *c = NULL;
453 - p_in_addr_t *masq_addr = NULL;
454 + struct sockaddr_storage *masq_addr = NULL;
455 char masq_ip[80] = {'\0'};
458 @@ -2029,7 +2031,7 @@
460 if ((c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress",
462 - p_in_addr_t *masq_addr = (p_in_addr_t *) c->argv[0];
463 + struct sockaddr_storage *masq_addr = (struct sockaddr_storage *) c->argv[0];
464 serverfqdn = inet_getname(main_server->pool, masq_addr);
467 @@ -2191,7 +2193,7 @@
468 MODRET cmd_pasv(cmd_rec *cmd)
472 + struct in_addr addr;
476 @@ -2203,8 +2205,16 @@
477 config_rec *c = NULL;
478 int pasv_min_port,pasv_max_port;
480 + if (session.flags & SF_EPSV_ALL)
481 + return ERROR_MSG(cmd,R_500,"Illegal PASV command - EPSV ALL requested before.");
483 CHECK_CMD_ARGS(cmd, 1);
486 + if (session.c->local_ipaddr->__ss_family == AF_INET6)
487 + return ERROR_MSG(cmd,R_425, "PASV over IPv6? Find a real FTP client.");
490 /* If we already have a passive listen data connection open, kill it.
493 @@ -2250,14 +2260,16 @@
494 session.data_port = session.d->local_port;
495 session.flags |= SF_PASSIVE;
497 - addr.addr = *session.d->local_ipaddr;
498 + addr.addr.s_addr = ((struct sockaddr_in *)session.d->local_ipaddr)->sin_addr.s_addr;
500 /* check for a MasqueradeAddress configuration record, and return that
501 * addr if appropriate.
503 if ((c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress",
505 - addr.addr = *((p_in_addr_t *) c->argv[0]);
507 + struct sockaddr_storage *masq_addr = (struct sockaddr_storage *)c->argv[0];
508 + addr.addr.s_addr = ((struct sockaddr_in *)masq_addr)->sin_addr.s_addr;
511 port.port = htons(session.data_port);
513 @@ -2275,7 +2287,7 @@
514 MODRET cmd_port(cmd_rec *cmd)
518 + struct in_addr addr;
522 @@ -2285,11 +2297,19 @@
528 int allow_foreign_addr = 0;
530 + if (session.flags & SF_EPSV_ALL)
531 + return ERROR_MSG(cmd,R_500,"Illegal PORT command - EPSV ALL requested before.");
533 CHECK_CMD_ARGS(cmd, 2);
536 + if (session.c->local_ipaddr->__ss_family == AF_INET6)
537 + return ERROR_MSG(cmd,R_500, "PORT over IPv6? Find a real FTP client.");
540 /* Format is h1,h2,h3,h4,p1,p2 (ASCII in network order) */
541 a = pstrdup(cmd->tmp_pool,cmd->argv[1]);
543 @@ -2322,8 +2342,10 @@
544 allow_foreign_addr = get_param_int(TOPLEVEL_CONF,"AllowForeignAddress",FALSE);
546 if(allow_foreign_addr != 1) {
547 - if(addr.addr.s_addr != session.c->remote_ipaddr->s_addr ||
550 + p = ((struct sockaddr_in *)session.c->remote_ipaddr)->sin_addr.s_addr;
552 + if(addr.addr.s_addr != p || !port.port) {
553 log_pri(LOG_WARNING, "Refused PORT %s (address mismatch).", cmd->arg);
554 return ERROR_MSG(cmd, R_500, "Illegal PORT command.");
556 @@ -2338,7 +2360,9 @@
557 return ERROR_MSG(cmd,R_500,"Illegal PORT command.");
560 - memcpy(&session.data_addr, &addr.addr, sizeof(session.data_addr));
561 + session.data_addr.__ss_family = AF_INET;
562 + ((struct sockaddr_in *)&session.data_addr)->sin_port = port.port;
563 + ((struct sockaddr_in *)&session.data_addr)->sin_addr.s_addr = addr.addr.s_addr;
564 session.data_port = ntohs(port.port);
565 session.flags &= (SF_ALL^SF_PASSIVE);
567 @@ -2355,6 +2379,207 @@
571 +MODRET cmd_epsv(cmd_rec *cmd)
575 + config_rec *c = NULL;
576 + int pasv_min_port,pasv_max_port;
578 + CHECK_CMD_MIN_ARGS(cmd, 1);
580 + arg = pstrdup(cmd->tmp_pool,cmd->argv[1]);
583 + if (!strncasecmp(arg, "all", 3)) {
584 + session.flags |= SF_EPSV_ALL;
585 + add_response(R_200, "EPSV ALL command successful.");
586 + return HANDLED(cmd);
588 + family = strtol(arg, &endp, 10);
591 + if (!(session.c->local_ipaddr->__ss_family == AF_INET))
592 + return ERROR_MSG(cmd,R_522,"Illegal EPSV command - IPv4 not supported over this link.");
594 + } else if (family == 2) {
596 + if (!(session.c->local_ipaddr->__ss_family == AF_INET6))
598 + return ERROR_MSG(cmd,R_522,"Illegal EPSV command - IPv6 not supported over this link.");
600 + return ERROR_MSG(cmd,R_522,"Illegal EPSV command - unknown network protocol.");
605 + /* If we already have a passive listen data connection open,
610 + inet_close(session.d->pool,session.d);
614 + if ((c = find_config(main_server->conf, CONF_PARAM, "PassivePorts", FALSE)) !=
616 + pasv_min_port = (int)c->argv[0];
617 + pasv_max_port = (int)c->argv[1];
619 + if(!(session.d = inet_create_connection_portrange(session.pool, NULL,
620 + session.c->local_ipaddr,
621 + pasv_min_port,pasv_max_port))) {
622 + /* If not able to open a passive port in the given range, default to
623 + * normal behavior (using INPORT_ANY), and log the failure. This
624 + * indicates a too-small range configuration.
626 + log_pri(LOG_WARNING, "unable to find open port in PassivePorts range "
627 + "%d-%d: defaulting to INPORT_ANY", pasv_min_port, pasv_max_port);
632 + /* Open up the connection and pass it back.
635 + session.d = inet_create_connection(session.pool, NULL, -1,
636 + session.c->local_ipaddr,
637 + INPORT_ANY, FALSE);
640 + return ERROR_MSG(cmd,R_425,
641 + "Unable to build data connection: Internal error.");
643 + inet_setblock(session.pool,session.d);
644 + inet_listen(session.pool,session.d,1);
646 + session.d->inf = io_open(session.pool,session.d->listen_fd,IO_READ);
648 + /* Now tell the client our address/port */
649 + session.data_port = session.d->local_port;
650 + session.flags |= SF_PASSIVE;
652 + log_debug(DEBUG1,"Entering Extended Passive Mode (|||%u|).", (int)session.data_port);
653 + add_response(R_229, "Entering Extended Passive Mode (|||%u|).", (int)session.data_port);
655 + return HANDLED(cmd);
658 +MODRET cmd_eprt(cmd_rec *cmd)
660 + struct sockaddr_storage addr;
661 + unsigned short port = 0;
662 + char *a,*endp,*arg;
664 + int family,i,cnt = 0;
665 + int allow_foreign_addr = 0;
667 + if (session.flags & SF_EPSV_ALL)
668 + return ERROR_MSG(cmd,R_500,"Illegal EPRT command - EPSV ALL requested before.");
670 + CHECK_CMD_ARGS(cmd, 2);
672 + bzero(&addr, sizeof(struct sockaddr_storage));
674 + /* Format is <d>proto<d>ip address<d>port<d> (ASCII in network order) */
675 + a = pstrdup(cmd->tmp_pool,cmd->argv[1]);
680 + family = strtol(a, &endp, 10);
682 + addr.__ss_family = AF_INET;
684 + else if (family == 2)
685 + addr.__ss_family = AF_INET6;
688 + return ERROR_MSG(cmd,R_522,"Illegal EPRT command - unknown network protocol.");
691 + return ERROR_MSG(cmd,R_501,"Illegal EPRT command.");
695 + while(a && *a && cnt < 2) {
696 + arg = strsep(&a,delim);
698 + if(!arg && a && *a) {
707 + i = inet_pton(AF_INET, arg, &((struct sockaddr_in *)&addr)->sin_addr);
710 + i = inet_pton(AF_INET6, arg, &((struct sockaddr_in6 *)&addr)->sin6_addr);
714 + } else if (cnt == 1) {
715 + i = strtol(arg,&endp,10);
718 + port = (unsigned short)i;
720 + ((struct sockaddr_in *)&addr)->sin_port = htons(port);
723 + ((struct sockaddr_in6 *)&addr)->sin6_port = htons(port);
730 + if(cnt != 2 || (a && *a))
731 + return ERROR_MSG(cmd,R_501,"Illegal EPRT command.");
733 + /* Make sure that the address specified matches the address
734 + * that the control connection is coming from.
737 + allow_foreign_addr = get_param_int(TOPLEVEL_CONF,"AllowForeignAddress",FALSE);
739 + if(allow_foreign_addr != 1) {
740 + if(!inet_address_match(&addr, session.c->remote_ipaddr) || !port) {
741 + log_pri(LOG_WARNING, "Refused EPRT %s (address mismatch).", cmd->arg);
742 + return ERROR_MSG(cmd, R_500, "Illegal EPRT command.");
746 + /* Additionally, make sure that the port number used is a "high
747 + * numbered" port, to avoid bounce attacks
751 + log_pri(LOG_WARNING, "Refused EPRT %s (bounce attack).", cmd->arg);
752 + return ERROR_MSG(cmd,R_500,"Illegal EPRT command.");
755 + memcpy(&session.data_addr, &addr, sizeof(struct sockaddr_storage));
756 + session.data_port = port;
757 + session.flags &= (SF_ALL^SF_PASSIVE);
759 + /* If we already have a data connection open, kill it.
763 + inet_close(session.d->pool,session.d);
767 + session.flags |= SF_PORT;
768 + add_response(R_200,"EPRT command successful.");
769 + return HANDLED(cmd);
772 MODRET cmd_help(cmd_rec *cmd)
775 @@ -3044,18 +3269,15 @@
779 -static cdir_t *add_cdir(class_t *class, u_int_32 address, u_int_8 netmask)
780 +static cdir_t *add_cdir(class_t *class, struct sockaddr_storage *address, u_int_32 prefix)
784 n = calloc(1, sizeof(cdir_t));
787 - while (netmask--) {
789 - n->netmask |= 0x80000000;
791 - n->address = address & n->netmask;
792 + n->prefix = prefix;
793 + memcpy(&n->address, address, sizeof(struct sockaddr_storage));
797 @@ -3063,7 +3285,7 @@
801 -static cdir_t *find_cdir(u_int_32 address)
802 +static cdir_t *find_cdir(struct sockaddr_storage *address)
806 @@ -3071,7 +3293,8 @@
809 /* within cdir range ? && more specific netmask ? */
810 - if (((address & c->netmask) == c->address) && (f == NULL || (f && (f->netmask < c->netmask))))
811 + if (inet_prefix_match(&c->address, address, c->prefix) &&
812 + (f == NULL || (f && (f->prefix < c->prefix))))
816 @@ -3108,18 +3331,18 @@
820 -class_t *find_class(p_in_addr_t *addr, char *remote_name)
821 +class_t *find_class(struct sockaddr_storage *addr, char *remote_name)
827 - if ((ip = find_cdir(ntohl(addr->s_addr))) != NULL)
828 + if ((ip = find_cdir(addr)) != NULL)
831 if ((host = find_hostname(remote_name)) != NULL)
833 - if ((host = find_hostname(inet_ntoa(*addr))) != NULL)
834 + if ((host = find_hostname(INET_NTOA(addr))) != NULL)
838 @@ -3140,8 +3363,8 @@
843 - char *ptr, ipaddress[20] = {'\0'}, errmsg[80] = {'\0'};
844 + struct sockaddr_storage *res;
845 + char *ptr, *ptrr, ipaddress[50] = {'\0'}, errmsg[80] = {'\0'};
846 #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
849 @@ -3197,19 +3420,28 @@
850 CONF_ERROR(cmd, "wrong syntax error.");
852 bits = atol(ptr + 1);
855 + if (bits < 0 || bits > 128) {
857 if (bits < 0 || bits > 32) {
859 log_pri(LOG_ERR, "Class '%s' ipmask %s skipped: wrong netmask.",
860 cmd->argv[1], cmd->argv[3]);
866 + if ((ptr = strchr(ipaddress, '[')) && (ptrr = strrchr(ipaddress, ']'))) {
872 - if((res = inet_getaddr(cmd->pool, ipaddress)) != NULL) {
873 - add_cdir(n, ntohl(res->s_addr), bits);
874 - log_debug(DEBUG4, "Class '%s' ipmask %p/%d added.",
875 - cmd->argv[1], res, bits);
876 + if((res = inet_getaddr(cmd->pool, ptr)) != NULL) {
877 + add_cdir(n, res, bits);
878 + log_debug(DEBUG4, "Class '%s' ipmask %s/%d added.",
879 + cmd->argv[1], INET_NTOA(res), bits);
881 log_pri(LOG_ERR, "Class '%s' ip could not parse '%s'.",
882 cmd->argv[1], cmd->argv[3]);
883 @@ -3335,6 +3567,8 @@
884 { PRE_CMD, "*",G_NONE, regex_filters,FALSE, FALSE, CL_NONE },
886 { CMD, C_HELP, G_NONE, cmd_help, FALSE, FALSE, CL_INFO },
887 + { CMD, C_EPRT, G_NONE, cmd_eprt, TRUE, FALSE, CL_MISC },
888 + { CMD, C_EPSV, G_NONE, cmd_epsv, TRUE, FALSE, CL_MISC },
889 { CMD, C_PORT, G_NONE, cmd_port, TRUE, FALSE, CL_MISC },
890 { CMD, C_PASV, G_NONE, cmd_pasv, TRUE, FALSE, CL_MISC },
891 { CMD, C_SYST, G_NONE, cmd_syst, TRUE, FALSE, CL_INFO },
892 diff -urN proftpd-1.2.5/modules/mod_log.c proftpd-1.2.5.v6/modules/mod_log.c
893 --- proftpd-1.2.5/modules/mod_log.c Tue May 21 22:47:17 2002
894 +++ proftpd-1.2.5.v6/modules/mod_log.c Thu Aug 8 21:35:24 2002
899 - sstrncpy(argp, inet_ntoa(*session.c->remote_ipaddr), sizeof(arg));
900 + sstrncpy(argp, INET_NTOA(session.c->remote_ipaddr), sizeof(arg));
904 diff -urN proftpd-1.2.5/src/data.c proftpd-1.2.5.v6/src/data.c
905 --- proftpd-1.2.5/src/data.c Tue May 21 22:47:22 2002
906 +++ proftpd-1.2.5.v6/src/data.c Thu Aug 8 21:35:24 2002
910 log_debug(DEBUG4,"active data connection opened - local : %s:%d",
911 - inet_ntoa(*session.d->local_ipaddr), session.d->local_port);
912 + INET_NTOA(session.d->local_ipaddr), session.d->local_port);
913 log_debug(DEBUG4,"active data connection opened - remote : %s:%d",
914 - inet_ntoa(*session.d->remote_ipaddr),
915 - session.d->remote_port);
916 + INET_NTOA(session.d->remote_ipaddr), session.d->remote_port);
920 diff -urN proftpd-1.2.5/src/dirtree.c proftpd-1.2.5.v6/src/dirtree.c
921 --- proftpd-1.2.5/src/dirtree.c Tue May 21 22:47:22 2002
922 +++ proftpd-1.2.5.v6/src/dirtree.c Thu Aug 8 21:35:24 2002
923 @@ -917,13 +917,14 @@
924 * returns 0 if no match
927 -int match_ip(p_in_addr_t *addr, char *name, const char *match)
928 +int match_ip(struct sockaddr_storage *addr, char *name, const char *match)
932 - int cidr_mode = 0, cidr_bits;
933 - p_in_addr_t cidr_addr;
934 - u_int_32 cidr_mask = 0;
938 + struct in6_addr ia6, net6;
941 if(!strcasecmp(match,"ALL"))
943 @@ -932,55 +933,108 @@
946 memset(buf,0,sizeof(buf));
955 sstrcat(buf, match, sizeof(buf));
956 } else if(*(match + strlen(match) - 1) == '.') {
957 sstrcat(buf, match, sizeof(buf));
958 sstrcat(buf, "*", sizeof(buf));
959 - } else if((cp = strchr(match,'/')) != NULL) { /* check for CIDR notation */
960 - /* first portion of CIDR should be dotted quad, second portion
963 - sstrncpy(buf, match, (cp-match)+1 <= sizeof(buf) ?
964 - (cp-match)+1 : sizeof(buf));
965 - cidr_bits = atoi(cp+1);
967 - if(cidr_bits > 0 && cidr_bits < 33) {
968 - int shift = 32 - cidr_bits;
972 - cidr_mask = (cidr_mask << 1) | 1;
973 - cidr_mask = cidr_mask << shift;
974 -#ifdef HAVE_INET_ATON
975 - if(inet_aton(mask,&cidr_addr) == 0)
978 - cidr_addr.s_addr = inet_addr(mask);
980 - cidr_addr.s_addr &= htonl(cidr_mask);
984 + } else if(*match == '[' && *(match + strlen(match) - 1) == ']') {
985 + sstrcat(buf, match+1, sizeof(buf));
986 + *(bufptr + strlen(bufptr) - 1) = '\0';
988 sstrcat(buf, match, sizeof(buf));
992 - if((addr->s_addr & htonl(cidr_mask)) == cidr_addr.s_addr)
993 + /* Now match can be one of the following:
996 + * (3) 123.456.0.0/16
998 + * (5) abcd:1234::dead:beef
999 + * (6) abcd:1234::/32
1002 + if (addr->__ss_family == AF_INET6) {
1003 + cp = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr;
1006 + cp = (char *)&((struct sockaddr_in *)addr)->sin_addr;
1007 + /* This will catch (1) and (2) */
1008 + if(pr_fnmatch(buf, name, PR_FNM_NOESCAPE | PR_FNM_CASEFOLD) == 0 ||
1009 + pr_fnmatch(buf, INET_NTOA(addr), PR_FNM_NOESCAPE | PR_FNM_CASEFOLD) == 0)
1012 + /* This will catch (4) and (5) */
1014 + /* For IPv6, pr_fnmatch() for comparing addresses is
1015 + not working enough. */
1016 + if (inet_pton(AF_INET6, buf, &net6) == 1) {
1017 + if (name && inet_pton(AF_INET6, name, &ia6) == 1 &&
1018 + IN6_ARE_ADDR_EQUAL(&ia6, &net6)) {
1021 - if(pr_fnmatch(buf, name, PR_FNM_NOESCAPE | PR_FNM_CASEFOLD) == 0 ||
1022 - pr_fnmatch(buf, inet_ntoa(*addr),
1023 - PR_FNM_NOESCAPE | PR_FNM_CASEFOLD) == 0)
1024 + } else if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr, &net6)) {
1032 + /* And now (3) and (6) */
1033 + if((cp = strchr(match,'/')) != NULL) { /* check for CIDR notation */
1034 + /* first portion of CIDR should be dotted quad, second portion
1038 + struct in_addr ia, net;
1039 + unsigned int mask;
1043 + if (addr->__ss_family == AF_INET6) {
1044 + ia.s_addr = INADDR_NONE;
1047 + ia.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
1048 + net.s_addr = inet_addr(match);
1049 + if (ia.s_addr != (unsigned int)INADDR_NONE &&
1050 + net.s_addr != (unsigned int)INADDR_NONE) {
1051 + if (strchr(cp+1, '.') == (char *)NULL) {
1052 + mask = atoi(cp+1);
1053 + for (bits = c = 0; c < mask && c < 32; c++)
1054 + bits |= (1 << (31 - c));
1055 + mask = htonl(bits);
1057 + mask = inet_addr(cp+1);
1059 + if ((ia.s_addr & mask) == (net.s_addr & mask))
1062 + } else if (inet_pton(AF_INET6, buf, &net6) == 1) {
1063 + struct sockaddr_in6 *pia6;
1065 + pia6 = (struct sockaddr_in6 *)addr;
1066 + if (strchr(cp+1, ':') == (char *)NULL) {
1067 + mask = atoi(cp+1);
1071 + for (c = 0; c < n; c++)
1072 + if (pia6->sin6_addr.s6_addr[c] != net6.s6_addr[c]) {
1076 + if (netmatch && bits > 0) {
1077 + if ((pia6->sin6_addr.s6_addr[c] & (0xff << (8 - bits))) !=
1078 + (net6.s6_addr[c] & (0xff << (8 - bits))))
1088 /* As of 1.2.0rc3, a '!' character in front of the IP address
1089 @@ -2513,7 +2567,7 @@
1091 log_pri(LOG_INFO, "%s:%d masquerading as %s",
1092 inet_ascii(s->pool, s->ipaddr), s->ServerPort,
1093 - inet_ascii(s->pool, (p_in_addr_t *) c->argv[0]));
1094 + inet_ascii(s->pool, c->argv[0]));
1097 /* honor the DefaultServer directive only if SocketBindTight is not
1098 @@ -2521,7 +2575,11 @@
1100 if (get_param_int(s->conf, "DefaultServer", FALSE) == 1) {
1101 if (!SocketBindTight)
1102 - s->ipaddr->s_addr = 0;
1104 + memcpy(&((struct sockaddr_in6 *)s->ipaddr)->sin6_addr, &in6addr_any, sizeof(struct in6_addr));
1106 + ((struct sockaddr_in *)s->ipaddr)->sin_addr = INADDR_ANY;
1110 "SocketBindTight in effect, ignoring DefaultServer");
1111 diff -urN proftpd-1.2.5/src/inet.c proftpd-1.2.5.v6/src/inet.c
1112 --- proftpd-1.2.5/src/inet.c Tue May 21 22:47:22 2002
1113 +++ proftpd-1.2.5.v6/src/inet.c Thu Aug 8 21:35:31 2002
1114 @@ -130,7 +130,11 @@
1115 for(p = buf; p && *p; p++) {
1116 /* Per RFC requirements, these are all that are valid from a DNS.
1118 - if(!isalnum(*p) && *p != '.' && *p != '-') {
1119 + if(!isalnum(*p) && *p != '.' && *p != '-'
1124 /* We set it to _ because we know that's an invalid, yet safe, option
1127 @@ -175,35 +179,31 @@
1129 /* DNS/hosts lookup for a particular name
1131 -p_in_addr_t *inet_getaddr(pool *pool, char *name)
1132 +struct sockaddr_storage *inet_getaddr(pool *pool, char *name)
1134 - struct hostent *host;
1136 + struct addrinfo hints, *res, *res0;
1137 + struct sockaddr_storage *ss;
1139 - res = (p_in_addr_t*)pcalloc(pool,sizeof(p_in_addr_t));
1140 + ss = (struct sockaddr_storage*)pcalloc(pool,sizeof(struct sockaddr_storage));
1142 - /* Try dotted quad notation first */
1143 -#ifdef HAVE_INET_ATON
1144 - if(inet_aton(name,res))
1147 - /* This is a bit unclean, because inet_addr() is obsolete, and
1148 - * returns -1 (255.255.255.255) if the input is invalid. The caller
1149 - * _might_ just be trying to resolve "255.255.255.255", in which case
1150 - * this entire function will fail. Hopefully, you have inet_aton().
1153 - if((res->s_addr = inet_addr(name)) != -1)
1156 + bzero(&hints, sizeof(hints));
1157 + hints.ai_family = AF_UNSPEC;
1158 + hints.ai_socktype = SOCK_STREAM;
1160 - host = gethostbyname(name);
1162 - memcpy(res, host->h_addr_list[0], sizeof(p_in_addr_t));
1164 + if (getaddrinfo(name, "0", &hints, &res0))
1166 + for (res = res0; res; res = res->ai_next) {
1167 + if (res->ai_family == AF_INET
1169 + || res->ai_family == AF_INET6
1172 + memcpy(ss, res->ai_addr, res->ai_addrlen);
1173 + freeaddrinfo(res0);
1179 + freeaddrinfo(res0);
1183 @@ -211,54 +211,51 @@
1187 -char *inet_ascii(pool *pool, p_in_addr_t *addr)
1188 +char *inet_ascii(pool *pool, struct sockaddr_storage *ss)
1190 + static char buf[1024];
1193 - if((res = inet_ntoa(*addr)) != NULL)
1194 - res = pstrdup(pool,res);
1195 + if (getnameinfo((struct sockaddr *)ss, sizeof(struct sockaddr_storage),
1196 + buf, sizeof(buf), NULL, 0, NI_NUMERICHOST))
1199 + res = pstrdup(pool,buf);
1204 /* Given an ip addresses, return the FQDN */
1205 -char *inet_getname(pool *pool, p_in_addr_t *addr)
1206 +char *inet_getname(pool *pool, struct sockaddr_storage *addr)
1208 + static char peername[1024];
1211 - struct hostent *hptr_rev = NULL, *hptr_forw = NULL;
1212 static char *res_cache = NULL;
1213 - static p_in_addr_t *addr_cache = NULL;
1214 + static struct sockaddr_storage *addr_cache = NULL;
1217 - if(res_cache && addr_cache && addr_cache->s_addr == addr->s_addr) {
1218 + if(res_cache && addr_cache && inet_address_match(addr_cache, addr)) {
1219 res = pstrdup(pool, res_cache);
1220 return inet_validate(res);
1223 - if((hptr_rev = gethostbyaddr((const char *)addr,
1224 - sizeof(p_in_addr_t), AF_INET)) != NULL) {
1225 - if((hptr_forw = gethostbyname(hptr_rev->h_name)) != NULL) {
1226 - for(checkaddr = hptr_forw->h_addr_list; *checkaddr; ++checkaddr) {
1227 - if(((p_in_addr_t*)(*checkaddr))->s_addr == addr->s_addr) {
1228 - res = pstrdup(pool, hptr_rev->h_name);
1234 + if (getnameinfo((struct sockaddr *)&addr, sizeof(struct sockaddr_storage),
1235 + peername, sizeof(peername), NULL, 0, 0) == 0) {
1236 + res = pstrdup(pool, peername);
1241 - res = pstrdup(pool, inet_ntoa(*addr));
1242 + res = pstrdup(pool, INET_NTOA(addr));
1245 /* cache the result */
1247 - addr_cache = malloc(sizeof(p_in_addr_t));
1248 + addr_cache = malloc(sizeof(struct sockaddr_storage));
1251 - memcpy(addr_cache, addr, sizeof(p_in_addr_t));
1252 + memcpy(addr_cache, addr, sizeof(struct sockaddr_storage));
1256 @@ -305,12 +302,12 @@
1257 res->inf = res->outf = NULL;
1259 if(c->local_ipaddr) {
1260 - res->local_ipaddr = (p_in_addr_t*)palloc(res->pool,sizeof(p_in_addr_t));
1261 + res->local_ipaddr = (struct sockaddr_storage*)palloc(res->pool,sizeof(struct sockaddr_storage));
1262 *res->local_ipaddr = *c->local_ipaddr;
1265 if(c->remote_ipaddr) {
1266 - res->remote_ipaddr = (p_in_addr_t*)palloc(res->pool,sizeof(p_in_addr_t));
1267 + res->remote_ipaddr = (struct sockaddr_storage*)palloc(res->pool,sizeof(struct sockaddr_storage));
1268 *res->remote_ipaddr = *c->remote_ipaddr;
1271 @@ -396,14 +393,15 @@
1272 * just for the new connection.
1274 static conn_t *inet_initialize_connection(pool *p, xaset_t *servers, int fd,
1275 - p_in_addr_t *bind_addr, int port,
1276 - int retry_bind, int reporting)
1277 + struct sockaddr_storage *bind_addr,
1278 + int port, int retry_bind, int reporting)
1284 - struct sockaddr_in servaddr;
1285 + struct sockaddr_storage servaddr;
1287 int i,res = 0, len, one = 1, hold_errno;
1291 /* Build the accept IPs dynamically using the inet work pool,
1292 * once built, move into the conn struc.
1294 - tmp = make_array(inet_pool, 5, sizeof(p_in_addr_t));
1295 + tmp = make_array(inet_pool, 5, sizeof(struct sockaddr_storage));
1296 subpool = make_sub_pool(p);
1297 c = (conn_t *) pcalloc(subpool, sizeof(conn_t));
1300 if(servers && servers->xas_list) {
1301 for(s = (server_rec *) servers->xas_list; s; s = s->next)
1303 - *((p_in_addr_t *) push_array(tmp)) = *s->ipaddr;
1304 + memcpy(((struct sockaddr_storage*)push_array(tmp)), s->ipaddr, sizeof(struct sockaddr_storage));
1306 - *((p_in_addr_t *) push_array(tmp)) = *main_server->ipaddr;
1307 + memcpy(((struct sockaddr_storage*)push_array(tmp)), main_server->ipaddr, sizeof(struct sockaddr_storage));
1310 c->local_port = port;
1311 @@ -436,6 +434,18 @@
1316 + family = bind_addr->__ss_family;
1319 + if ((fd = socket(AF_INET6, SOCK_STREAM, 0)) != -1) {
1321 + family = AF_INET6;
1327 /* Certain versions of Solaris apparently require us to be root
1328 * in order to create a socket inside a chroot ??
1334 - fd = socket(AF_INET, SOCK_STREAM, tcp_proto);
1335 + fd = socket(family, SOCK_STREAM, tcp_proto);
1337 #if defined(SOLARIS2) || defined(FREEBSD2) || defined(FREEBSD3) || \
1338 defined(FREEBSD4) || defined(__OpenBSD__) || defined(__NetBSD__) || \
1339 @@ -494,15 +504,28 @@
1341 memset(&servaddr, 0, sizeof(servaddr));
1343 - servaddr.sin_family = AF_INET;
1346 - memcpy(&servaddr.sin_addr, bind_addr, sizeof(servaddr.sin_addr));
1348 - servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
1350 - servaddr.sin_port = htons(port);
1351 + memcpy(&servaddr, bind_addr, sizeof(struct sockaddr_storage));
1354 + if (family == AF_INET6)
1355 + ((struct sockaddr_in6 *)&servaddr)->sin6_addr = in6addr_any;
1358 + ((struct sockaddr_in *)&servaddr)->sin_addr.s_addr = htonl(INADDR_ANY);
1362 + if (family == AF_INET6) {
1363 + ((struct sockaddr_in6 *)&servaddr)->sin6_family = AF_INET6;
1364 + ((struct sockaddr_in6 *)&servaddr)->sin6_port = htons(port);
1368 + ((struct sockaddr_in *)&servaddr)->sin_family = AF_INET;
1369 + ((struct sockaddr_in *)&servaddr)->sin_port = htons(port);
1372 if(port != INPORT_ANY && port < 1024) {
1378 log_pri(LOG_ERR, "Failed binding to %s, port %d: %s",
1379 - inet_ntoa(servaddr.sin_addr), port, strerror(hold_errno));
1380 + INET_NTOA((struct sockaddr_storage *)&servaddr),
1381 + port, strerror(hold_errno));
1382 log_pri(LOG_ERR, "Check the ServerType directive "
1383 "to ensure you are configured correctly.");
1385 @@ -571,11 +595,16 @@
1387 len = sizeof(servaddr);
1388 if(fd >= 0 && getsockname(fd, (struct sockaddr *) &servaddr, &len) != -1) {
1389 + mappedtov4(&servaddr);
1390 if(!c->local_ipaddr)
1391 - c->local_ipaddr = (p_in_addr_t *) pcalloc(c->pool,
1392 - sizeof(p_in_addr_t));
1393 - *c->local_ipaddr = servaddr.sin_addr;
1394 - c->local_port = ntohs(servaddr.sin_port);
1395 + c->local_ipaddr = (struct sockaddr_storage*)pcalloc(c->pool,sizeof(struct sockaddr_storage));
1396 + memcpy(c->local_ipaddr, &servaddr, sizeof(struct sockaddr_storage));
1398 + if (servaddr.__ss_family == AF_INET6)
1399 + c->local_port = ntohs(((struct sockaddr_in6 *)&servaddr)->sin6_port);
1402 + c->local_port = ntohs(((struct sockaddr_in *)&servaddr)->sin_port);
1409 conn_t *inet_create_connection(pool *p, xaset_t *servers, int fd,
1410 - p_in_addr_t *bind_addr, int port,
1412 + struct sockaddr_storage *bind_addr,
1413 + int port, int retry_bind)
1415 conn_t *c = inet_initialize_connection(p, servers, fd, bind_addr,
1416 port, retry_bind, TRUE);
1420 conn_t *inet_create_connection_portrange(pool *p, xaset_t *servers,
1421 - p_in_addr_t *bind_addr, int low_port, int high_port)
1422 + struct sockaddr_storage *bind_addr,
1423 + int low_port, int high_port)
1425 int range_len, index;
1427 @@ -902,20 +932,30 @@
1431 -int inet_connect(pool *pool, conn_t *c, p_in_addr_t *addr, int port)
1432 +int inet_connect(pool *pool, conn_t *c, struct sockaddr_storage *addr, int port)
1434 - struct sockaddr_in remaddr;
1436 + struct sockaddr_storage remaddr;
1438 inet_setblock(pool,c);
1439 - remaddr.sin_family = AF_INET;
1440 - remaddr.sin_addr = *addr;
1441 - remaddr.sin_port = htons(port);
1443 + memcpy(&remaddr, addr, sizeof(struct sockaddr_storage));
1445 + if (addr->__ss_family == AF_INET6)
1446 + ((struct sockaddr_in6 *)&remaddr)->sin6_port = htons(port);
1449 + ((struct sockaddr_in *)&remaddr)->sin_port = htons(port);
1451 c->mode = CM_CONNECT;
1453 - while( (ret = connect(c->listen_fd,(struct sockaddr*)&remaddr,sizeof(remaddr))) == -1 &&
1454 - errno == EINTR ) ;
1455 + while( (ret = connect(c->listen_fd,(struct sockaddr*)&remaddr,
1457 + (addr->__ss_family == AF_INET) ?
1458 + sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)
1460 + sizeof(struct sockaddr_in)
1462 + ) == -1) && errno == EINTR ) ;
1466 @@ -937,18 +977,28 @@
1467 * called once, and can then be selected for writing.
1470 -int inet_connect_nowait(pool *pool, conn_t *c, p_in_addr_t *addr, int port)
1471 +int inet_connect_nowait(pool *pool, conn_t *c, struct sockaddr_storage *addr, int port)
1473 - struct sockaddr_in remaddr;
1474 + struct sockaddr_storage remaddr;
1476 inet_setnonblock(pool,c);
1478 - remaddr.sin_family = AF_INET;
1479 - remaddr.sin_addr = *addr;
1480 - remaddr.sin_port = htons(port);
1481 + memcpy(&remaddr, addr, sizeof(struct sockaddr_storage));
1483 + if (addr->__ss_family == AF_INET6)
1484 + ((struct sockaddr_in6 *)&remaddr)->sin6_port = htons(port);
1487 + ((struct sockaddr_in *)&remaddr)->sin_port = htons(port);
1489 c->mode = CM_CONNECT;
1490 - if(connect(c->listen_fd,(struct sockaddr*)&remaddr,sizeof(remaddr)) == -1) {
1491 + if(connect(c->listen_fd,(struct sockaddr*)&remaddr,
1493 + (addr->__ss_family == AF_INET) ?
1494 + sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)
1496 + sizeof(struct sockaddr_in)
1499 if(errno != EINPROGRESS && errno != EALREADY) {
1502 @@ -978,7 +1028,7 @@
1503 int inet_accept_nowait(pool *pool, conn_t *c)
1506 - struct sockaddr_in servaddr;
1507 + struct sockaddr_storage servaddr;
1508 int len = sizeof(servaddr);
1510 if(c->mode == CM_LISTEN)
1511 @@ -1013,7 +1063,7 @@
1514 int newfd = -1, allow_foreign_addr = -1;
1515 - struct sockaddr_in addr;
1516 + struct sockaddr_storage addr;
1517 int addrlen = sizeof(addr);
1519 d->mode = CM_ACCEPT;
1520 @@ -1025,10 +1075,32 @@
1522 if((allow_foreign_addr != 1) &&
1523 (getpeername(newfd, (struct sockaddr *) &addr, &addrlen) != -1)) {
1524 - if(addr.sin_addr.s_addr != c->remote_ipaddr->s_addr) {
1525 + mappedtov4(&addr);
1527 + if (addr.__ss_family == AF_INET6) {
1528 + if (!IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)&addr)->sin6_addr,
1529 + &((struct sockaddr_in6 *)c->remote_ipaddr)->sin6_addr)) {
1530 + log_pri(LOG_NOTICE,
1531 + "SECURITY VIOLATION: Passive connection from %s rejected.",
1532 + INET_NTOA(&addr));
1538 + if (addr.__ss_family == AF_INET) {
1539 + if(((struct sockaddr_in *)&addr)->sin_addr.s_addr !=
1540 + ((struct sockaddr_in *)c->remote_ipaddr)->sin_addr.s_addr) {
1541 + log_pri(LOG_NOTICE,
1542 + "SECURITY VIOLATION: Passive connection from %s rejected.",
1543 + INET_NTOA(&addr));
1549 "SECURITY VIOLATION: Passive connection from %s rejected.",
1550 - inet_ntoa(addr.sin_addr));
1551 + INET_NTOA(&addr));
1555 @@ -1047,7 +1119,7 @@
1558 int inet_get_conn_info(conn_t *c, int fd) {
1559 - static struct sockaddr_in servaddr;
1560 + static struct sockaddr_storage servaddr;
1561 int len = sizeof(servaddr);
1564 @@ -1058,21 +1130,33 @@
1567 if (getsockname(fd, (struct sockaddr *) &servaddr, &len) != -1) {
1568 + mappedtov4(&servaddr);
1569 if (!c->local_ipaddr)
1570 - c->local_ipaddr = (p_in_addr_t *) pcalloc(c->pool, sizeof(p_in_addr_t));
1571 - *c->local_ipaddr = servaddr.sin_addr;
1572 - c->local_port = ntohs(servaddr.sin_port);
1574 + c->local_ipaddr = (struct sockaddr_storage*)pcalloc(c->pool,sizeof(struct sockaddr_storage));
1575 + memcpy(c->local_ipaddr, &servaddr, sizeof(struct sockaddr_storage));
1577 + if (servaddr.__ss_family == AF_INET6)
1578 + c->local_port = ntohs(((struct sockaddr_in6 *)&servaddr)->sin6_port);
1581 + if (servaddr.__ss_family == AF_INET)
1582 + c->local_port = ntohs(((struct sockaddr_in *)&servaddr)->sin_port);
1586 len = sizeof(servaddr);
1588 if (getpeername(fd, (struct sockaddr *) &servaddr, &len) != -1) {
1589 - c->remote_ipaddr = (p_in_addr_t *) pcalloc(c->pool, sizeof(p_in_addr_t));
1590 - *c->remote_ipaddr = servaddr.sin_addr;
1591 - c->remote_port = ntohs(servaddr.sin_port);
1593 + mappedtov4(&servaddr);
1594 + c->remote_ipaddr = (struct sockaddr_storage*)pcalloc(c->pool,sizeof(struct sockaddr_storage));
1595 + memcpy(c->remote_ipaddr, &servaddr, sizeof(struct sockaddr_storage));
1597 + if (servaddr.__ss_family == AF_INET6)
1598 + c->remote_port = ntohs(((struct sockaddr_in6 *)&servaddr)->sin6_port);
1601 + if (servaddr.__ss_family == AF_INET)
1602 + c->remote_port = ntohs(((struct sockaddr_in *)&servaddr)->sin_port);
1606 @@ -1086,7 +1170,7 @@
1607 * If resolve is non-zero, the remote address is reverse resolved.
1610 -conn_t *inet_associate(pool *pool, conn_t *c, p_in_addr_t *addr,
1611 +conn_t *inet_associate(pool *pool, conn_t *c, struct sockaddr_storage *addr,
1612 IOFILE *inf, IOFILE *outf, int resolve)
1615 @@ -1120,15 +1204,15 @@
1618 if(!res->remote_ipaddr)
1619 - res->remote_ipaddr = (p_in_addr_t*)palloc(res->pool,sizeof(p_in_addr_t));
1620 - *res->remote_ipaddr = *addr;
1621 + res->remote_ipaddr = (struct sockaddr_storage*)palloc(res->pool,sizeof(struct sockaddr_storage));
1622 + memcpy(res->remote_ipaddr, addr, sizeof(struct sockaddr_storage));
1625 if(resolve && res->remote_ipaddr)
1626 res->remote_name = inet_getname(res->pool,res->remote_ipaddr);
1628 if(!res->remote_name)
1629 - res->remote_name = pstrdup(res->pool,inet_ntoa(*res->remote_ipaddr));
1630 + res->remote_name = pstrdup(res->pool,INET_NTOA(res->remote_ipaddr));
1632 inet_setoptions(res->pool,res,0,0);
1633 /* inet_setnonblock(res->pool,res); */
1634 @@ -1152,7 +1236,7 @@
1635 * Important, do not call any log_* functions from inside of inet_openrw()
1636 * or any functions it calls, as the possibility for fd overwriting occurs.
1638 -conn_t *inet_openrw(pool *pool, conn_t *c, p_in_addr_t *addr, int fd,
1639 +conn_t *inet_openrw(pool *pool, conn_t *c, struct sockaddr_storage *addr, int fd,
1640 int rfd,int wfd, int resolve)
1643 @@ -1172,15 +1256,15 @@
1646 if (!res->remote_ipaddr)
1647 - res->remote_ipaddr = (p_in_addr_t*)palloc(res->pool,sizeof(p_in_addr_t));
1648 - *res->remote_ipaddr = *addr;
1649 + res->remote_ipaddr = (struct sockaddr_storage*)palloc(res->pool,sizeof(struct sockaddr_storage));
1650 + memcpy(res->remote_ipaddr, addr, sizeof(struct sockaddr_storage));
1653 if (resolve && res->remote_ipaddr)
1654 res->remote_name = inet_getname(res->pool,res->remote_ipaddr);
1656 if (!res->remote_name)
1657 - res->remote_name = pstrdup(res->pool,inet_ntoa(*res->remote_ipaddr));
1658 + res->remote_name = pstrdup(res->pool,INET_NTOA(res->remote_ipaddr));
1660 if (fd == -1 && c->listen_fd != -1)
1662 @@ -1224,6 +1308,127 @@
1666 +int inet_address_match(struct sockaddr_storage *cp,
1667 + struct sockaddr_storage *rp)
1669 + struct sockaddr_in *sin_cp, *sin_rp;
1671 + struct sockaddr_in6 *sin6_cp, *sin6_rp;
1673 + if (cp->__ss_family == AF_INET6 && rp->__ss_family == AF_INET) {
1674 + sin6_cp = (struct sockaddr_in6 *)cp;
1675 + sin_rp = (struct sockaddr_in *)rp;
1676 + if (IN6_IS_ADDR_V4MAPPED(&sin6_cp->sin6_addr) &&
1677 + memcmp(&sin6_cp->sin6_addr.s6_addr[12], &sin_rp->sin_addr.s_addr,
1678 + sizeof(struct in_addr)) == 0)
1682 + } else if (cp->__ss_family == AF_INET && rp->__ss_family == AF_INET6) {
1683 + sin_cp = (struct sockaddr_in *)cp;
1684 + sin6_rp = (struct sockaddr_in6 *)rp;
1685 + if (IN6_IS_ADDR_V4MAPPED(&sin6_rp->sin6_addr) &&
1686 + memcmp(&sin6_rp->sin6_addr.s6_addr[12], &sin_cp->sin_addr.s_addr,
1687 + sizeof(struct in_addr)) == 0)
1693 + if (cp->__ss_family != rp->__ss_family)
1695 + if (cp->__ss_family == AF_INET) {
1696 + sin_cp = (struct sockaddr_in *)cp;
1697 + sin_rp = (struct sockaddr_in *)rp;
1698 + if (sin_cp->sin_addr.s_addr == sin_rp->sin_addr.s_addr)
1703 + } else if (cp->__ss_family == AF_INET6) {
1704 + sin6_cp = (struct sockaddr_in6 *)cp;
1705 + sin6_rp = (struct sockaddr_in6 *)rp;
1706 + if (IN6_ARE_ADDR_EQUAL(&sin6_cp->sin6_addr, &sin6_rp->sin6_addr))
1715 +int inet_prefix_match(struct sockaddr_storage *cp,
1716 + struct sockaddr_storage *rp, int prefix)
1718 + u_int_32 netmask = 0;
1719 + struct sockaddr_in *sin_cp, *sin_rp;
1720 + struct in_addr cp4, rp4;
1722 + struct sockaddr_in6 *sin6_cp, *sin6_rp;
1723 + struct in6_addr cp6, rp6;
1725 + if (cp->__ss_family == AF_INET6 && rp->__ss_family == AF_INET) {
1726 + sin6_cp = (struct sockaddr_in6 *)cp;
1727 + sin_rp = (struct sockaddr_in *)rp;
1728 + if (IN6_IS_ADDR_V4MAPPED(&sin6_cp->sin6_addr)) {
1729 + if (prefix > 32) prefix = 32;
1730 + while (prefix--) { netmask >>= 1; netmask |= 0x80000000; }
1731 + cp4.s_addr = ntohl(sin6_cp->sin6_addr.s6_addr32[3]) & netmask;
1732 + rp4.s_addr = ntohl(sin_rp->sin_addr.s_addr) & netmask;
1733 + if (cp4.s_addr == rp4.s_addr)
1739 + } else if (cp->__ss_family == AF_INET && rp->__ss_family == AF_INET6) {
1740 + sin_cp = (struct sockaddr_in *)cp;
1741 + sin6_rp = (struct sockaddr_in6 *)rp;
1742 + if (IN6_IS_ADDR_V4MAPPED(&sin6_rp->sin6_addr)) {
1743 + if (prefix > 32) prefix = 32;
1744 + while (prefix--) { netmask >>= 1; netmask |= 0x80000000; }
1745 + cp4.s_addr = ntohl(sin_cp->sin_addr.s_addr) & netmask;
1746 + rp4.s_addr = ntohl(sin6_rp->sin6_addr.s6_addr32[3]) & netmask;
1747 + if (cp4.s_addr == rp4.s_addr)
1755 + if (cp->__ss_family != rp->__ss_family)
1757 + if (cp->__ss_family == AF_INET) {
1758 + if (prefix > 32) prefix = 32;
1759 + while (prefix--) { netmask >>= 1; netmask |= 0x80000000; }
1760 + cp4.s_addr = ntohl(((struct sockaddr_in *)cp)->sin_addr.s_addr) & netmask;
1761 + rp4.s_addr = ntohl(((struct sockaddr_in *)rp)->sin_addr.s_addr) & netmask;
1762 + if (cp4.s_addr == rp4.s_addr)
1767 + } else if (cp->__ss_family == AF_INET6) {
1770 + memcpy(&cp6, &((struct sockaddr_in6 *)cp)->sin6_addr, sizeof(struct in6_addr));
1771 + memcpy(&rp6, &((struct sockaddr_in6 *)rp)->sin6_addr, sizeof(struct in6_addr));
1772 + for (i=0; i<4; i++) {
1774 + while (prefix && j++<32) { prefix--; netmask >>= 1; netmask |= 0x80000000; }
1775 + cp6.s6_addr32[i] &= htonl(netmask);
1776 + rp6.s6_addr32[i] &= htonl(netmask);
1778 + if (IN6_ARE_ADDR_EQUAL(&cp6, &rp6))
1787 /* Perform reverse ip dns resolution on an existing
1790 @@ -1234,7 +1439,7 @@
1791 c->remote_name = inet_getname(c->pool,c->remote_ipaddr);
1794 - c->remote_name = pstrdup(c->pool,inet_ntoa(*c->remote_ipaddr));
1795 + c->remote_name = pstrdup(c->pool,INET_NTOA(c->remote_ipaddr));
1799 diff -urN proftpd-1.2.5/src/intoa.c proftpd-1.2.5.v6/src/intoa.c
1800 --- proftpd-1.2.5/src/intoa.c Thu Jan 1 01:00:00 1970
1801 +++ proftpd-1.2.5.v6/src/intoa.c Thu Aug 8 21:35:24 2002
1804 + * ProFTPD - FTP server daemon
1805 + * Copyright (c) 1997, 1998 Public Flood Software
1806 + * Copyright (C) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver@tos.net>
1808 + * This program is free software; you can redistribute it and/or modify
1809 + * it under the terms of the GNU General Public License as published by
1810 + * the Free Software Foundation; either version 2 of the License, or
1811 + * (at your option) any later version.
1813 + * This program is distributed in the hope that it will be useful,
1814 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1815 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1816 + * GNU General Public License for more details.
1818 + * You should have received a copy of the GNU General Public License
1819 + * along with this program; if not, write to the Free Software
1820 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
1824 + * Inet support functions, many wrappers for netdb functions
1832 +char *INET_NTOA(struct sockaddr_storage *ss)
1834 + static char buf[1024];
1836 + if (getnameinfo((struct sockaddr *)ss, sizeof(struct sockaddr_storage),
1837 + buf, sizeof(buf), NULL, 0, NI_NUMERICHOST))
1838 + strcpy(buf, "0.0.0.0");
1843 diff -urN proftpd-1.2.5/src/log.c proftpd-1.2.5.v6/src/log.c
1844 --- proftpd-1.2.5/src/log.c Tue May 21 22:47:22 2002
1845 +++ proftpd-1.2.5.v6/src/log.c Thu Aug 8 21:35:24 2002
1846 @@ -434,12 +434,12 @@
1850 -void log_run_address(const char *remote_name, const p_in_addr_t *remote_ipaddr)
1851 +void log_run_address(const char *remote_name, const struct sockaddr_storage *remote_ipaddr)
1853 char buf[LOGBUFFER_SIZE] = {'\0'};
1855 snprintf(buf, sizeof(buf), "%s [%s]",
1856 - remote_name, inet_ntoa(*remote_ipaddr));
1857 + remote_name, INET_NTOA((struct sockaddr_storage *)remote_ipaddr));
1858 buf[sizeof(buf) - 1] = '\0';
1859 address = pstrdup(permanent_pool,buf);
1864 int log_add_run(pid_t mpid, time_t *idle_since, char *user,char *class,
1865 - p_in_addr_t *server_ip, unsigned short server_port,
1866 + struct sockaddr_storage *server_ip, unsigned short server_port,
1867 unsigned long tx_size, unsigned long tx_done, char *op, ...)
1871 * but I haven't been able to test them.
1874 -int log_wtmp(char *line, char *name, char *host, p_in_addr_t *ip)
1875 +int log_wtmp(char *line, char *name, char *host, struct sockaddr_storage *ip)
1879 @@ -657,8 +657,14 @@
1880 memset(&ut,0,sizeof(ut));
1881 #ifdef HAVE_UTMAXTYPE
1884 - memcpy(&ut.ut_addr,ip,sizeof(ut.ut_addr));
1887 + if (ip->__ss_family == AF_INET6)
1888 + memcpy(&ut.ut_addr_v6,&((struct sockaddr_in6 *)ip)->sin6_addr,sizeof(ut.ut_addr_v6));
1891 + memcpy(&ut.ut_addr,&((struct sockaddr_in *)ip)->sin_addr,sizeof(ut.ut_addr));
1894 sstrncpy(ut.ut_id,"ftp",sizeof(ut.ut_id));
1895 ut.ut_exit.e_termination = 0;
1897 if(session.c && session.c->remote_name) {
1898 snprintf(serverinfo + strlen(serverinfo),
1899 sizeof(serverinfo) - strlen(serverinfo), " (%s[%s])",
1900 - session.c->remote_name, inet_ntoa(*session.c->remote_ipaddr));
1901 + session.c->remote_name, INET_NTOA(session.c->remote_ipaddr));
1902 serverinfo[sizeof(serverinfo) - 1] = '\0';
1905 diff -urN proftpd-1.2.5/src/main.c proftpd-1.2.5.v6/src/main.c
1906 --- proftpd-1.2.5/src/main.c Tue May 21 22:47:23 2002
1907 +++ proftpd-1.2.5.v6/src/main.c Thu Aug 8 21:35:24 2002
1909 struct _binding *next;
1911 server_rec *server; /* server to handle request */
1912 - p_in_addr_t ipaddr; /* ip address "bound" to */
1913 + struct sockaddr_storage ipaddr; /* ip address "bound" to */
1915 conn_t *listen; /* listen connection (if separate) */
1916 char isdefault; /* if default connection */
1917 @@ -158,17 +158,17 @@
1919 char *config_filename = CONFIG_FILE_PATH;
1921 -int add_binding(server_rec *server, p_in_addr_t *ipaddr, conn_t *listen,
1922 +int add_binding(server_rec *server, struct sockaddr_storage *ipaddr, conn_t *listen,
1923 char isdefault, char islocalhost)
1927 for(b = bind_list; b; b=b->next)
1928 - if(b->ipaddr.s_addr == ipaddr->s_addr &&
1929 + if(inet_address_match(&b->ipaddr, ipaddr) &&
1930 b->port == server->ServerPort) {
1931 /* binding already exists for this IP */
1932 log_pri(LOG_NOTICE,"cannot bind %s:%d to server '%s', already bound to '%s'.",
1933 - inet_ntoa(*ipaddr),server->ServerPort,
1934 + INET_NTOA(ipaddr),server->ServerPort,
1935 server->ServerName,b->server->ServerName);
1939 b = palloc(bind_pool,sizeof(binding_t));
1941 b->port = server->ServerPort;
1942 - b->ipaddr = *ipaddr;
1943 + memcpy(&b->ipaddr, ipaddr, sizeof(struct sockaddr_storage));
1945 b->isdefault = isdefault;
1946 b->islocalhost = islocalhost;
1947 @@ -190,12 +190,12 @@
1951 -server_rec *find_binding(p_in_addr_t *ipaddr, int port)
1952 +server_rec *find_binding(struct sockaddr_storage *ipaddr, int port)
1954 binding_t *b,*local_b = NULL,*default_b = NULL;
1956 for(b = bind_list; b; b=b->next) {
1957 - if(b->ipaddr.s_addr == ipaddr->s_addr && (!b->port || b->port == port))
1958 + if(inet_address_match(&b->ipaddr, ipaddr) && (!b->port || b->port == port))
1962 @@ -206,20 +206,20 @@
1964 /* Not found in binding list, so see if it's the loopback address */
1966 - p_in_addr_t loopback,loopmask,tmp;
1968 -#ifdef HAVE_INET_ATON
1969 - inet_aton(LOOPBACK_NET,&loopback);
1970 - inet_aton(LOOPBACK_MASK,&loopmask);
1972 - loopback.s_addr = inet_addr(LOOPBACK_NET);
1973 - loopmask.s_addr = inet_addr(LOOPBACK_MASK);
1974 + struct sockaddr_storage loopback;
1975 + struct sockaddr_in *loopback4 = (struct sockaddr_in *)&loopback;
1977 + struct sockaddr_in6 *loopback6 = (struct sockaddr_in6 *)&loopback;
1979 + loopback.__ss_family = AF_INET6;
1980 + memcpy(&loopback6->sin6_addr, &in6addr_loopback, sizeof(struct in6_addr));
1981 + if(inet_address_match(ipaddr, (struct sockaddr_storage *)&loopback) &&
1982 + (!local_b->port || port == local_b->port))
1983 + return local_b->server;
1985 - loopback.s_addr = ntohl(loopback.s_addr);
1986 - loopmask.s_addr = ntohl(loopmask.s_addr);
1987 - tmp.s_addr = ntohl(ipaddr->s_addr);
1989 - if((tmp.s_addr & loopmask.s_addr) == loopback.s_addr &&
1990 + loopback.__ss_family = AF_INET;
1991 + loopback4->sin_addr.s_addr = INADDR_LOOPBACK;
1992 + if(inet_address_match(ipaddr, (struct sockaddr_storage *)&loopback) &&
1993 (!local_b->port || port == local_b->port))
1994 return local_b->server;
1997 if ((c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress",
2000 - p_in_addr_t *masq_addr = (p_in_addr_t *) c->argv[0];
2001 - serveraddress = pstrdup(main_server->pool, inet_ntoa(*masq_addr));
2002 + struct sockaddr_storage *masq_addr = (struct sockaddr_storage *) c->argv[0];
2003 + serveraddress = pstrdup(main_server->pool, INET_NTOA(masq_addr));
2009 set_proc_title("proftpd: connected: %s (%s:%d)",
2010 c->remote_name ? c->remote_name : "?",
2011 - c->remote_ipaddr ? inet_ntoa(*c->remote_ipaddr) : "?",
2012 + c->remote_ipaddr ? INET_NTOA(c->remote_ipaddr) : "?",
2013 c->remote_port ? c->remote_port : 0
2018 if ((masq_c = find_config(server->conf, CONF_PARAM, "MasqueradeAddress",
2020 - p_in_addr_t *masq_addr = (p_in_addr_t *) masq_c->argv[0];
2021 - serveraddress = pstrdup(server->pool, inet_ntoa(*masq_addr));
2022 + struct sockaddr_storage *masq_addr = (struct sockaddr_storage *) masq_c->argv[0];
2023 + serveraddress = pstrdup(server->pool, INET_NTOA(masq_addr));
2026 display = (char*)get_param_ptr(server->conf,"DisplayConnect",FALSE);
2027 @@ -1482,8 +1482,8 @@
2028 if ((c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress",
2031 - p_in_addr_t *masq_addr = (p_in_addr_t *) c->argv[0];
2032 - serveraddress = pstrdup(main_server->pool, inet_ntoa(*masq_addr));
2033 + struct sockaddr_storage *masq_addr = (struct sockaddr_storage *) c->argv[0];
2034 + serveraddress = pstrdup(main_server->pool, INET_NTOA(masq_addr));
2037 reason = sreplace(permanent_pool,shutmsg,
2038 @@ -1501,7 +1501,7 @@
2040 log_auth(LOG_NOTICE, "connection refused (%s) from %s [%s]",
2041 reason, session.c->remote_name,
2042 - inet_ntoa(*session.c->remote_ipaddr));
2043 + INET_NTOA(session.c->remote_ipaddr));
2045 send_response(R_500,
2046 "FTP server shut down (%s) -- please try again later.",
2047 @@ -1532,7 +1532,7 @@
2048 /* Check config tree for <Limit LOGIN> directives */
2049 if(!login_check_limits(serv->conf,TRUE,FALSE,&i)) {
2050 log_pri(LOG_NOTICE,"Connection from %s [%s] denied.",
2051 - session.c->remote_name,inet_ntoa(*session.c->remote_ipaddr));
2052 + session.c->remote_name,INET_NTOA(session.c->remote_ipaddr));
2056 @@ -1563,10 +1563,10 @@
2057 init_child_modules();
2059 log_debug(DEBUG4,"connected - local : %s:%d",
2060 - inet_ntoa(*session.c->local_ipaddr),
2061 + INET_NTOA(session.c->local_ipaddr),
2062 session.c->local_port);
2063 log_debug(DEBUG4,"connected - remote : %s:%d",
2064 - inet_ntoa(*session.c->remote_ipaddr),
2065 + INET_NTOA(session.c->remote_ipaddr),
2066 session.c->remote_port);
2068 /* xfer_set_data_port(conn->local_ipaddr,conn->local_port-1); */
2069 @@ -2172,7 +2172,7 @@
2073 - p_in_addr_t *ipaddr;
2074 + struct sockaddr_storage *ipaddr;
2076 c = find_config(s->conf,CONF_PARAM,"Bind",FALSE);
2078 diff -urN proftpd-1.2.5/src/support.c proftpd-1.2.5.v6/src/support.c
2079 --- proftpd-1.2.5/src/support.c Tue May 21 22:47:23 2002
2080 +++ proftpd-1.2.5.v6/src/support.c Thu Aug 8 21:35:24 2002
2081 @@ -902,3 +902,22 @@
2086 +/* convert IPv4-mapped to real IPv4 struct */
2087 +void mappedtov4( struct sockaddr_storage *ss )
2089 + struct sockaddr_in sin;
2090 + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ss;
2091 + if (ss->__ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ) {
2092 + memcpy(&sin.sin_addr, sin6->sin6_addr.s6_addr+12,
2093 + sizeof(sin.sin_addr));
2094 + sin.sin_port = ((struct sockaddr_in6 *)ss)->sin6_port;
2095 + sin.sin_family = AF_INET;
2097 + sin.sin_len = sizeof(struct sockaddr_in);
2099 + memset(ss, 0, sizeof(struct sockaddr_storage));
2100 + memcpy(ss, &sin, sizeof(sin));