]> git.pld-linux.org Git - packages/proftpd.git/blame - proftpd-IPv6.patch
- updated to 1.2.10rc3
[packages/proftpd.git] / proftpd-IPv6.patch
CommitLineData
1a8ebc7c
TO
1diff -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
4@@ -56,18 +56,18 @@
5
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 \
14- src/mkhome.o
15+ src/mkhome.o src/intoa.o
16
17 MODULE_OBJS=@MODULE_OBJS@
18 BUILD_MODULE_OBJS=@BUILD_MODULE_OBJS@ modules/module_glue.o
19
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
24
25 FTPSHUT_OBJS=ftpshut.o
26 BUILD_FTPSHUT_OBJS=utils/ftpshut.o
27@@ -75,5 +75,5 @@
28 FTPTOP_OBJS=ftptop.o scoreboard.o
29 BUILD_FTPTOP_OBJS=utils/ftptop.o utils/scoreboard.o
30
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
35diff -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
38@@ -0,0 +1,23 @@
39+FTP Daemon with IPv6 support for PLD GNU/Linux (http://www.pld.org.pl/)
40+
41+IPv6 port by Jan Rekorajski <baggins@pld.org.pl>
42+Note from me:
43+Proftpd program is an example of How NOT To write networking code.
44+
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
52+
53+Config:
54+If you want to specify IPv6 addres, you may use '[' ']'
55+notation ([::1] for example).
56+
57+Known Bugs:
58+- none known
59+
60+Todo:
61+- test fully VirtualHosts and IPv4 <-> IPv6 interoperability
62diff -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
65@@ -80,6 +80,13 @@
66 * configure should, we hope <wink>, detect this for you.
67 */
68 #undef PF_ARGV_TYPE
69+
70+/* Define if you want IPv6 support */
71+#undef INET6
72+
73+/* Define if you have ss_family field in struct sockaddr_storage */
74+#undef HAVE_SS_FAMILY_IN_SS
75+
76 @TOP@
77
78 /* autoheader generated things inserted here. */
79diff -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
82@@ -82,6 +82,13 @@
83 */
84 #undef PF_ARGV_TYPE
85
86+/* Define if you want IPv6 support */
87+#undef INET6
88+
89+/* Define if you have ss_family field in struct sockaddr_storage */
90+#undef HAVE_SS_FAMILY_IN_SS
91+
92+
93 /* Define if using alloca.c. */
94 #undef C_ALLOCA
95
96diff -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
99@@ -520,6 +520,45 @@
100 esac
101 fi
102
103+dnl === part for IPv6 support ===
104+AC_MSG_CHECKING([whether to enable ipv6])
105+AC_ARG_ENABLE(ipv6,
106+[ --enable-ipv6 Enable ipv6 support
107+ --disable-ipv6 Disable ipv6 support],
108+[case "$enableval" in
109+ no) AC_MSG_RESULT(no)
110+ ;;
111+ *) AC_MSG_RESULT(yes)
112+ AC_DEFINE(INET6)
113+ CFLAGS="$CFLAGS -DINET6"
114+ ;;
115+esac],
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)
121+ AC_DEFINE(INET6)
122+],[ AC_MSG_RESULT(no)
123+],[ AC_MSG_RESULT(unknown)
124+]))
125+AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage],
126+ ac_cv_have_ss_family_in_struct_ss, [
127+ AC_TRY_COMPILE(
128+ [
129+#include <sys/types.h>
130+#include <sys/socket.h>
131+ ],
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" ],
135+ )
136+])
137+if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then
138+ AC_DEFINE(HAVE_SS_FAMILY_IN_SS)
139+fi
140+dnl === end of part for IPv6 support ===
141+
142 dnl Check for various argv[] replacing functions on various OSs
143 AC_CHECK_FUNCS(setproctitle)
144 AC_CHECK_HEADERS(libutil.h)
145diff -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
148@@ -224,8 +224,6 @@
149 {
150 modret_t *mr = 0;
151 config_rec *c;
152- char buf[1024] = {'\0'};
153- char *mask;
154 char **data;
155
156 if (!(g.enable = get_param_int (main_server->conf, "Ratios", FALSE) == TRUE))
157@@ -256,23 +254,7 @@
158 c = find_config (main_server->conf, CONF_PARAM, "HostRatio", TRUE);
159 while (c)
160 {
161- mask = buf;
162- if (*(char *) c->argv[0] == '.')
163- {
164- *mask++ = '*';
165- sstrncpy (mask, c->argv[0], sizeof (buf));
166- }
167- else if (*(char *) ((char *) c->argv[0] + (strlen (c->argv[0]) - 1)) == '.')
168- {
169- sstrncpy (mask, c->argv[0], sizeof(buf) - 2);
170- sstrcat(buf, "*", sizeof(buf));
171- }
172- else
173- sstrncpy (mask, c->argv[0], sizeof (buf));
174-
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]))
179 {
180 _set_ratios (c->argv[1], c->argv[2], c->argv[3], c->argv[4]);
181 g.rtype = "h";
182@@ -436,7 +418,7 @@
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);
188 }
189 return DECLINED (cmd);
190 }
191diff -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 @@
195 break;
196 case 'a':
197 argp = arg;
198- sstrncpy(argp, inet_ntoa(*session.c->remote_ipaddr), sizeof(arg));
199+ sstrncpy(argp, INET_NTOA(session.c->remote_ipaddr), sizeof(arg));
200 break;
201 case 'l':
202 argp = arg;
203diff -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
206@@ -322,8 +322,6 @@
207
208 /* Generic typedefs */
209
210-typedef struct in_addr p_in_addr_t;
211-
212 #include "pool.h"
213 #include "regexp.h"
214 #include "proftpd.h"
215@@ -357,4 +355,8 @@
216
217 #endif /* __PROFTPD_SUPPORT_LIBRARY */
218
219+#ifdef HAVE_SS_FAMILY_IN_SS
220+#define __ss_family ss_family
221+#endif
222+
223 #endif /* PR_CONF_H */
224diff -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
227@@ -59,7 +59,7 @@
228
229 int AnonymousGreeting; /* Do not greet until after user login */
230
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 */
235
236@@ -201,7 +201,7 @@
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 *);
242
243 array_header *parse_group_expression(pool *, int *, char **);
244 array_header *parse_user_expression(pool *, int *, char **);
245@@ -236,6 +236,6 @@
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 *);
251
252 #endif /* __DIRTREE_H */
253diff -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
256@@ -85,6 +85,8 @@
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 */
262
263 #define C_ANY "*" /* Special "wildcard" matching command */
264
265@@ -113,6 +115,7 @@
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 */
273@@ -138,6 +141,7 @@
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 */
281diff -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
284@@ -69,9 +69,9 @@
285 int rfd,wfd; /* Read and write fds */
286 pr_netio_stream_t *instrm, *outstrm; /* Input/Output streams */
287
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 */
295 } conn_t;
296@@ -85,14 +85,16 @@
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*);
307+#if 0
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 *,
312+#endif
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 *,
316 int, int);
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);
337+#ifdef INET6
338+char *INET_NTOA(struct sockaddr_storage *ss);
339+#else
340+#define INET_NTOA(a) inet_ntoa(((struct sockaddr_in *)(a))->sin_addr)
341+#endif
342
343 #endif /* PR_INET_H */
344diff -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
347@@ -66,7 +66,7 @@
348 #define LOG_XFER_MODE 0644
349
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 *);
356diff -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
359@@ -71,8 +71,8 @@
360 typedef struct cdir_struc {
361 struct cdir_struc *next;
362
363- u_int_32 address;
364- u_int_32 netmask;
365+ struct sockaddr_storage address;
366+ u_int_32 prefix;
367 class_t *class;
368 } cdir_t;
369
370@@ -94,7 +94,7 @@
371 volatile int sf_flags; /* Session/State flags */
372 volatile int sp_flags; /* Session/Protection flags */
373
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 */
377
378 unsigned char ident_lookups; /* Is RFC931 (ident) protocol used? */
379@@ -210,9 +210,11 @@
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 */
384
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| \
388+ SF_EPSV_ALL)
389
390 /* Session/Protection flags (RFC 2228) */
391
392diff -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
395@@ -98,4 +98,6 @@
396 char *sstrncpy(char *, const char *, size_t);
397 char *sreplace(pool *, char *, ...);
398
399+void mappedtov4(struct sockaddr_storage *);
400+
401 #endif /* PR_SUPPORT_H */
402diff -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 @@
406 PRIVS_ROOT
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) {
412
413 cur++;
414@@ -1270,11 +1270,11 @@
415
416 /* Make sure it matches our current server.
417 */
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)) ||
422 !c) {
423- char *s, *d, ip[32] = {'\0'};
424+ char *s, *d, ip[64] = {'\0'};
425 int mpos = sizeof(ip) - 1;
426
427 cur++;
428@@ -1292,7 +1292,7 @@
429
430 /* Count up sessions on a per-host basis.
431 */
432- if(!strcmp(ip, inet_ntoa(*session.c->remote_ipaddr))) {
433+ if(!strcmp(ip, INET_NTOA(session.c->remote_ipaddr))) {
434 samehost++;
435 hcur++;
436 }
437diff -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
440@@ -63,6 +63,8 @@
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 },
449@@ -401,7 +403,7 @@
450
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'};
456
457 CHECK_ARGS(cmd, 1);
458@@ -2029,7 +2031,7 @@
459
460 if ((c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress",
461 FALSE)) != NULL) {
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);
465 }
466
467@@ -2191,7 +2193,7 @@
468 MODRET cmd_pasv(cmd_rec *cmd)
469 {
470 union {
471- p_in_addr_t addr;
472+ struct in_addr addr;
473 unsigned char u[4];
474 } addr;
475
476@@ -2203,8 +2205,16 @@
477 config_rec *c = NULL;
478 int pasv_min_port,pasv_max_port;
479
480+ if (session.flags & SF_EPSV_ALL)
481+ return ERROR_MSG(cmd,R_500,"Illegal PASV command - EPSV ALL requested before.");
482+
483 CHECK_CMD_ARGS(cmd, 1);
484
485+#ifdef INET6
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.");
488+#endif
489+
490 /* If we already have a passive listen data connection open, kill it.
491 */
492 if(session.d) {
493@@ -2250,14 +2260,16 @@
494 session.data_port = session.d->local_port;
495 session.flags |= SF_PASSIVE;
496
497- addr.addr = *session.d->local_ipaddr;
498+ addr.addr.s_addr = ((struct sockaddr_in *)session.d->local_ipaddr)->sin_addr.s_addr;
499
500 /* check for a MasqueradeAddress configuration record, and return that
501 * addr if appropriate.
502 */
503 if ((c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress",
504- FALSE)) != NULL)
505- addr.addr = *((p_in_addr_t *) c->argv[0]);
506+ FALSE)) != NULL) {
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;
509+ }
510
511 port.port = htons(session.data_port);
512
513@@ -2275,7 +2287,7 @@
514 MODRET cmd_port(cmd_rec *cmd)
515 {
516 union {
517- p_in_addr_t addr;
518+ struct in_addr addr;
519 unsigned char u[4];
520 } addr;
521
522@@ -2285,11 +2297,19 @@
523 } port;
524
525 char *a,*endp,*arg;
526- int i,cnt = 0;
527+ int p,i,cnt = 0;
528 int allow_foreign_addr = 0;
529
530+ if (session.flags & SF_EPSV_ALL)
531+ return ERROR_MSG(cmd,R_500,"Illegal PORT command - EPSV ALL requested before.");
532+
533 CHECK_CMD_ARGS(cmd, 2);
534
535+#ifdef INET6
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.");
538+#endif
539+
540 /* Format is h1,h2,h3,h4,p1,p2 (ASCII in network order) */
541 a = pstrdup(cmd->tmp_pool,cmd->argv[1]);
542
543@@ -2322,8 +2342,10 @@
544 allow_foreign_addr = get_param_int(TOPLEVEL_CONF,"AllowForeignAddress",FALSE);
545
546 if(allow_foreign_addr != 1) {
547- if(addr.addr.s_addr != session.c->remote_ipaddr->s_addr ||
548- !port.port) {
549+
550+ p = ((struct sockaddr_in *)session.c->remote_ipaddr)->sin_addr.s_addr;
551+
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.");
555 }
556@@ -2338,7 +2360,9 @@
557 return ERROR_MSG(cmd,R_500,"Illegal PORT command.");
558 }
559
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);
566
567@@ -2355,6 +2379,207 @@
568 return HANDLED(cmd);
569 }
570
571+MODRET cmd_epsv(cmd_rec *cmd)
572+{
573+ char *endp,*arg;
574+ int family;
575+ config_rec *c = NULL;
576+ int pasv_min_port,pasv_max_port;
577+
578+ CHECK_CMD_MIN_ARGS(cmd, 1);
579+
580+ arg = pstrdup(cmd->tmp_pool,cmd->argv[1]);
581+
582+ if (arg) {
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);
587+ } else {
588+ family = strtol(arg, &endp, 10);
589+ if (family == 1) {
590+#ifdef INET6
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.");
593+#endif
594+ } else if (family == 2) {
595+#ifdef INET6
596+ if (!(session.c->local_ipaddr->__ss_family == AF_INET6))
597+#endif
598+ return ERROR_MSG(cmd,R_522,"Illegal EPSV command - IPv6 not supported over this link.");
599+ } else {
600+ return ERROR_MSG(cmd,R_522,"Illegal EPSV command - unknown network protocol.");
601+ }
602+ }
603+ }
604+
605+ /* If we already have a passive listen data connection open,
606+ * kill it.
607+ */
608+
609+ if(session.d) {
610+ inet_close(session.d->pool,session.d);
611+ session.d = NULL;
612+ }
613+
614+ if ((c = find_config(main_server->conf, CONF_PARAM, "PassivePorts", FALSE)) !=
615+ NULL) {
616+ pasv_min_port = (int)c->argv[0];
617+ pasv_max_port = (int)c->argv[1];
618+
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.
625+ */
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);
628+ }
629+ }
630+
631+
632+ /* Open up the connection and pass it back.
633+ */
634+ if (!session.d)
635+ session.d = inet_create_connection(session.pool, NULL, -1,
636+ session.c->local_ipaddr,
637+ INPORT_ANY, FALSE);
638+
639+ if(!session.d)
640+ return ERROR_MSG(cmd,R_425,
641+ "Unable to build data connection: Internal error.");
642+
643+ inet_setblock(session.pool,session.d);
644+ inet_listen(session.pool,session.d,1);
645+
646+ session.d->inf = io_open(session.pool,session.d->listen_fd,IO_READ);
647+
648+ /* Now tell the client our address/port */
649+ session.data_port = session.d->local_port;
650+ session.flags |= SF_PASSIVE;
651+
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);
654+
655+ return HANDLED(cmd);
656+}
657+
658+MODRET cmd_eprt(cmd_rec *cmd)
659+{
660+ struct sockaddr_storage addr;
661+ unsigned short port = 0;
662+ char *a,*endp,*arg;
663+ char delim[2];
664+ int family,i,cnt = 0;
665+ int allow_foreign_addr = 0;
666+
667+ if (session.flags & SF_EPSV_ALL)
668+ return ERROR_MSG(cmd,R_500,"Illegal EPRT command - EPSV ALL requested before.");
669+
670+ CHECK_CMD_ARGS(cmd, 2);
671+
672+ bzero(&addr, sizeof(struct sockaddr_storage));
673+
674+ /* Format is <d>proto<d>ip address<d>port<d> (ASCII in network order) */
675+ a = pstrdup(cmd->tmp_pool,cmd->argv[1]);
676+
677+ delim[0] = *a++;
678+ delim[1] = '\0';
679+
680+ family = strtol(a, &endp, 10);
681+ if (family == 1)
682+ addr.__ss_family = AF_INET;
683+#ifdef INET6
684+ else if (family == 2)
685+ addr.__ss_family = AF_INET6;
686+#endif
687+ else
688+ return ERROR_MSG(cmd,R_522,"Illegal EPRT command - unknown network protocol.");
689+
690+ if (!*endp)
691+ return ERROR_MSG(cmd,R_501,"Illegal EPRT command.");
692+
693+ a = ++endp;
694+
695+ while(a && *a && cnt < 2) {
696+ arg = strsep(&a,delim);
697+
698+ if(!arg && a && *a) {
699+ arg = a;
700+ a = NULL;
701+ } else if(!arg)
702+ break;
703+
704+ if (cnt == 0) {
705+ i = 0;
706+ if (family == 1)
707+ i = inet_pton(AF_INET, arg, &((struct sockaddr_in *)&addr)->sin_addr);
708+#ifdef INET6
709+ else
710+ i = inet_pton(AF_INET6, arg, &((struct sockaddr_in6 *)&addr)->sin6_addr);
711+#endif
712+ if (i == 0)
713+ break;
714+ } else if (cnt == 1) {
715+ i = strtol(arg,&endp,10);
716+ if(*endp || i < 1)
717+ break;
718+ port = (unsigned short)i;
719+ if (family == 1)
720+ ((struct sockaddr_in *)&addr)->sin_port = htons(port);
721+#ifdef INET6
722+ else
723+ ((struct sockaddr_in6 *)&addr)->sin6_port = htons(port);
724+#endif
725+ } else
726+ break;
727+ cnt++;
728+ }
729+
730+ if(cnt != 2 || (a && *a))
731+ return ERROR_MSG(cmd,R_501,"Illegal EPRT command.");
732+
733+ /* Make sure that the address specified matches the address
734+ * that the control connection is coming from.
735+ */
736+
737+ allow_foreign_addr = get_param_int(TOPLEVEL_CONF,"AllowForeignAddress",FALSE);
738+
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.");
743+ }
744+ }
745+
746+ /* Additionally, make sure that the port number used is a "high
747+ * numbered" port, to avoid bounce attacks
748+ */
749+
750+ if(port < 1024) {
751+ log_pri(LOG_WARNING, "Refused EPRT %s (bounce attack).", cmd->arg);
752+ return ERROR_MSG(cmd,R_500,"Illegal EPRT command.");
753+ }
754+
755+ memcpy(&session.data_addr, &addr, sizeof(struct sockaddr_storage));
756+ session.data_port = port;
757+ session.flags &= (SF_ALL^SF_PASSIVE);
758+
759+ /* If we already have a data connection open, kill it.
760+ */
761+
762+ if(session.d) {
763+ inet_close(session.d->pool,session.d);
764+ session.d = NULL;
765+ }
766+
767+ session.flags |= SF_PORT;
768+ add_response(R_200,"EPRT command successful.");
769+ return HANDLED(cmd);
770+}
771+
772 MODRET cmd_help(cmd_rec *cmd)
773 {
774 int i,c = 0;
775@@ -3044,18 +3269,15 @@
776 return NULL;
777 }
778
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)
781 {
782 cdir_t *n;
783
784 n = calloc(1, sizeof(cdir_t));
785
786 n->class = class;
787- while (netmask--) {
788- n->netmask >>= 1;
789- n->netmask |= 0x80000000;
790- }
791- n->address = address & n->netmask;
792+ n->prefix = prefix;
793+ memcpy(&n->address, address, sizeof(struct sockaddr_storage));
794
795 n->next = cdir_list;
796 cdir_list = n;
797@@ -3063,7 +3285,7 @@
798 return n;
799 }
800
801-static cdir_t *find_cdir(u_int_32 address)
802+static cdir_t *find_cdir(struct sockaddr_storage *address)
803 {
804 cdir_t *c, *f;
805
806@@ -3071,7 +3293,8 @@
807 f = NULL;
808 while (c) {
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))))
813 f = c;
814
815 c = c->next;
816@@ -3108,18 +3331,18 @@
817 return NULL;
818 }
819
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)
822 {
823 cdir_t *ip;
824 hostname_t *host;
825 class_t *c, *f;
826
827- if ((ip = find_cdir(ntohl(addr->s_addr))) != NULL)
828+ if ((ip = find_cdir(addr)) != NULL)
829 return ip->class;
830
831 if ((host = find_hostname(remote_name)) != NULL)
832 return host->class;
833- if ((host = find_hostname(inet_ntoa(*addr))) != NULL)
834+ if ((host = find_hostname(INET_NTOA(addr))) != NULL)
835 return host->class;
836
837 c = class_list;
838@@ -3140,8 +3363,8 @@
839 {
840 int bits, ret;
841 class_t *n;
842- p_in_addr_t *res;
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)
847 regex_t *preg;
848 #endif
849@@ -3197,19 +3420,28 @@
850 CONF_ERROR(cmd, "wrong syntax error.");
851 } else {
852 bits = atol(ptr + 1);
853-
854+#ifdef INET6
855+ if (bits < 0 || bits > 128) {
856+#else
857 if (bits < 0 || bits > 32) {
858+#endif
859 log_pri(LOG_ERR, "Class '%s' ipmask %s skipped: wrong netmask.",
860 cmd->argv[1], cmd->argv[3]);
861 }
862
863 *ptr = 0;
864 }
865+
866+ if ((ptr = strchr(ipaddress, '[')) && (ptrr = strrchr(ipaddress, ']'))) {
867+ ptr++;
868+ *ptrr = 0;
869+ } else
870+ ptr = ipaddress;
871
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);
880 } else {
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 },
885 #endif
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 },
892diff -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
895@@ -537,7 +537,7 @@
896
897 case META_REMOTE_IP:
898 argp = arg;
899- sstrncpy(argp, inet_ntoa(*session.c->remote_ipaddr), sizeof(arg));
900+ sstrncpy(argp, INET_NTOA(session.c->remote_ipaddr), sizeof(arg));
901 m++;
902 break;
903
904diff -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
907@@ -230,10 +230,9 @@
908
909 if(c) {
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);
917
918 if(size) {
919 send_response(R_150,
920diff -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
925 */
926
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)
929 {
930 char buf[1024];
931- char *mask,*cp;
932- int cidr_mode = 0, cidr_bits;
933- p_in_addr_t cidr_addr;
934- u_int_32 cidr_mask = 0;
935+ char *bufptr,*cp;
936+ int netmatch = 0;
937+#ifdef INET6
938+ struct in6_addr ia6, net6;
939+#endif /* INET6 */
940
941 if(!strcasecmp(match,"ALL"))
942 return 1;
943@@ -932,55 +933,108 @@
944 return -1;
945
946 memset(buf,0,sizeof(buf));
947- mask = buf;
948+ bufptr = buf;
949
950 if(*match == '.') {
951- *mask++ = '*';
952- *mask = '\0';
953+ *bufptr++ = '*';
954+ *bufptr = '\0';
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
961- * is netmask
962- */
963- sstrncpy(buf, match, (cp-match)+1 <= sizeof(buf) ?
964- (cp-match)+1 : sizeof(buf));
965- cidr_bits = atoi(cp+1);
966-
967- if(cidr_bits > 0 && cidr_bits < 33) {
968- int shift = 32 - cidr_bits;
969-
970- cidr_mode = 1;
971- while(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)
976- return 0;
977-#else
978- cidr_addr.s_addr = inet_addr(mask);
979-#endif
980- cidr_addr.s_addr &= htonl(cidr_mask);
981- } else {
982- return 0;
983- }
984+ } else if(*match == '[' && *(match + strlen(match) - 1) == ']') {
985+ sstrcat(buf, match+1, sizeof(buf));
986+ *(bufptr + strlen(bufptr) - 1) = '\0';
987 } else {
988 sstrcat(buf, match, sizeof(buf));
989 }
990-
991- if(cidr_mode) {
992- if((addr->s_addr & htonl(cidr_mask)) == cidr_addr.s_addr)
993+ /* Now match can be one of the following:
994+ * (1) *.domain
995+ * (2) 123.456.*
996+ * (3) 123.456.0.0/16
997+ * (4) abcd:1234::
998+ * (5) abcd:1234::dead:beef
999+ * (6) abcd:1234::/32
1000+ */
1001+#ifdef INET6
1002+ if (addr->__ss_family == AF_INET6) {
1003+ cp = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr;
1004+ } else
1005+#endif
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)
1010+ return 1;
1011+
1012+ /* This will catch (4) and (5) */
1013+#ifdef INET6
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)) {
1019 return 1;
1020- } else {
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)) {
1025 return 1;
1026+ }
1027 }
1028-
1029- return 0;
1030+#endif
1031+
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
1035+ * is netmask
1036+ */
1037+ int bits, c, n;
1038+ struct in_addr ia, net;
1039+ unsigned int mask;
1040+
1041+ *cp = '\0';
1042+#ifdef INET6
1043+ if (addr->__ss_family == AF_INET6) {
1044+ ia.s_addr = INADDR_NONE;
1045+ } else
1046+#endif
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);
1056+ } else {
1057+ mask = inet_addr(cp+1);
1058+ }
1059+ if ((ia.s_addr & mask) == (net.s_addr & mask))
1060+ return 1;
1061+#ifdef INET6
1062+ } else if (inet_pton(AF_INET6, buf, &net6) == 1) {
1063+ struct sockaddr_in6 *pia6;
1064+
1065+ pia6 = (struct sockaddr_in6 *)addr;
1066+ if (strchr(cp+1, ':') == (char *)NULL) {
1067+ mask = atoi(cp+1);
1068+ n = mask / 8;
1069+ bits = mask % 8;
1070+ netmatch = 1;
1071+ for (c = 0; c < n; c++)
1072+ if (pia6->sin6_addr.s6_addr[c] != net6.s6_addr[c]) {
1073+ netmatch = 0;
1074+ break;
1075+ }
1076+ if (netmatch && bits > 0) {
1077+ if ((pia6->sin6_addr.s6_addr[c] & (0xff << (8 - bits))) !=
1078+ (net6.s6_addr[c] & (0xff << (8 - bits))))
1079+ netmatch = 0;
1080+ }
1081+ }
1082+#endif /* INET6 */
1083+ }
1084+ }
1085+ return netmatch;
1086 }
1087
1088 /* As of 1.2.0rc3, a '!' character in front of the IP address
1089@@ -2513,7 +2567,7 @@
1090 FALSE)) != NULL) {
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]));
1095 }
1096
1097 /* honor the DefaultServer directive only if SocketBindTight is not
1098@@ -2521,7 +2575,11 @@
1099 */
1100 if (get_param_int(s->conf, "DefaultServer", FALSE) == 1) {
1101 if (!SocketBindTight)
1102- s->ipaddr->s_addr = 0;
1103+#ifdef INET6
1104+ memcpy(&((struct sockaddr_in6 *)s->ipaddr)->sin6_addr, &in6addr_any, sizeof(struct in6_addr));
1105+#else
1106+ ((struct sockaddr_in *)s->ipaddr)->sin_addr = INADDR_ANY;
1107+#endif
1108 else
1109 log_pri(LOG_NOTICE,
1110 "SocketBindTight in effect, ignoring DefaultServer");
1111diff -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.
1117 */
1118- if(!isalnum(*p) && *p != '.' && *p != '-') {
1119+ if(!isalnum(*p) && *p != '.' && *p != '-'
1120+#ifdef INET6
1121+ && *p != ':'
1122+#endif
1123+ ) {
1124 /* We set it to _ because we know that's an invalid, yet safe, option
1125 * for a DNS entry.
1126 */
1127@@ -175,35 +179,31 @@
1128
1129 /* DNS/hosts lookup for a particular name
1130 */
1131-p_in_addr_t *inet_getaddr(pool *pool, char *name)
1132+struct sockaddr_storage *inet_getaddr(pool *pool, char *name)
1133 {
1134- struct hostent *host;
1135- p_in_addr_t *res;
1136+ struct addrinfo hints, *res, *res0;
1137+ struct sockaddr_storage *ss;
1138
1139- res = (p_in_addr_t*)pcalloc(pool,sizeof(p_in_addr_t));
1140+ ss = (struct sockaddr_storage*)pcalloc(pool,sizeof(struct sockaddr_storage));
1141
1142- /* Try dotted quad notation first */
1143-#ifdef HAVE_INET_ATON
1144- if(inet_aton(name,res))
1145- return res;
1146-#else
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().
1151- * <grin>
1152- */
1153- if((res->s_addr = inet_addr(name)) != -1)
1154- return res;
1155-#endif
1156+ bzero(&hints, sizeof(hints));
1157+ hints.ai_family = AF_UNSPEC;
1158+ hints.ai_socktype = SOCK_STREAM;
1159
1160- host = gethostbyname(name);
1161- if(host) {
1162- memcpy(res, host->h_addr_list[0], sizeof(p_in_addr_t));
1163- return res;
1164+ if (getaddrinfo(name, "0", &hints, &res0))
1165+ return NULL;
1166+ for (res = res0; res; res = res->ai_next) {
1167+ if (res->ai_family == AF_INET
1168+#ifdef INET6
1169+ || res->ai_family == AF_INET6
1170+#endif
1171+ ) {
1172+ memcpy(ss, res->ai_addr, res->ai_addrlen);
1173+ freeaddrinfo(res0);
1174+ return ss;
1175+ }
1176 }
1177-
1178-
1179+ freeaddrinfo(res0);
1180 return NULL;
1181 }
1182
1183@@ -211,54 +211,51 @@
1184 * memory.
1185 */
1186
1187-char *inet_ascii(pool *pool, p_in_addr_t *addr)
1188+char *inet_ascii(pool *pool, struct sockaddr_storage *ss)
1189 {
1190+ static char buf[1024];
1191 char *res = NULL;
1192
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))
1197+ return NULL;
1198+
1199+ res = pstrdup(pool,buf);
1200
1201 return res;
1202 }
1203
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)
1207 {
1208+ static char peername[1024];
1209 char *res = NULL;
1210 char **checkaddr;
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;
1215
1216 if(reverse_dns) {
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);
1221 }
1222-
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);
1229- break;
1230- }
1231- }
1232- }
1233+
1234+ if (getnameinfo((struct sockaddr *)&addr, sizeof(struct sockaddr_storage),
1235+ peername, sizeof(peername), NULL, 0, 0) == 0) {
1236+ res = pstrdup(pool, peername);
1237 }
1238 }
1239
1240 if(!res)
1241- res = pstrdup(pool, inet_ntoa(*addr));
1242+ res = pstrdup(pool, INET_NTOA(addr));
1243
1244 if(reverse_dns) {
1245 /* cache the result */
1246 if(!addr_cache)
1247- addr_cache = malloc(sizeof(p_in_addr_t));
1248+ addr_cache = malloc(sizeof(struct sockaddr_storage));
1249
1250 if(addr_cache)
1251- memcpy(addr_cache, addr, sizeof(p_in_addr_t));
1252+ memcpy(addr_cache, addr, sizeof(struct sockaddr_storage));
1253
1254 if(res_cache)
1255 free(res_cache);
1256@@ -305,12 +302,12 @@
1257 res->inf = res->outf = NULL;
1258
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;
1263 }
1264
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;
1269 }
1270
1271@@ -396,14 +393,15 @@
1272 * just for the new connection.
1273 */
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)
1279 {
1280 pool *subpool;
1281 conn_t *c;
1282 array_header *tmp;
1283 server_rec *s;
1284- struct sockaddr_in servaddr;
1285+ struct sockaddr_storage servaddr;
1286+ int family;
1287 int i,res = 0, len, one = 1, hold_errno;
1288
1289 CHECK_INET_POOL;
1290@@ -414,7 +412,7 @@
1291 /* Build the accept IPs dynamically using the inet work pool,
1292 * once built, move into the conn struc.
1293 */
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));
1298 c->pool = subpool;
1299@@ -422,9 +420,9 @@
1300 if(servers && servers->xas_list) {
1301 for(s = (server_rec *) servers->xas_list; s; s = s->next)
1302 if(s->ipaddr)
1303- *((p_in_addr_t *) push_array(tmp)) = *s->ipaddr;
1304+ memcpy(((struct sockaddr_storage*)push_array(tmp)), s->ipaddr, sizeof(struct sockaddr_storage));
1305 } else {
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));
1308 }
1309
1310 c->local_port = port;
1311@@ -436,6 +434,18 @@
1312 */
1313 if(fd == -1) {
1314
1315+ if (bind_addr)
1316+ family = bind_addr->__ss_family;
1317+ else {
1318+#ifdef INET6
1319+ if ((fd = socket(AF_INET6, SOCK_STREAM, 0)) != -1) {
1320+ close(fd);
1321+ family = AF_INET6;
1322+ } else
1323+#endif
1324+ family = AF_INET;
1325+ }
1326+
1327 /* Certain versions of Solaris apparently require us to be root
1328 * in order to create a socket inside a chroot ??
1329 */
1330@@ -461,7 +471,7 @@
1331 # endif
1332 #endif
1333
1334- fd = socket(AF_INET, SOCK_STREAM, tcp_proto);
1335+ fd = socket(family, SOCK_STREAM, tcp_proto);
1336
1337 #if defined(SOLARIS2) || defined(FREEBSD2) || defined(FREEBSD3) || \
1338 defined(FREEBSD4) || defined(__OpenBSD__) || defined(__NetBSD__) || \
1339@@ -494,15 +504,28 @@
1340
1341 memset(&servaddr, 0, sizeof(servaddr));
1342
1343- servaddr.sin_family = AF_INET;
1344-
1345 if(bind_addr)
1346- memcpy(&servaddr.sin_addr, bind_addr, sizeof(servaddr.sin_addr));
1347- else
1348- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
1349-
1350- servaddr.sin_port = htons(port);
1351+ memcpy(&servaddr, bind_addr, sizeof(struct sockaddr_storage));
1352+ else {
1353+#ifdef INET6
1354+ if (family == AF_INET6)
1355+ ((struct sockaddr_in6 *)&servaddr)->sin6_addr = in6addr_any;
1356+ else
1357+#endif
1358+ ((struct sockaddr_in *)&servaddr)->sin_addr.s_addr = htonl(INADDR_ANY);
1359+ }
1360
1361+#ifdef INET6
1362+ if (family == AF_INET6) {
1363+ ((struct sockaddr_in6 *)&servaddr)->sin6_family = AF_INET6;
1364+ ((struct sockaddr_in6 *)&servaddr)->sin6_port = htons(port);
1365+ } else
1366+#endif
1367+ {
1368+ ((struct sockaddr_in *)&servaddr)->sin_family = AF_INET;
1369+ ((struct sockaddr_in *)&servaddr)->sin_port = htons(port);
1370+ }
1371+
1372 if(port != INPORT_ANY && port < 1024) {
1373 block_signals();
1374 PRIVS_ROOT
1375@@ -549,7 +572,8 @@
1376
1377 if(reporting) {
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.");
1384 }
1385@@ -571,11 +595,16 @@
1386 */
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));
1397+#ifdef INET6
1398+ if (servaddr.__ss_family == AF_INET6)
1399+ c->local_port = ntohs(((struct sockaddr_in6 *)&servaddr)->sin6_port);
1400+ else
1401+#endif
1402+ c->local_port = ntohs(((struct sockaddr_in *)&servaddr)->sin_port);
1403 }
1404 }
1405
1406@@ -586,8 +615,8 @@
1407 }
1408
1409 conn_t *inet_create_connection(pool *p, xaset_t *servers, int fd,
1410- p_in_addr_t *bind_addr, int port,
1411- int retry_bind)
1412+ struct sockaddr_storage *bind_addr,
1413+ int port, int retry_bind)
1414 {
1415 conn_t *c = inet_initialize_connection(p, servers, fd, bind_addr,
1416 port, retry_bind, TRUE);
1417@@ -607,7 +636,8 @@
1418 */
1419
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)
1424 {
1425 int range_len, index;
1426 int *range, *ports;
1427@@ -902,20 +932,30 @@
1428 return 0;
1429 }
1430
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)
1433 {
1434- struct sockaddr_in remaddr;
1435 int ret;
1436+ struct sockaddr_storage remaddr;
1437
1438 inet_setblock(pool,c);
1439- remaddr.sin_family = AF_INET;
1440- remaddr.sin_addr = *addr;
1441- remaddr.sin_port = htons(port);
1442-
1443+ memcpy(&remaddr, addr, sizeof(struct sockaddr_storage));
1444+#ifdef INET6
1445+ if (addr->__ss_family == AF_INET6)
1446+ ((struct sockaddr_in6 *)&remaddr)->sin6_port = htons(port);
1447+ else
1448+#endif
1449+ ((struct sockaddr_in *)&remaddr)->sin_port = htons(port);
1450+
1451 c->mode = CM_CONNECT;
1452
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,
1456+#ifdef INET6
1457+ (addr->__ss_family == AF_INET) ?
1458+ sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)
1459+#else
1460+ sizeof(struct sockaddr_in)
1461+#endif
1462+ ) == -1) && errno == EINTR ) ;
1463
1464 if(ret == -1) {
1465 c->mode = CM_ERROR;
1466@@ -937,18 +977,28 @@
1467 * called once, and can then be selected for writing.
1468 */
1469
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)
1472 {
1473- struct sockaddr_in remaddr;
1474+ struct sockaddr_storage remaddr;
1475
1476 inet_setnonblock(pool,c);
1477-
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));
1482+#ifdef INET6
1483+ if (addr->__ss_family == AF_INET6)
1484+ ((struct sockaddr_in6 *)&remaddr)->sin6_port = htons(port);
1485+ else
1486+#endif
1487+ ((struct sockaddr_in *)&remaddr)->sin_port = htons(port);
1488
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,
1492+#ifdef INET6
1493+ (addr->__ss_family == AF_INET) ?
1494+ sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)
1495+#else
1496+ sizeof(struct sockaddr_in)
1497+#endif
1498+ ) == -1) {
1499 if(errno != EINPROGRESS && errno != EALREADY) {
1500 c->mode = CM_ERROR;
1501 c->xerrno = errno;
1502@@ -978,7 +1028,7 @@
1503 int inet_accept_nowait(pool *pool, conn_t *c)
1504 {
1505 int fd;
1506- struct sockaddr_in servaddr;
1507+ struct sockaddr_storage servaddr;
1508 int len = sizeof(servaddr);
1509
1510 if(c->mode == CM_LISTEN)
1511@@ -1013,7 +1063,7 @@
1512 int resolve) {
1513 conn_t *res = NULL;
1514 int newfd = -1, allow_foreign_addr = -1;
1515- struct sockaddr_in addr;
1516+ struct sockaddr_storage addr;
1517 int addrlen = sizeof(addr);
1518
1519 d->mode = CM_ACCEPT;
1520@@ -1025,10 +1075,32 @@
1521 &addrlen)) != -1) {
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);
1526+#ifdef INET6
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));
1533+ close(newfd);
1534+ continue;
1535+ }
1536+ } else
1537+#endif
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));
1544+ close(newfd);
1545+ continue;
1546+ }
1547+ } else {
1548 log_pri(LOG_NOTICE,
1549 "SECURITY VIOLATION: Passive connection from %s rejected.",
1550- inet_ntoa(addr.sin_addr));
1551+ INET_NTOA(&addr));
1552 close(newfd);
1553 continue;
1554 }
1555@@ -1047,7 +1119,7 @@
1556 }
1557
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);
1562
1563 /* Sanity check.
1564@@ -1058,21 +1130,33 @@
1565 }
1566
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);
1573-
1574+ c->local_ipaddr = (struct sockaddr_storage*)pcalloc(c->pool,sizeof(struct sockaddr_storage));
1575+ memcpy(c->local_ipaddr, &servaddr, sizeof(struct sockaddr_storage));
1576+#ifdef INET6
1577+ if (servaddr.__ss_family == AF_INET6)
1578+ c->local_port = ntohs(((struct sockaddr_in6 *)&servaddr)->sin6_port);
1579+ else
1580+#endif
1581+ if (servaddr.__ss_family == AF_INET)
1582+ c->local_port = ntohs(((struct sockaddr_in *)&servaddr)->sin_port);
1583 } else
1584 return -1;
1585
1586 len = sizeof(servaddr);
1587
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);
1592-
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));
1596+#ifdef INET6
1597+ if (servaddr.__ss_family == AF_INET6)
1598+ c->remote_port = ntohs(((struct sockaddr_in6 *)&servaddr)->sin6_port);
1599+ else
1600+#endif
1601+ if (servaddr.__ss_family == AF_INET)
1602+ c->remote_port = ntohs(((struct sockaddr_in *)&servaddr)->sin_port);
1603 } else
1604 return -1;
1605
1606@@ -1086,7 +1170,7 @@
1607 * If resolve is non-zero, the remote address is reverse resolved.
1608 */
1609
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)
1613 {
1614 int rfd,wfd;
1615@@ -1120,15 +1204,15 @@
1616
1617 if(addr) {
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));
1623 }
1624
1625 if(resolve && res->remote_ipaddr)
1626 res->remote_name = inet_getname(res->pool,res->remote_ipaddr);
1627
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));
1631
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.
1637 */
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)
1641 {
1642 conn_t *res = NULL;
1643@@ -1172,15 +1256,15 @@
1644
1645 if (addr) {
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));
1651 }
1652
1653 if (resolve && res->remote_ipaddr)
1654 res->remote_name = inet_getname(res->pool,res->remote_ipaddr);
1655
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));
1659
1660 if (fd == -1 && c->listen_fd != -1)
1661 fd = c->listen_fd;
1662@@ -1224,6 +1308,127 @@
1663 return res;
1664 }
1665
1666+int inet_address_match(struct sockaddr_storage *cp,
1667+ struct sockaddr_storage *rp)
1668+{
1669+ struct sockaddr_in *sin_cp, *sin_rp;
1670+#ifdef INET6
1671+ struct sockaddr_in6 *sin6_cp, *sin6_rp;
1672+
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)
1679+ return 1;
1680+ else
1681+ return 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)
1688+ return 1;
1689+ else
1690+ return 0;
1691+ }
1692+#endif /* INET6 */
1693+ if (cp->__ss_family != rp->__ss_family)
1694+ return 0;
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)
1699+ return 1;
1700+ else
1701+ return 0;
1702+#ifdef INET6
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))
1707+ return 1;
1708+ else
1709+ return 0;
1710+#endif /* INET6 */
1711+ }
1712+ return 0;
1713+}
1714+
1715+int inet_prefix_match(struct sockaddr_storage *cp,
1716+ struct sockaddr_storage *rp, int prefix)
1717+{
1718+ u_int_32 netmask = 0;
1719+ struct sockaddr_in *sin_cp, *sin_rp;
1720+ struct in_addr cp4, rp4;
1721+#ifdef INET6
1722+ struct sockaddr_in6 *sin6_cp, *sin6_rp;
1723+ struct in6_addr cp6, rp6;
1724+
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)
1734+ return 1;
1735+ else
1736+ return 0;
1737+ } else
1738+ return 0;
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)
1748+ return 1;
1749+ else
1750+ return 0;
1751+ } else
1752+ return 0;
1753+ }
1754+#endif /* INET6 */
1755+ if (cp->__ss_family != rp->__ss_family)
1756+ return 0;
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)
1763+ return 1;
1764+ else
1765+ return 0;
1766+#ifdef INET6
1767+ } else if (cp->__ss_family == AF_INET6) {
1768+ int i,j;
1769+
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++) {
1773+ j=0; netmask=0;
1774+ while (prefix && j++<32) { prefix--; netmask >>= 1; netmask |= 0x80000000; }
1775+ cp6.s6_addr32[i] &= htonl(netmask);
1776+ rp6.s6_addr32[i] &= htonl(netmask);
1777+ }
1778+ if (IN6_ARE_ADDR_EQUAL(&cp6, &rp6))
1779+ return 1;
1780+ else
1781+ return 0;
1782+#endif /* INET6 */
1783+ }
1784+ return 0;
1785+}
1786+
1787 /* Perform reverse ip dns resolution on an existing
1788 * connection.
1789 */
1790@@ -1234,7 +1439,7 @@
1791 c->remote_name = inet_getname(c->pool,c->remote_ipaddr);
1792
1793 if(!c->remote_name)
1794- c->remote_name = pstrdup(c->pool,inet_ntoa(*c->remote_ipaddr));
1795+ c->remote_name = pstrdup(c->pool,INET_NTOA(c->remote_ipaddr));
1796
1797 }
1798 }
1799diff -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
1802@@ -0,0 +1,40 @@
1803+/*
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>
1807+ *
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.
1812+ *
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.
1817+ *
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.
1821+ */
1822+
1823+/*
1824+ * Inet support functions, many wrappers for netdb functions
1825+ */
1826+
1827+
1828+#include "conf.h"
1829+#include "privs.h"
1830+
1831+#ifdef INET6
1832+char *INET_NTOA(struct sockaddr_storage *ss)
1833+{
1834+ static char buf[1024];
1835+
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");
1839+
1840+ return buf;
1841+}
1842+#endif
1843diff -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 @@
1847 return NULL;
1848 }
1849
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)
1852 {
1853 char buf[LOGBUFFER_SIZE] = {'\0'};
1854
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);
1860 }
1861@@ -459,7 +459,7 @@
1862 */
1863
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, ...)
1868 {
1869 logrun_t ent,fent;
1870@@ -590,7 +590,7 @@
1871 * but I haven't been able to test them.
1872 */
1873
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)
1876 {
1877 struct stat buf;
1878 struct utmp ut;
1879@@ -657,8 +657,14 @@
1880 memset(&ut,0,sizeof(ut));
1881 #ifdef HAVE_UTMAXTYPE
1882 #ifdef LINUX
1883- if(ip)
1884- memcpy(&ut.ut_addr,ip,sizeof(ut.ut_addr));
1885+ if(ip) {
1886+#ifdef INET6
1887+ if (ip->__ss_family == AF_INET6)
1888+ memcpy(&ut.ut_addr_v6,&((struct sockaddr_in6 *)ip)->sin6_addr,sizeof(ut.ut_addr_v6));
1889+ else
1890+#endif
1891+ memcpy(&ut.ut_addr,&((struct sockaddr_in *)ip)->sin_addr,sizeof(ut.ut_addr));
1892+ }
1893 #else
1894 sstrncpy(ut.ut_id,"ftp",sizeof(ut.ut_id));
1895 ut.ut_exit.e_termination = 0;
1896@@ -835,7 +841,7 @@
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';
1903 }
1904 }
1905diff -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
1908@@ -108,7 +108,7 @@
1909 struct _binding *next;
1910
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 */
1914 int port;
1915 conn_t *listen; /* listen connection (if separate) */
1916 char isdefault; /* if default connection */
1917@@ -158,17 +158,17 @@
1918
1919 char *config_filename = CONFIG_FILE_PATH;
1920
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)
1924 {
1925 binding_t *b;
1926
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);
1936 return -1;
1937 }
1938@@ -179,7 +179,7 @@
1939 b = palloc(bind_pool,sizeof(binding_t));
1940 b->server = server;
1941 b->port = server->ServerPort;
1942- b->ipaddr = *ipaddr;
1943+ memcpy(&b->ipaddr, ipaddr, sizeof(struct sockaddr_storage));
1944 b->listen = listen;
1945 b->isdefault = isdefault;
1946 b->islocalhost = islocalhost;
1947@@ -190,12 +190,12 @@
1948 return 0;
1949 }
1950
1951-server_rec *find_binding(p_in_addr_t *ipaddr, int port)
1952+server_rec *find_binding(struct sockaddr_storage *ipaddr, int port)
1953 {
1954 binding_t *b,*local_b = NULL,*default_b = NULL;
1955
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))
1959 return b->server;
1960
1961 if(b->islocalhost)
1962@@ -206,20 +206,20 @@
1963
1964 /* Not found in binding list, so see if it's the loopback address */
1965 if(local_b) {
1966- p_in_addr_t loopback,loopmask,tmp;
1967-
1968-#ifdef HAVE_INET_ATON
1969- inet_aton(LOOPBACK_NET,&loopback);
1970- inet_aton(LOOPBACK_MASK,&loopmask);
1971-#else
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;
1976+#ifdef INET6
1977+ struct sockaddr_in6 *loopback6 = (struct sockaddr_in6 *)&loopback;
1978+
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;
1984 #endif
1985- loopback.s_addr = ntohl(loopback.s_addr);
1986- loopmask.s_addr = ntohl(loopmask.s_addr);
1987- tmp.s_addr = ntohl(ipaddr->s_addr);
1988-
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;
1995 }
1996@@ -664,8 +664,8 @@
1997 if ((c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress",
1998 FALSE)) != NULL) {
1999
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));
2004 }
2005
2006 time(&now);
2007@@ -962,7 +962,7 @@
2008
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
2014 );
2015
2016@@ -972,8 +972,8 @@
2017
2018 if ((masq_c = find_config(server->conf, CONF_PARAM, "MasqueradeAddress",
2019 FALSE)) != NULL) {
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));
2024 }
2025
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",
2029 FALSE)) != NULL) {
2030
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));
2035 }
2036
2037 reason = sreplace(permanent_pool,shutmsg,
2038@@ -1501,7 +1501,7 @@
2039
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));
2044
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));
2053 exit(0);
2054 }
2055
2056@@ -1563,10 +1563,10 @@
2057 init_child_modules();
2058
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);
2067
2068 /* xfer_set_data_port(conn->local_ipaddr,conn->local_port-1); */
2069@@ -2172,7 +2172,7 @@
2070 {
2071 config_rec *c;
2072 conn_t *listen;
2073- p_in_addr_t *ipaddr;
2074+ struct sockaddr_storage *ipaddr;
2075
2076 c = find_config(s->conf,CONF_PARAM,"Bind",FALSE);
2077 while(c) {
2078diff -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 @@
2082
2083 return dest;
2084 }
2085+
2086+/* convert IPv4-mapped to real IPv4 struct */
2087+void mappedtov4( struct sockaddr_storage *ss )
2088+{
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;
2096+#ifdef SIN6_LEN
2097+ sin.sin_len = sizeof(struct sockaddr_in);
2098+#endif
2099+ memset(ss, 0, sizeof(struct sockaddr_storage));
2100+ memcpy(ss, &sin, sizeof(sin));
2101+ }
2102+}
2103+
This page took 0.257544 seconds and 4 git commands to generate.