1309 lines
44 KiB
Diff
1309 lines
44 KiB
Diff
|
Submitted By: Mario Fetka (geos_one) (mario dot fetka at gmail dot com)
|
||
|
Date: 2010-01-05
|
||
|
Initial Package Version: 0.3.6
|
||
|
Origin: ftp://ftp.deepspace6.net/pub/ds6/sources/oftpd/oftpd-0.3.6-ipv6rel2.patch.gz
|
||
|
Upstream Status: unknown
|
||
|
Description: add better ipv6 support to oftpd
|
||
|
|
||
|
diff -Naur oftpd-0.3.7.orig/src/Makefile.am oftpd-0.3.7/src/Makefile.am
|
||
|
--- oftpd-0.3.7.orig/src/Makefile.am 2001-04-17 23:05:16.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/Makefile.am 2010-01-05 21:50:11.109303546 +0000
|
||
|
@@ -1,2 +1,2 @@
|
||
|
bin_PROGRAMS = oftpd
|
||
|
-oftpd_SOURCES = file_list.c file_list.h ftp_command.c ftp_command.h ftp_listener.c ftp_listener.h ftp_session.c ftp_session.h oftpd.c oftpd.h telnet_session.c telnet_session.h watchdog.c watchdog.h error.c error.h af_portability.h daemon_assert.c daemon_assert.h
|
||
|
+oftpd_SOURCES = file_list.c file_list.h ftp_command.c ftp_command.h ftp_listener.c ftp_listener.h ftp_session.c ftp_session.h oftpd.c oftpd.h telnet_session.c telnet_session.h watchdog.c watchdog.h error.c error.h af_portability.h af_portability.c daemon_assert.c daemon_assert.h
|
||
|
diff -Naur oftpd-0.3.7.orig/src/af_portability.c oftpd-0.3.7/src/af_portability.c
|
||
|
--- oftpd-0.3.7.orig/src/af_portability.c 1970-01-01 00:00:00.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/af_portability.c 2010-01-05 21:50:11.109303546 +0000
|
||
|
@@ -0,0 +1,32 @@
|
||
|
+#include <stdlib.h>
|
||
|
+#include <netdb.h>
|
||
|
+#include <netinet/in.h>
|
||
|
+
|
||
|
+unsigned short int sockaddr_port(const struct sockaddr *sa, socklen_t salen)
|
||
|
+{
|
||
|
+#ifdef INET6
|
||
|
+ char sbuf[NI_MAXSERV];
|
||
|
+#endif
|
||
|
+ unsigned short int port = 0;
|
||
|
+
|
||
|
+#ifdef INET6
|
||
|
+ if (getnameinfo(sa, salen, NULL, 0, sbuf, sizeof(sbuf),
|
||
|
+ NI_NUMERICSERV) == 0)
|
||
|
+ port = atoi(sbuf);
|
||
|
+ else
|
||
|
+#endif
|
||
|
+ switch (sa->sa_family) {
|
||
|
+ case AF_INET:
|
||
|
+ port = ntohs(((struct sockaddr_in *)sa)->sin_port);
|
||
|
+ break;
|
||
|
+#ifdef INET6
|
||
|
+ case AF_INET6:
|
||
|
+ port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
|
||
|
+ break;
|
||
|
+#endif
|
||
|
+ default:
|
||
|
+ /* everything went wrong :-P */
|
||
|
+ exit(1);
|
||
|
+ }
|
||
|
+ return port;
|
||
|
+}
|
||
|
diff -Naur oftpd-0.3.7.orig/src/af_portability.h oftpd-0.3.7/src/af_portability.h
|
||
|
--- oftpd-0.3.7.orig/src/af_portability.h 2001-03-28 22:31:01.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/af_portability.h 2010-01-05 21:50:11.109303546 +0000
|
||
|
@@ -2,10 +2,9 @@
|
||
|
#define AF_PORTABILITY_H
|
||
|
|
||
|
#include <netinet/in.h>
|
||
|
-#include <sys/socket.h>
|
||
|
|
||
|
/* _x_ must be a pointer to a sockaddr structure */
|
||
|
-
|
||
|
+/*
|
||
|
#define SAFAM(_x_) (((struct sockaddr *)(_x_))->sa_family)
|
||
|
|
||
|
#ifdef HAVE_NEW_SS_FAMILY
|
||
|
@@ -26,6 +25,7 @@
|
||
|
#define SINADDR(_x_) SIN4ADDR(_x_)
|
||
|
#define SINPORT(_x_) SIN4PORT(_x_)
|
||
|
#endif
|
||
|
+*/
|
||
|
|
||
|
#ifndef INET_ADDRSTRLEN
|
||
|
#define INET_ADDRSTRLEN 16
|
||
|
@@ -43,10 +43,13 @@
|
||
|
#define IP_ADDRSTRLEN INET_ADDRSTRLEN
|
||
|
#endif
|
||
|
|
||
|
+unsigned short int sockaddr_port(const struct sockaddr *sa, socklen_t salen);
|
||
|
+/*
|
||
|
#ifdef INET6
|
||
|
typedef struct sockaddr_storage sockaddr_storage_t;
|
||
|
#else
|
||
|
typedef struct sockaddr_in sockaddr_storage_t;
|
||
|
#endif
|
||
|
+*/
|
||
|
|
||
|
#endif /* AF_PORTABILITY_H */
|
||
|
diff -Naur oftpd-0.3.7.orig/src/config.h.in oftpd-0.3.7/src/config.h.in
|
||
|
--- oftpd-0.3.7.orig/src/config.h.in 2002-02-04 22:45:58.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/config.h.in 2010-01-05 21:50:11.110304366 +0000
|
||
|
@@ -97,15 +97,15 @@
|
||
|
/* Define if you have the <limits.h> header file. */
|
||
|
#undef HAVE_LIMITS_H
|
||
|
|
||
|
+/* Define if you have the <syslog.h> header file. */
|
||
|
+#undef HAVE_SYSLOG_H
|
||
|
+
|
||
|
/* Define if you have the <sys/time.h> header file. */
|
||
|
#undef HAVE_SYS_TIME_H
|
||
|
|
||
|
/* Define if you have the <sys/types.h> header file. */
|
||
|
#undef HAVE_SYS_TYPES_H
|
||
|
|
||
|
-/* Define if you have the <syslog.h> header file. */
|
||
|
-#undef HAVE_SYSLOG_H
|
||
|
-
|
||
|
/* Define if you have the <unistd.h> header file. */
|
||
|
#undef HAVE_UNISTD_H
|
||
|
|
||
|
diff -Naur oftpd-0.3.7.orig/src/error.c oftpd-0.3.7/src/error.c
|
||
|
--- oftpd-0.3.7.orig/src/error.c 2001-04-18 21:41:04.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/error.c 2010-01-05 21:50:11.110304366 +0000
|
||
|
@@ -23,6 +23,7 @@
|
||
|
{
|
||
|
va_list args;
|
||
|
|
||
|
+ fprintf(stderr, "error_init: %d %s", error_code, desc_fmt);
|
||
|
daemon_assert(err != NULL);
|
||
|
daemon_assert(error_code >= 0);
|
||
|
daemon_assert(desc_fmt != NULL);
|
||
|
diff -Naur oftpd-0.3.7.orig/src/ftp_command.c oftpd-0.3.7/src/ftp_command.c
|
||
|
--- oftpd-0.3.7.orig/src/ftp_command.c 2004-03-25 20:46:57.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/ftp_command.c 2010-01-05 21:50:11.133303657 +0000
|
||
|
@@ -12,7 +12,6 @@
|
||
|
#include <arpa/inet.h>
|
||
|
#include <netdb.h>
|
||
|
#include "ftp_command.h"
|
||
|
-#include "af_portability.h"
|
||
|
#include "daemon_assert.h"
|
||
|
|
||
|
/* argument types */
|
||
|
@@ -67,8 +66,8 @@
|
||
|
static const char *parse_host_port(struct sockaddr_in *addr, const char *s);
|
||
|
static const char *parse_number(int *num, const char *s, int max_num);
|
||
|
static const char *parse_offset(off_t *ofs, const char *s);
|
||
|
-static const char *parse_host_port_long(sockaddr_storage_t *sa, const char *s);
|
||
|
-static const char *parse_host_port_ext(sockaddr_storage_t *sa, const char *s);
|
||
|
+static const char *parse_host_port_long(struct sockaddr *sa, const char *s);
|
||
|
+static const char *parse_host_port_ext(struct sockaddr *sa, const char *s);
|
||
|
|
||
|
int ftp_command_parse(const char *input, ftp_command_t *cmd)
|
||
|
{
|
||
|
@@ -137,7 +136,7 @@
|
||
|
input++;
|
||
|
|
||
|
/* parse the host & port information (if any) */
|
||
|
- input = parse_host_port(&tmp.arg[0].host_port, input);
|
||
|
+ input = parse_host_port((struct sockaddr_in *)&tmp.arg[0].host_port, input);
|
||
|
if (input == NULL) {
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -151,7 +150,7 @@
|
||
|
input++;
|
||
|
|
||
|
/* parse the host & port information (if any) */
|
||
|
- input = parse_host_port_long(&tmp.arg[0].host_port, input);
|
||
|
+ input = parse_host_port_long((struct sockaddr *)&tmp.arg[0].host_port, input);
|
||
|
if (input == NULL) {
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -165,7 +164,7 @@
|
||
|
input++;
|
||
|
|
||
|
/* parse the host & port information (if any) */
|
||
|
- input = parse_host_port_ext(&tmp.arg[0].host_port, input);
|
||
|
+ input = parse_host_port_ext((struct sockaddr *)&tmp.arg[0].host_port, input);
|
||
|
if (input == NULL) {
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -378,7 +377,7 @@
|
||
|
|
||
|
/* note: returns success even for unknown address families */
|
||
|
/* this is okay, as long as subsequent uses VERIFY THE FAMILY first */
|
||
|
-static const char *parse_host_port_long(sockaddr_storage_t *sa, const char *s)
|
||
|
+static const char *parse_host_port_long(struct sockaddr *sa, const char *s)
|
||
|
{
|
||
|
int i;
|
||
|
int family;
|
||
|
@@ -441,38 +440,38 @@
|
||
|
|
||
|
/* okay, everything parses, load the address if possible */
|
||
|
if (family == 4) {
|
||
|
- SAFAM(sa) = AF_INET;
|
||
|
+ ((struct sockaddr_in *)sa)->sin_family = AF_INET;
|
||
|
if (addr_len != sizeof(struct in_addr)) {
|
||
|
return NULL;
|
||
|
}
|
||
|
if (port_len != 2) {
|
||
|
return NULL;
|
||
|
- }
|
||
|
- memcpy(&SINADDR(sa), addr, addr_len);
|
||
|
- SINPORT(sa) = htons((port[0] << 8) + port[1]);
|
||
|
+ }
|
||
|
+ memcpy(&((struct sockaddr_in *)sa)->sin_addr, addr, addr_len);
|
||
|
+ ((struct sockaddr_in *)sa)->sin_port = htons((port[0] << 8) + port[1]);
|
||
|
}
|
||
|
#ifdef INET6
|
||
|
else if (family == 6) {
|
||
|
- SAFAM(sa) = AF_INET6;
|
||
|
+ ((struct sockaddr_in6 *)sa)->sin6_family = AF_INET6;
|
||
|
if (addr_len != sizeof(struct in6_addr)) {
|
||
|
return NULL;
|
||
|
}
|
||
|
if (port_len != 2) {
|
||
|
return NULL;
|
||
|
}
|
||
|
- memcpy(&SIN6ADDR(sa), addr, addr_len);
|
||
|
- SINPORT(sa) = htons((port[0] << 8) + port[1]);
|
||
|
+ memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr, addr, addr_len);
|
||
|
+ ((struct sockaddr_in6 *)sa)->sin6_port = htons((port[0] << 8) + port[1]);
|
||
|
}
|
||
|
#endif
|
||
|
else {
|
||
|
- SAFAM(sa) = -1;
|
||
|
+ sa->sa_family = -1;
|
||
|
}
|
||
|
|
||
|
/* return new pointer */
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
-static const char *parse_host_port_ext(sockaddr_storage_t *sa, const char *s)
|
||
|
+static const char *parse_host_port_ext(struct sockaddr *sa, const char *s)
|
||
|
{
|
||
|
int delimeter;
|
||
|
int family;
|
||
|
@@ -545,12 +544,11 @@
|
||
|
}
|
||
|
#endif /* HAVE_INET_ATON */
|
||
|
|
||
|
- SIN4ADDR(sa) = in_addr;
|
||
|
+ ((struct sockaddr_in *)sa)->sin_addr = in_addr;
|
||
|
}
|
||
|
#else
|
||
|
{
|
||
|
- struct addrinfo hints;
|
||
|
- struct *res;
|
||
|
+ struct addrinfo hints, *res;
|
||
|
|
||
|
memset(&hints, 0, sizeof(hints));
|
||
|
hints.ai_flags = AI_NUMERICHOST;
|
||
|
@@ -566,8 +564,17 @@
|
||
|
}
|
||
|
#endif /* INET6 */
|
||
|
|
||
|
- SAFAM(sa) = family;
|
||
|
- SINPORT(sa) = htons(port);
|
||
|
+ sa->sa_family = family;
|
||
|
+ if (family == AF_INET) {
|
||
|
+ ((struct sockaddr_in *)sa)->sin_port = htons(port);
|
||
|
+#ifdef INET6
|
||
|
+ } else if (family == AF_INET6) {
|
||
|
+ ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
|
||
|
+#endif /* INET6 */
|
||
|
+ } else {
|
||
|
+ /* we have an error! */
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
|
||
|
/* return new pointer */
|
||
|
return s;
|
||
|
diff -Naur oftpd-0.3.7.orig/src/ftp_command.h oftpd-0.3.7/src/ftp_command.h
|
||
|
--- oftpd-0.3.7.orig/src/ftp_command.h 2001-03-20 23:56:00.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/ftp_command.h 2010-01-05 21:50:11.141303856 +0000
|
||
|
@@ -34,7 +34,6 @@
|
||
|
#include <netinet/in.h>
|
||
|
#include <limits.h>
|
||
|
#include <sys/types.h>
|
||
|
-#include "af_portability.h"
|
||
|
|
||
|
/* special macro for handling EPSV ALL requests */
|
||
|
#define EPSV_ALL (-1)
|
||
|
@@ -50,7 +49,11 @@
|
||
|
int num_arg;
|
||
|
union {
|
||
|
char string[MAX_STRING_LEN+1];
|
||
|
- sockaddr_storage_t host_port;
|
||
|
+#ifdef INET6
|
||
|
+ struct sockaddr_storage host_port;
|
||
|
+#else
|
||
|
+ struct sockaddr_in host_port;
|
||
|
+#endif
|
||
|
int num;
|
||
|
off_t offset;
|
||
|
} arg[MAX_ARG];
|
||
|
diff -Naur oftpd-0.3.7.orig/src/ftp_listener.c oftpd-0.3.7/src/ftp_listener.c
|
||
|
--- oftpd-0.3.7.orig/src/ftp_listener.c 2001-05-10 23:29:46.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/ftp_listener.c 2010-01-05 21:50:11.144303870 +0000
|
||
|
@@ -52,7 +52,6 @@
|
||
|
#include "af_portability.h"
|
||
|
|
||
|
|
||
|
-
|
||
|
/* maximum number of consecutive errors in accept()
|
||
|
before we terminate listener */
|
||
|
#define MAX_ACCEPT_ERROR 10
|
||
|
@@ -73,7 +72,7 @@
|
||
|
/* prototypes */
|
||
|
static int invariant(const ftp_listener_t *f);
|
||
|
static void *connection_acceptor(ftp_listener_t *f);
|
||
|
-static void addr_to_string(const sockaddr_storage_t *s, char *addr);
|
||
|
+static void addr_to_string(const struct sockaddr *s, char *addr);
|
||
|
static void *connection_handler(connection_info_t *info);
|
||
|
static void connection_handler_cleanup(connection_info_t *info);
|
||
|
|
||
|
@@ -85,14 +84,22 @@
|
||
|
int inactivity_timeout,
|
||
|
error_t *err)
|
||
|
{
|
||
|
- sockaddr_storage_t sock_addr;
|
||
|
+#ifdef INET6
|
||
|
+ struct sockaddr_storage sock_addr;
|
||
|
+ int gai_err;
|
||
|
+ struct addrinfo hints;
|
||
|
+ struct addrinfo *res;
|
||
|
+ char buf[ADDR_BUF_LEN+1];
|
||
|
+ int ret;
|
||
|
+#else
|
||
|
+ struct sockaddr_in sock_addr;
|
||
|
+ char *addr_str;
|
||
|
+#endif
|
||
|
int fd;
|
||
|
int flags;
|
||
|
int pipefds[2];
|
||
|
int reuseaddr;
|
||
|
char dir[PATH_MAX+1];
|
||
|
- char buf[ADDR_BUF_LEN+1];
|
||
|
- const char *inet_ntop_ret;
|
||
|
|
||
|
daemon_assert(f != NULL);
|
||
|
daemon_assert(port >= 0);
|
||
|
@@ -108,64 +115,67 @@
|
||
|
}
|
||
|
|
||
|
/* set up our socket address */
|
||
|
- memset(&sock_addr, 0, sizeof(sockaddr_storage_t));
|
||
|
+ memset(&sock_addr, 0, sizeof(sock_addr));
|
||
|
|
||
|
- if (address == NULL) {
|
||
|
#ifdef INET6
|
||
|
- SAFAM(&sock_addr) = AF_INET6;
|
||
|
- memcpy(&SIN6ADDR(&sock_addr), &in6addr_any, sizeof(struct in6_addr));
|
||
|
+ memset(&hints, 0, sizeof(hints));
|
||
|
+
|
||
|
+ /* with AF_UNSPEC we can handle even hostnames */
|
||
|
+ hints.ai_family = (address == NULL ? AF_INET6 : AF_UNSPEC);
|
||
|
+ hints.ai_flags = AI_PASSIVE;
|
||
|
+ hints.ai_socktype = SOCK_STREAM;
|
||
|
+
|
||
|
+ gai_err = getaddrinfo(address, "21", &hints, &res);
|
||
|
+ if (gai_err != 0) {
|
||
|
+ if (gai_err < 0) gai_err = -gai_err;
|
||
|
+ error_init(err, gai_err, "error parsing server socket address; %s",
|
||
|
+ gai_strerror(gai_err));
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ memcpy(&sock_addr, res->ai_addr, res->ai_addrlen);
|
||
|
+ freeaddrinfo(res);
|
||
|
#else
|
||
|
- SAFAM(&sock_addr) = AF_INET;
|
||
|
+ if (address == NULL) {
|
||
|
+ sock_addr.sin_family = AF_INET;
|
||
|
sock_addr.sin_addr.s_addr = INADDR_ANY;
|
||
|
-#endif
|
||
|
} else {
|
||
|
- int gai_err;
|
||
|
- struct addrinfo hints;
|
||
|
- struct addrinfo *res;
|
||
|
-
|
||
|
- memset(&hints, 0, sizeof(hints));
|
||
|
-
|
||
|
-/* - This code should be able to parse both IPv4 and IPv6 internet
|
||
|
- * addresses and put them in the sock_addr variable.
|
||
|
- * - Much neater now.
|
||
|
- * - Bug: Can't handle hostnames, only IP addresses. Not sure
|
||
|
- * exactly why. But then again, I'm not sure exactly why
|
||
|
- * there is a man page for getipnodebyname (which getaddrinfo
|
||
|
- * says it uses) but no corresponding function in libc.
|
||
|
- * -- Matthew Danish [3/20/2001]
|
||
|
- */
|
||
|
+ struct hostent *hp;
|
||
|
+
|
||
|
+ hp = gethostbyname(address);
|
||
|
+ if(hp == NULL) {
|
||
|
+ error_init(err, h_errno, "error with gethostbyname");
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ assert(hp->h_length <= sizeof(sock_addr));
|
||
|
+ memcpy(&sock_addr, hp->h_addr, hp->h_length);
|
||
|
+ }
|
||
|
+#endif
|
||
|
|
||
|
+ /* setup non-default port */
|
||
|
+ if (port != 0) {
|
||
|
+ sa_family_t family = ((struct sockaddr *)&sock_addr)->sa_family;
|
||
|
+ switch (family) {
|
||
|
#ifdef INET6
|
||
|
- hints.ai_family = AF_INET6;
|
||
|
-#else
|
||
|
- hints.ai_family = AF_INET;
|
||
|
+ case AF_INET6:
|
||
|
+ ((struct sockaddr_in6*)&sock_addr)->sin6_port = port;
|
||
|
+ break;
|
||
|
#endif
|
||
|
-
|
||
|
- hints.ai_flags = AI_PASSIVE;
|
||
|
-
|
||
|
- gai_err = getaddrinfo(address, NULL, &hints, &res);
|
||
|
- if (gai_err != 0) {
|
||
|
- error_init(err, gai_err, "error parsing server socket address; %s",
|
||
|
- gai_strerror(gai_err));
|
||
|
- return 0;
|
||
|
- }
|
||
|
-
|
||
|
- memcpy(&sock_addr, res->ai_addr, res->ai_addrlen);
|
||
|
- freeaddrinfo(res);
|
||
|
- }
|
||
|
-
|
||
|
- if (port == 0) {
|
||
|
- SINPORT(&sock_addr) = htons(DEFAULT_FTP_PORT);
|
||
|
- } else {
|
||
|
- SINPORT(&sock_addr) = htons(port);
|
||
|
+ case AF_INET:
|
||
|
+ ((struct sockaddr_in*)&sock_addr)->sin_port = port;
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ /* handle error */
|
||
|
+ error_init(err, 1, "unknown adderess family");
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
}
|
||
|
-
|
||
|
-
|
||
|
- inet_ntop_ret = inet_ntop(SAFAM(&sock_addr),
|
||
|
- (void *)&SINADDR(&sock_addr),
|
||
|
- buf,
|
||
|
- sizeof(buf));
|
||
|
- if (inet_ntop_ret == NULL) {
|
||
|
+
|
||
|
+#ifdef INET6
|
||
|
+ ret = getnameinfo((struct sockaddr *)(&sock_addr), sizeof(sock_addr), buf, sizeof(buf),
|
||
|
+ NULL, 0, NI_NUMERICHOST);
|
||
|
+ if (ret != 0) {
|
||
|
error_init(err, errno, "error converting server address to ASCII; %s",
|
||
|
strerror(errno));
|
||
|
return 0;
|
||
|
@@ -173,11 +183,26 @@
|
||
|
|
||
|
/* Put some information in syslog */
|
||
|
syslog(LOG_INFO, "Binding interface '%s', port %d, max clients %d\n", buf,
|
||
|
- ntohs(SINPORT(&sock_addr)), max_connections);
|
||
|
+ sockaddr_port((struct sockaddr *)&sock_addr, sizeof(sock_addr)), max_connections);
|
||
|
+#else
|
||
|
+ /* this should be thread-safe, as glibc texinfo documentation states:
|
||
|
+ *
|
||
|
+ * In multi-threaded programs each thread has an own
|
||
|
+ * statically-allocated buffer (for inet_ntoa). But still
|
||
|
+ * subsequent calls of `inet_ntoa' in the same thread will
|
||
|
+ * overwrite the result of the last call.
|
||
|
+ */
|
||
|
+ addr_str = inet_ntoa(sock_addr.sin_addr);
|
||
|
+
|
||
|
+ /* Put some information in syslog */
|
||
|
+ syslog(LOG_INFO, "Binding interface '%s', port %d, max clients %d\n",
|
||
|
+ addr_str,sockaddr_port((struct sockaddr*)&sock_addr,sizeof(sock_addr)),
|
||
|
+ max_connections);
|
||
|
+#endif
|
||
|
|
||
|
|
||
|
/* okay, finally do some socket manipulation */
|
||
|
- fd = socket(AF_INET, SOCK_STREAM, 0);
|
||
|
+ fd = socket(((struct sockaddr *)&sock_addr)->sa_family, SOCK_STREAM, 0);
|
||
|
if (fd == -1) {
|
||
|
error_init(err, errno, "error creating socket; %s", strerror(errno));
|
||
|
return 0;
|
||
|
@@ -193,8 +218,7 @@
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
- if (bind(fd, (struct sockaddr *)&sock_addr,
|
||
|
- sizeof(struct sockaddr_in)) != 0)
|
||
|
+ if (bind(fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0)
|
||
|
{
|
||
|
close(fd);
|
||
|
error_init(err, errno, "error binding address; %s", strerror(errno));
|
||
|
@@ -261,6 +285,8 @@
|
||
|
daemon_assert(invariant(f));
|
||
|
daemon_assert(err != NULL);
|
||
|
|
||
|
+ syslog(LOG_WARNING, "in ftp_listener_start\n");
|
||
|
+
|
||
|
error_code = pthread_create(&thread_id,
|
||
|
NULL,
|
||
|
(void *(*)())connection_acceptor,
|
||
|
@@ -320,8 +346,13 @@
|
||
|
|
||
|
int fd;
|
||
|
int tcp_nodelay;
|
||
|
- sockaddr_storage_t client_addr;
|
||
|
- sockaddr_storage_t server_addr;
|
||
|
+#ifdef INET6
|
||
|
+ struct sockaddr_storage client_addr;
|
||
|
+ struct sockaddr_storage server_addr;
|
||
|
+#else
|
||
|
+ struct sockaddr_in client_addr;
|
||
|
+ struct sockaddr_in server_addr;
|
||
|
+#endif
|
||
|
unsigned addr_len;
|
||
|
|
||
|
connection_info_t *info;
|
||
|
@@ -332,6 +363,8 @@
|
||
|
|
||
|
daemon_assert(invariant(f));
|
||
|
|
||
|
+ syslog(LOG_WARNING, "in connection_acceptor\n");
|
||
|
+
|
||
|
if (!watchdog_init(&f->watchdog, f->inactivity_timeout, &err)) {
|
||
|
syslog(LOG_ERR, "Error initializing watchdog thread; %s",
|
||
|
error_get_desc(&err));
|
||
|
@@ -355,10 +388,12 @@
|
||
|
}
|
||
|
|
||
|
/* otherwise accept our pending connection (if any) */
|
||
|
- addr_len = sizeof(sockaddr_storage_t);
|
||
|
+ addr_len = sizeof(client_addr);
|
||
|
fd = accept(f->fd, (struct sockaddr *)&client_addr, &addr_len);
|
||
|
if (fd >= 0) {
|
||
|
|
||
|
+ syslog(LOG_WARNING, "in connection_acceptor loop\n");
|
||
|
+
|
||
|
tcp_nodelay = 1;
|
||
|
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&tcp_nodelay,
|
||
|
sizeof(int)) != 0)
|
||
|
@@ -370,7 +405,7 @@
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
- addr_len = sizeof(sockaddr_storage_t);
|
||
|
+ addr_len = sizeof(server_addr);
|
||
|
if (getsockname(fd, (struct sockaddr *)&server_addr,
|
||
|
&addr_len) == -1)
|
||
|
{
|
||
|
@@ -392,9 +427,11 @@
|
||
|
|
||
|
telnet_session_init(&info->telnet_session, fd, fd);
|
||
|
|
||
|
+ syslog(LOG_WARNING, "about to call ftp_session_init\n");
|
||
|
+
|
||
|
if (!ftp_session_init(&info->ftp_session,
|
||
|
- &client_addr,
|
||
|
- &server_addr,
|
||
|
+ (struct sockaddr *)&client_addr,
|
||
|
+ (struct sockaddr *)&server_addr,
|
||
|
&info->telnet_session,
|
||
|
f->dir,
|
||
|
&err))
|
||
|
@@ -444,7 +481,7 @@
|
||
|
|
||
|
/* convert an address to a printable string */
|
||
|
/* NOT THREADSAFE - wrap with a mutex before calling! */
|
||
|
-static char *addr2string(const sockaddr_storage_t *s)
|
||
|
+static char *addr2string(const struct sockaddr *s)
|
||
|
{
|
||
|
static char addr[IP_ADDRSTRLEN+1];
|
||
|
int error;
|
||
|
@@ -454,14 +491,14 @@
|
||
|
|
||
|
#ifdef INET6
|
||
|
error = getnameinfo((struct sockaddr *)s,
|
||
|
- sizeof(sockaddr_storage_t),
|
||
|
+ sizeof(struct sockaddr_storage),
|
||
|
addr,
|
||
|
sizeof(addr),
|
||
|
NULL,
|
||
|
0,
|
||
|
NI_NUMERICHOST);
|
||
|
if (error != 0) {
|
||
|
- syslog(LOG_WARN, "getnameinfo error; %s", gai_strerror(error));
|
||
|
+ syslog(LOG_WARNING, "getnameinfo error; %s", gai_strerror(error));
|
||
|
ret_val = "Unknown IP";
|
||
|
} else {
|
||
|
ret_val = addr;
|
||
|
@@ -480,6 +517,7 @@
|
||
|
int num_connections;
|
||
|
char drop_reason[80];
|
||
|
|
||
|
+ syslog(LOG_WARNING, "in connection_handler\n");
|
||
|
/* for ease of use only */
|
||
|
f = info->ftp_listener;
|
||
|
|
||
|
@@ -497,13 +535,15 @@
|
||
|
pthread_mutex_lock(&f->mutex);
|
||
|
num_connections = ++f->num_connections;
|
||
|
syslog(LOG_INFO, "%s port %d connection",
|
||
|
- addr2string(&info->ftp_session.client_addr),
|
||
|
- ntohs(SINPORT(&info->ftp_session.client_addr)));
|
||
|
+ addr2string((struct sockaddr *)&info->ftp_session.client_addr),
|
||
|
+ sockaddr_port((struct sockaddr *)&info->ftp_session.client_addr,
|
||
|
+ sizeof(info->ftp_session.client_addr)));
|
||
|
pthread_mutex_unlock(&f->mutex);
|
||
|
|
||
|
/* handle the session */
|
||
|
if (num_connections <= f->max_connections) {
|
||
|
|
||
|
+ syslog(LOG_WARNING, "about to call ftp_session_run\n");
|
||
|
ftp_session_run(&info->ftp_session, &info->watched);
|
||
|
|
||
|
} else {
|
||
|
@@ -518,8 +558,9 @@
|
||
|
pthread_mutex_lock(&f->mutex);
|
||
|
syslog(LOG_WARNING,
|
||
|
"%s port %d exceeds max users (%d), dropping connection",
|
||
|
- addr2string(&info->ftp_session.client_addr),
|
||
|
- ntohs(SINPORT(&info->ftp_session.client_addr)),
|
||
|
+ addr2string((struct sockaddr *)&info->ftp_session.client_addr),
|
||
|
+ sockaddr_port((struct sockaddr *)&info->ftp_session.client_addr,
|
||
|
+ sizeof(info->ftp_session.client_addr)),
|
||
|
num_connections);
|
||
|
pthread_mutex_unlock(&f->mutex);
|
||
|
|
||
|
@@ -548,8 +589,9 @@
|
||
|
|
||
|
syslog(LOG_INFO,
|
||
|
"%s port %d disconnected",
|
||
|
- addr2string(&info->ftp_session.client_addr),
|
||
|
- ntohs(SINPORT(&info->ftp_session.client_addr)));
|
||
|
+ addr2string((struct sockaddr *)&info->ftp_session.client_addr),
|
||
|
+ sockaddr_port((struct sockaddr *)&info->ftp_session.client_addr,
|
||
|
+ sizeof(info->ftp_session.client_addr)));
|
||
|
|
||
|
pthread_mutex_unlock(&f->mutex);
|
||
|
|
||
|
diff -Naur oftpd-0.3.7.orig/src/ftp_session.c oftpd-0.3.7/src/ftp_session.c
|
||
|
--- oftpd-0.3.7.orig/src/ftp_session.c 2004-03-25 20:46:40.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/ftp_session.c 2010-01-05 21:50:11.159303450 +0000
|
||
|
@@ -52,12 +52,12 @@
|
||
|
static void init_passive_port();
|
||
|
static int get_passive_port();
|
||
|
static int convert_newlines(char *dst, const char *src, int srclen);
|
||
|
-static void get_addr_str(const sockaddr_storage_t *s, char *buf, int bufsiz);
|
||
|
+static void get_addr_str(const struct sockaddr *s, char *buf, int bufsiz);
|
||
|
static void send_readme(const ftp_session_t *f, int code);
|
||
|
static void netscape_hack(int fd);
|
||
|
-static void set_port(ftp_session_t *f, const sockaddr_storage_t *host_port);
|
||
|
-static int set_pasv(ftp_session_t *f, sockaddr_storage_t *host_port);
|
||
|
-static int ip_equal(const sockaddr_storage_t *a, const sockaddr_storage_t *b);
|
||
|
+static void set_port(ftp_session_t *f, const struct sockaddr *host_port);
|
||
|
+static int set_pasv(ftp_session_t *f, struct sockaddr *host_port);
|
||
|
+static int ip_equal(const struct sockaddr *a, const struct sockaddr *b);
|
||
|
static void get_absolute_fname(char *fname,
|
||
|
int fname_len,
|
||
|
const char *dir,
|
||
|
@@ -123,8 +123,8 @@
|
||
|
|
||
|
|
||
|
int ftp_session_init(ftp_session_t *f,
|
||
|
- const sockaddr_storage_t *client_addr,
|
||
|
- const sockaddr_storage_t *server_addr,
|
||
|
+ const struct sockaddr *client_addr,
|
||
|
+ const struct sockaddr *server_addr,
|
||
|
telnet_session_t *t,
|
||
|
const char *dir,
|
||
|
error_t *err)
|
||
|
@@ -138,9 +138,9 @@
|
||
|
daemon_assert(err != NULL);
|
||
|
|
||
|
#ifdef INET6
|
||
|
- /* if the control connection is on IPv6, we need to get an IPv4 address */
|
||
|
- /* to bind the socket to */
|
||
|
- if (SSFAM(server_addr) == AF_INET6) {
|
||
|
+ /* if the control connection is on IPv6, we need to get an IPv4 address
|
||
|
+ * to bind the socket to */
|
||
|
+ if (server_addr->sa_family == AF_INET6) {
|
||
|
struct addrinfo hints;
|
||
|
struct addrinfo *res;
|
||
|
int errcode;
|
||
|
@@ -149,8 +149,10 @@
|
||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||
|
hints.ai_family = AF_INET;
|
||
|
hints.ai_flags = AI_PASSIVE;
|
||
|
- if (getaddrinfo(NULL, "ftp", &hints, &res) != 0) {
|
||
|
- error_init(err, 0, "unable to determing IPv4 address; %s",
|
||
|
+ hints.ai_socktype = SOCK_STREAM;
|
||
|
+
|
||
|
+ if ((errcode = getaddrinfo(NULL, "21", &hints, &res)) != 0) {
|
||
|
+ error_init(err, 0, "unable to determine IPv4 address; %s",
|
||
|
gai_strerror(errcode));
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -158,17 +160,14 @@
|
||
|
/* let's sanity check */
|
||
|
daemon_assert(res != NULL);
|
||
|
daemon_assert(sizeof(f->server_ipv4_addr) >= res->ai_addrlen);
|
||
|
- daemon_assert(SSFAM(host_port) == AF_INET);
|
||
|
+ daemon_assert(res->ai_addr->sa_family == AF_INET);
|
||
|
|
||
|
/* copy the result and free memory as necessary */
|
||
|
memcpy(&f->server_ipv4_addr, res->ai_addr, res->ai_addrlen);
|
||
|
freeaddrinfo(res);
|
||
|
} else {
|
||
|
- daemon_assert(SSFAM(host_port) == AF_INET);
|
||
|
- f->server_ipv4_addr = *server_addr;
|
||
|
+ f->server_ipv4_addr = *((struct sockaddr_in *)server_addr);
|
||
|
}
|
||
|
-#else
|
||
|
- f->server_ipv4_addr = *server_addr;
|
||
|
#endif
|
||
|
|
||
|
f->session_active = 1;
|
||
|
@@ -182,17 +181,22 @@
|
||
|
|
||
|
f->epsv_all_set = 0;
|
||
|
|
||
|
- f->client_addr = *client_addr;
|
||
|
+#ifdef INET6
|
||
|
+ memcpy(&f->client_addr, client_addr, sizeof(struct sockaddr_in6));
|
||
|
+ memcpy(&f->server_addr, server_addr, sizeof(struct sockaddr_in6));
|
||
|
+ memcpy(&f->data_port, client_addr, sizeof(struct sockaddr_in6));
|
||
|
+#else
|
||
|
+ memcpy(&f->client_addr, client_addr, sizeof(struct sockaddr_in));
|
||
|
+ memcpy(&f->server_addr, server_addr, sizeof(struct sockaddr_in));
|
||
|
+ memcpy(&f->data_port, client_addr, sizeof(struct sockaddr_in));
|
||
|
+#endif
|
||
|
get_addr_str(client_addr, f->client_addr_str, sizeof(f->client_addr_str));
|
||
|
|
||
|
- f->server_addr = *server_addr;
|
||
|
-
|
||
|
f->telnet_session = t;
|
||
|
daemon_assert(strlen(dir) < sizeof(f->dir));
|
||
|
strcpy(f->dir, dir);
|
||
|
|
||
|
f->data_channel = DATA_PORT;
|
||
|
- f->data_port = *client_addr;
|
||
|
f->server_fd = -1;
|
||
|
|
||
|
daemon_assert(invariant(f));
|
||
|
@@ -326,7 +330,8 @@
|
||
|
/* If the client specifies a port, verify that it is from the */
|
||
|
/* host the client connected from. This prevents a client from */
|
||
|
/* using the server to open connections to arbritrary hosts. */
|
||
|
- if (!ip_equal(&f->client_addr, &f->data_port)) {
|
||
|
+ if (!ip_equal((struct sockaddr *)&f->client_addr,
|
||
|
+ (struct sockaddr *)&f->data_port)) {
|
||
|
return 0;
|
||
|
}
|
||
|
if (f->server_fd != -1) {
|
||
|
@@ -412,7 +417,7 @@
|
||
|
}
|
||
|
|
||
|
#ifdef INET6
|
||
|
-static void get_addr_str(const sockaddr_storage_t *s, char *buf, int bufsiz)
|
||
|
+static void get_addr_str(const struct sockaddr *s, char *buf, int bufsiz)
|
||
|
{
|
||
|
int port;
|
||
|
int error;
|
||
|
@@ -426,17 +431,17 @@
|
||
|
* number (which is 5 chars max), plus the '\0' character. */
|
||
|
daemon_assert(bufsiz >= (INET_ADDRSTRLEN + 12));
|
||
|
|
||
|
- error = getnameinfo(client_addr, sizeof(sockaddr_storage_t), buf,
|
||
|
+ error = getnameinfo(s, sizeof(struct sockaddr_storage), buf,
|
||
|
bufsiz, NULL, 0, NI_NUMERICHOST);
|
||
|
/* getnameinfo() should never fail when called with NI_NUMERICHOST */
|
||
|
daemon_assert(error == 0);
|
||
|
|
||
|
len = strlen(buf);
|
||
|
daemon_assert(bufsiz >= len+12);
|
||
|
- snprintf(buf+len, bufsiz-len, " port %d", ntohs(SINPORT(&f->client_addr)));
|
||
|
+ snprintf(buf+len, bufsiz-len, " port %d", sockaddr_port((struct sockaddr *)s, sizeof(s)));
|
||
|
}
|
||
|
#else
|
||
|
-static void get_addr_str(const sockaddr_storage_t *s, char *buf, int bufsiz)
|
||
|
+static void get_addr_str(const struct sockaddr *s, char *buf, int bufsiz)
|
||
|
{
|
||
|
unsigned int addr;
|
||
|
int port;
|
||
|
@@ -449,8 +454,8 @@
|
||
|
* number (which is 5 chars max), plus the '\0' character. */
|
||
|
daemon_assert(bufsiz >= (INET_ADDRSTRLEN + 12));
|
||
|
|
||
|
- addr = ntohl(s->sin_addr.s_addr);
|
||
|
- port = ntohs(s->sin_port);
|
||
|
+ addr = ntohl(((struct sockaddr_in *)s)->sin_addr.s_addr);
|
||
|
+ port = ntohs(((struct sockaddr_in *)s)->sin_port);
|
||
|
snprintf(buf, bufsiz, "%d.%d.%d.%d port %d",
|
||
|
(addr >> 24) & 0xff,
|
||
|
(addr >> 16) & 0xff,
|
||
|
@@ -626,16 +631,22 @@
|
||
|
}
|
||
|
|
||
|
/* support for the various port setting functions */
|
||
|
-static void set_port(ftp_session_t *f, const sockaddr_storage_t *host_port)
|
||
|
-{
|
||
|
+static void set_port(ftp_session_t *f, const struct sockaddr *host_port)
|
||
|
+{
|
||
|
daemon_assert(invariant(f));
|
||
|
daemon_assert(host_port != NULL);
|
||
|
|
||
|
if (f->epsv_all_set) {
|
||
|
reply(f, 500, "After EPSV ALL, only EPSV allowed.");
|
||
|
- } else if (!ip_equal(&f->client_addr, host_port)) {
|
||
|
+ } else if (!ip_equal((struct sockaddr *)&f->client_addr, host_port)) {
|
||
|
reply(f, 500, "Port must be on command channel IP.");
|
||
|
- } else if (ntohs(SINPORT(host_port)) < IPPORT_RESERVED) {
|
||
|
+#ifdef INET6
|
||
|
+ } else if (sockaddr_port(host_port, sizeof(struct sockaddr_storage))
|
||
|
+ < IPPORT_RESERVED) {
|
||
|
+#else
|
||
|
+ } else if (sockaddr_port(host_port, sizeof(struct sockaddr_in))
|
||
|
+ < IPPORT_RESERVED) {
|
||
|
+#endif
|
||
|
reply(f, 500, "Port may not be less than 1024, which is reserved.");
|
||
|
} else {
|
||
|
/* close any outstanding PASSIVE port */
|
||
|
@@ -645,7 +656,11 @@
|
||
|
}
|
||
|
|
||
|
f->data_channel = DATA_PORT;
|
||
|
- f->data_port = *host_port;
|
||
|
+#ifdef INET6
|
||
|
+ memcpy(&f->data_port, host_port, sizeof(struct sockaddr_in6));
|
||
|
+#else
|
||
|
+ memcpy(&f->data_port, host_port, sizeof(struct sockaddr_in));
|
||
|
+#endif
|
||
|
reply(f, 200, "Command okay.");
|
||
|
}
|
||
|
|
||
|
@@ -655,16 +670,20 @@
|
||
|
/* set IP and port for client to receive data on */
|
||
|
static void do_port(ftp_session_t *f, const ftp_command_t *cmd)
|
||
|
{
|
||
|
- const sockaddr_storage_t *host_port;
|
||
|
+#ifdef INET6
|
||
|
+ const struct sockaddr_storage *host_port;
|
||
|
+#else
|
||
|
+ const struct sockaddr_in *host_port;
|
||
|
+#endif
|
||
|
|
||
|
daemon_assert(invariant(f));
|
||
|
daemon_assert(cmd != NULL);
|
||
|
daemon_assert(cmd->num_arg == 1);
|
||
|
|
||
|
host_port = &cmd->arg[0].host_port;
|
||
|
- daemon_assert(SSFAM(host_port) == AF_INET);
|
||
|
+ daemon_assert(((struct sockaddr *)host_port)->sa_family == AF_INET);
|
||
|
|
||
|
- set_port(f, host_port);
|
||
|
+ set_port(f, (struct sockaddr *)host_port);
|
||
|
|
||
|
daemon_assert(invariant(f));
|
||
|
}
|
||
|
@@ -672,7 +691,12 @@
|
||
|
/* set IP and port for client to receive data on, transport independent */
|
||
|
static void do_lprt(ftp_session_t *f, const ftp_command_t *cmd)
|
||
|
{
|
||
|
- const sockaddr_storage_t *host_port;
|
||
|
+#ifdef INET6
|
||
|
+ const struct sockaddr_storage *host_port;
|
||
|
+#else
|
||
|
+ const struct sockaddr_in *host_port;
|
||
|
+#endif
|
||
|
+ struct sockaddr_in6 *tmp = (struct sockaddr_in6 *)host_port;
|
||
|
|
||
|
daemon_assert(invariant(f));
|
||
|
daemon_assert(cmd != NULL);
|
||
|
@@ -681,16 +705,30 @@
|
||
|
host_port = &cmd->arg[0].host_port;
|
||
|
|
||
|
#ifdef INET6
|
||
|
- if ((SSFAM(host_port) != AF_INET) && (SSFAM(host_port) != AF_INET6)) {
|
||
|
+ if ((((struct sockaddr *)host_port)->sa_family != AF_INET) &&
|
||
|
+ (((struct sockaddr *)host_port)->sa_family != AF_INET6)) {
|
||
|
reply(f, 521, "Only IPv4 and IPv6 supported, address families (4,6)");
|
||
|
}
|
||
|
#else
|
||
|
- if (SSFAM(host_port) != AF_INET) {
|
||
|
+ if (((struct sockaddr *)host_port)->sa_family != AF_INET) {
|
||
|
reply(f, 521, "Only IPv4 supported, address family (4)");
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
- set_port(f, host_port);
|
||
|
+ /*
|
||
|
+ syslog(LOG_WARNING, "host is %d:%d:%d:%d:%d:%d:%d:%d %d",
|
||
|
+ ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[0]),
|
||
|
+ ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[1]),
|
||
|
+ ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[2]),
|
||
|
+ ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[3]),
|
||
|
+ ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[4]),
|
||
|
+ ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[5]),
|
||
|
+ ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[6]),
|
||
|
+ ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[7]),
|
||
|
+ sockaddr_port(host_port, sizeof(struct sockaddr_storage)));
|
||
|
+ */
|
||
|
+
|
||
|
+ set_port(f, (struct sockaddr *)host_port);
|
||
|
|
||
|
daemon_assert(invariant(f));
|
||
|
}
|
||
|
@@ -703,7 +741,11 @@
|
||
|
/* requests. */
|
||
|
static void do_eprt(ftp_session_t *f, const ftp_command_t *cmd)
|
||
|
{
|
||
|
- const sockaddr_storage_t *host_port;
|
||
|
+#ifdef INET6
|
||
|
+ const struct sockaddr_storage *host_port;
|
||
|
+#else
|
||
|
+ const struct sockaddr_in *host_port;
|
||
|
+#endif
|
||
|
|
||
|
daemon_assert(invariant(f));
|
||
|
daemon_assert(cmd != NULL);
|
||
|
@@ -717,15 +759,17 @@
|
||
|
/* support for the various pasv setting functions */
|
||
|
/* returns the file descriptor of the bound port, or -1 on error */
|
||
|
/* note: the "host_port" parameter will be modified, having its port set */
|
||
|
-static int set_pasv(ftp_session_t *f, sockaddr_storage_t *bind_addr)
|
||
|
+static int set_pasv(ftp_session_t *f, struct sockaddr *bind_addr)
|
||
|
{
|
||
|
int socket_fd;
|
||
|
int port;
|
||
|
+ sa_family_t family;
|
||
|
|
||
|
daemon_assert(invariant(f));
|
||
|
daemon_assert(bind_addr != NULL);
|
||
|
|
||
|
- socket_fd = socket(SSFAM(bind_addr), SOCK_STREAM, 0);
|
||
|
+ family = ((struct sockaddr *)bind_addr)->sa_family;
|
||
|
+ socket_fd = socket(family, SOCK_STREAM, 0);
|
||
|
if (socket_fd == -1) {
|
||
|
reply(f, 500, "Error creating server socket; %s.", strerror(errno));
|
||
|
return -1;
|
||
|
@@ -733,9 +777,19 @@
|
||
|
|
||
|
for (;;) {
|
||
|
port = get_passive_port();
|
||
|
- SINPORT(bind_addr) = htons(port);
|
||
|
+#ifdef INET6
|
||
|
+ if (((struct sockaddr *)bind_addr)->sa_family == AF_INET6) {
|
||
|
+ ((struct sockaddr_in6 *)bind_addr)->sin6_port = htons(port);
|
||
|
+ } else
|
||
|
+#endif
|
||
|
+ ((struct sockaddr_in *)bind_addr)->sin_port = htons(port);
|
||
|
+
|
||
|
if (bind(socket_fd, (struct sockaddr *)bind_addr,
|
||
|
- sizeof(struct sockaddr)) == 0)
|
||
|
+#ifdef INET6
|
||
|
+ sizeof(struct sockaddr_storage)) == 0)
|
||
|
+#else
|
||
|
+ sizeof(struct sockaddr_in)) == 0)
|
||
|
+#endif
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
@@ -771,14 +825,23 @@
|
||
|
goto exit_pasv;
|
||
|
}
|
||
|
|
||
|
- socket_fd = set_pasv(f, &f->server_ipv4_addr);
|
||
|
+#ifdef INET6
|
||
|
+ socket_fd = set_pasv(f, (struct sockaddr *)&f->server_ipv4_addr);
|
||
|
+#else
|
||
|
+ socket_fd = set_pasv(f, (struct sockaddr *)&f->server_addr);
|
||
|
+#endif
|
||
|
if (socket_fd == -1) {
|
||
|
goto exit_pasv;
|
||
|
}
|
||
|
|
||
|
/* report port to client */
|
||
|
+#ifdef INET6
|
||
|
addr = ntohl(f->server_ipv4_addr.sin_addr.s_addr);
|
||
|
port = ntohs(f->server_ipv4_addr.sin_port);
|
||
|
+#else
|
||
|
+ addr = ntohl(f->server_addr.sin_addr.s_addr);
|
||
|
+ port = ntohs(f->server_addr.sin_port);
|
||
|
+#endif
|
||
|
reply(f, 227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d).",
|
||
|
addr >> 24,
|
||
|
(addr >> 16) & 0xff,
|
||
|
@@ -815,16 +878,16 @@
|
||
|
goto exit_lpsv;
|
||
|
}
|
||
|
|
||
|
- socket_fd = set_pasv(f, &f->server_addr);
|
||
|
+ socket_fd = set_pasv(f, (struct sockaddr *)&f->server_addr);
|
||
|
if (socket_fd == -1) {
|
||
|
goto exit_lpsv;
|
||
|
}
|
||
|
|
||
|
- /* report address and port to client */
|
||
|
+ /* report address and port to server */
|
||
|
#ifdef INET6
|
||
|
- if (SSFAM(&f->server_addr) == AF_INET6) {
|
||
|
- a = (uint8_t *)&SIN6ADDR(&f->server_addr);
|
||
|
- p = (uint8_t *)&SIN6PORT(&f->server_addr);
|
||
|
+ if (((struct sockaddr *)&f->server_addr)->sa_family == AF_INET6) {
|
||
|
+ a = (uint8_t *)&(((struct sockaddr_in6 *)&f->server_addr)->sin6_addr);
|
||
|
+ p = (uint8_t *)&(((struct sockaddr_in6 *)&f->server_addr)->sin6_port);
|
||
|
snprintf(addr, sizeof(addr),
|
||
|
"(6,16,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,2,%d,%d)",
|
||
|
a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8],
|
||
|
@@ -832,8 +895,8 @@
|
||
|
} else
|
||
|
#endif
|
||
|
{
|
||
|
- a = (uint8_t *)&SIN4ADDR(&f->server_addr);
|
||
|
- p = (uint8_t *)&SIN4PORT(&f->server_addr);
|
||
|
+ a = (uint8_t *)&(((struct sockaddr_in *)&f->server_addr)->sin_addr);
|
||
|
+ p = (uint8_t *)&(((struct sockaddr_in *)&f->server_addr)->sin_port);
|
||
|
snprintf(addr, sizeof(addr), "(4,4,%d,%d,%d,%d,2,%d,%d)",
|
||
|
a[0], a[1], a[2], a[3], p[0], p[1]);
|
||
|
}
|
||
|
@@ -855,7 +918,7 @@
|
||
|
static void do_epsv(ftp_session_t *f, const ftp_command_t *cmd)
|
||
|
{
|
||
|
int socket_fd;
|
||
|
- sockaddr_storage_t *addr;
|
||
|
+ struct sockaddr *addr;
|
||
|
|
||
|
daemon_assert(invariant(f));
|
||
|
daemon_assert(cmd != NULL);
|
||
|
@@ -863,10 +926,10 @@
|
||
|
|
||
|
/* check our argument, if any, and use the appropriate address */
|
||
|
if (cmd->num_arg == 0) {
|
||
|
- addr = &f->server_addr;
|
||
|
+ addr = (struct sockaddr *)&f->server_addr;
|
||
|
} else {
|
||
|
switch (cmd->arg[0].num) {
|
||
|
- /* EPSV_ALL is a special number indicating the client sent */
|
||
|
+ /* EPSV_ALL is a special number indicating the server sent */
|
||
|
/* the command "EPSV ALL" - this is not a request to assign */
|
||
|
/* a new passive port, but rather to deny all future port */
|
||
|
/* assignment requests other than EPSV */
|
||
|
@@ -874,17 +937,20 @@
|
||
|
f->epsv_all_set = 1;
|
||
|
reply(f, 200, "EPSV ALL command successful.");
|
||
|
goto exit_epsv;
|
||
|
+#ifdef INET6
|
||
|
case 1:
|
||
|
- addr = (sockaddr_storage_t *)&f->server_ipv4_addr;
|
||
|
+ addr = (struct sockaddr *)&f->server_ipv4_addr;
|
||
|
break;
|
||
|
-#ifdef INET6
|
||
|
case 2:
|
||
|
- addr = &f->server_addr;
|
||
|
+ addr = (struct sockaddr *)&f->server_addr;
|
||
|
break;
|
||
|
default:
|
||
|
reply(f, 522, "Only IPv4 and IPv6 supported, use (1,2)");
|
||
|
goto exit_epsv;
|
||
|
#else
|
||
|
+ case 1:
|
||
|
+ addr = (struct sockaddr *)&f->server_addr;
|
||
|
+ break;
|
||
|
default:
|
||
|
reply(f, 522, "Only IPv4 supported, use (1)");
|
||
|
goto exit_epsv;
|
||
|
@@ -900,7 +966,8 @@
|
||
|
|
||
|
/* report port to client */
|
||
|
reply(f, 229, "Entering Extended Passive Mode (|||%d|)",
|
||
|
- ntohs(SINPORT(&f->server_addr)));
|
||
|
+ sockaddr_port((struct sockaddr *)&f->server_addr,
|
||
|
+ sizeof(f->server_addr)));
|
||
|
|
||
|
/* close any outstanding PASSIVE port */
|
||
|
if (f->data_channel == DATA_PASSIVE) {
|
||
|
@@ -1278,29 +1345,36 @@
|
||
|
static int open_connection(ftp_session_t *f)
|
||
|
{
|
||
|
int socket_fd;
|
||
|
+#ifdef INET6
|
||
|
+ struct sockaddr_storage addr;
|
||
|
+#else
|
||
|
struct sockaddr_in addr;
|
||
|
+#endif
|
||
|
unsigned addr_len;
|
||
|
+ sa_family_t family;
|
||
|
|
||
|
daemon_assert((f->data_channel == DATA_PORT) ||
|
||
|
(f->data_channel == DATA_PASSIVE));
|
||
|
|
||
|
if (f->data_channel == DATA_PORT) {
|
||
|
- socket_fd = socket(SSFAM(&f->data_port), SOCK_STREAM, 0);
|
||
|
+ family = ((struct sockaddr *)&f->data_port)->sa_family;
|
||
|
+ socket_fd = socket(family, SOCK_STREAM, 0);
|
||
|
if (socket_fd == -1) {
|
||
|
reply(f, 425, "Error creating socket; %s.", strerror(errno));
|
||
|
return -1;
|
||
|
}
|
||
|
if (connect(socket_fd, (struct sockaddr *)&f->data_port,
|
||
|
- sizeof(sockaddr_storage_t)) != 0)
|
||
|
+ sizeof(f->data_port)) != 0)
|
||
|
{
|
||
|
reply(f, 425, "Error connecting; %s.", strerror(errno));
|
||
|
close(socket_fd);
|
||
|
return -1;
|
||
|
}
|
||
|
} else {
|
||
|
+ sa_family_t a, b;
|
||
|
daemon_assert(f->data_channel == DATA_PASSIVE);
|
||
|
|
||
|
- addr_len = sizeof(struct sockaddr_in);
|
||
|
+ addr_len = sizeof(addr);
|
||
|
socket_fd = accept(f->server_fd, (struct sockaddr *)&addr, &addr_len);
|
||
|
if (socket_fd == -1) {
|
||
|
reply(f, 425, "Error accepting connection; %s.", strerror(errno));
|
||
|
@@ -1310,15 +1384,31 @@
|
||
|
/* in IPv6, the client can connect to a channel using a different */
|
||
|
/* protocol - in that case, we'll just blindly let the connection */
|
||
|
/* through, otherwise verify addresses match */
|
||
|
- if (SAFAM(addr) == SSFAM(&f->client_addr)) {
|
||
|
- if (memcmp(&SINADDR(&f->client_addr), &SINADDR(&addr),
|
||
|
- sizeof(SINADDR(&addr))))
|
||
|
- {
|
||
|
- reply(f, 425,
|
||
|
- "Error accepting connection; connection from invalid IP.");
|
||
|
- close(socket_fd);
|
||
|
- return -1;
|
||
|
- }
|
||
|
+ a = ((struct sockaddr *)&addr)->sa_family;
|
||
|
+ b = ((struct sockaddr *)&f->client_addr)->sa_family;
|
||
|
+
|
||
|
+ if (a == b) {
|
||
|
+ if (a == AF_INET6) {
|
||
|
+ if (memcmp(&(((struct sockaddr_in6 *)&addr)->sin6_addr),
|
||
|
+ &(((struct sockaddr_in6 *)&f->client_addr)->sin6_addr),
|
||
|
+ sizeof(struct in6_addr)))
|
||
|
+ {
|
||
|
+ reply(f, 425,
|
||
|
+ "Error accepting connection; connection from invalid IP.");
|
||
|
+ close(socket_fd);
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ if (memcmp(&(((struct sockaddr_in *)&addr)->sin_addr),
|
||
|
+ &(((struct sockaddr_in *)&f->client_addr)->sin_addr),
|
||
|
+ sizeof(struct in_addr)))
|
||
|
+ {
|
||
|
+ reply(f, 425,
|
||
|
+ "Error accepting connection; connection from invalid IP.");
|
||
|
+ close(socket_fd);
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
#else
|
||
|
if (memcmp(&f->client_addr.sin_addr,
|
||
|
@@ -1811,20 +1901,69 @@
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+#ifdef INET6
|
||
|
+
|
||
|
/* compare two addresses to see if they contain the same IP address */
|
||
|
-static int ip_equal(const sockaddr_storage_t *a, const sockaddr_storage_t *b)
|
||
|
+static int ip_equal(const struct sockaddr *a, const struct sockaddr *b)
|
||
|
{
|
||
|
+ struct sockaddr *aa, *bb;
|
||
|
+
|
||
|
daemon_assert(a != NULL);
|
||
|
daemon_assert(b != NULL);
|
||
|
- daemon_assert((SSFAM(a) == AF_INET) || (SSFAM(a) == AF_INET6));
|
||
|
- daemon_assert((SSFAM(b) == AF_INET) || (SSFAM(b) == AF_INET6));
|
||
|
-
|
||
|
- if (SSFAM(a) != SSFAM(b)) {
|
||
|
- return 0;
|
||
|
+ daemon_assert((a->sa_family == AF_INET) || (a->sa_family == AF_INET6));
|
||
|
+ daemon_assert((b->sa_family == AF_INET) || (b->sa_family == AF_INET6));
|
||
|
+
|
||
|
+ aa = (struct sockaddr *)a;
|
||
|
+ bb = (struct sockaddr *)b;
|
||
|
+
|
||
|
+ /* we have to handle those --damned-- IPV4MAPPED addresses */
|
||
|
+ if (aa->sa_family != bb->sa_family) {
|
||
|
+ if (a->sa_family == AF_INET6 &&
|
||
|
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)a)->sin6_addr)) {
|
||
|
+ aa = (struct sockaddr *)alloca(sizeof(struct sockaddr_in));
|
||
|
+ memset(aa, 0, sizeof(struct sockaddr_in));
|
||
|
+ ((struct sockaddr_in *)aa)->sin_addr.s_addr =
|
||
|
+ ((struct sockaddr_in6 *)a)->sin6_addr.s6_addr32[3];
|
||
|
+ ((struct sockaddr_in *)aa)->sin_port =
|
||
|
+ ((struct sockaddr_in6 *)a)->sin6_port;
|
||
|
+ } else if (b->sa_family == AF_INET6 &&
|
||
|
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)b)->sin6_addr)) {
|
||
|
+ bb = (struct sockaddr *)alloca(sizeof(struct sockaddr_in));
|
||
|
+ memset(bb, 0, sizeof(struct sockaddr_in));
|
||
|
+ ((struct sockaddr_in *)bb)->sin_addr.s_addr =
|
||
|
+ ((struct sockaddr_in6 *)b)->sin6_addr.s6_addr32[3];
|
||
|
+ ((struct sockaddr_in *)bb)->sin_port =
|
||
|
+ ((struct sockaddr_in6 *)b)->sin6_port;
|
||
|
+ } else {
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
}
|
||
|
- if (memcmp(&SINADDR(a), &SINADDR(b), sizeof(SINADDR(a))) != 0) {
|
||
|
- return 0;
|
||
|
+
|
||
|
+ if (aa->sa_family == AF_INET6) {
|
||
|
+ if (memcmp(&((struct sockaddr_in6 *)aa)->sin6_addr,
|
||
|
+ &((struct sockaddr_in6 *)bb)->sin6_addr,
|
||
|
+ sizeof(struct sockaddr_in6)) != 0) return 0;
|
||
|
+ } else {
|
||
|
+ if (((struct sockaddr_in *)aa)->sin_addr.s_addr !=
|
||
|
+ ((struct sockaddr_in *)bb)->sin_addr.s_addr) return 0;
|
||
|
}
|
||
|
+
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
+#else
|
||
|
+
|
||
|
+static int ip_equal(const struct sockaddr *a, const struct sockaddr *b)
|
||
|
+{
|
||
|
+ daemon_assert(a != NULL);
|
||
|
+ daemon_assert(b != NULL);
|
||
|
+ daemon_assert(a->sa_family == AF_INET);
|
||
|
+ daemon_assert(b->sa_family == AF_INET);
|
||
|
+
|
||
|
+ if (((struct sockaddr_in *)aa)->sin_addr.s_addr !=
|
||
|
+ ((struct sockaddr_in *)bb)->sin_addr.s_addr) return 0;
|
||
|
+
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+#endif
|
||
|
diff -Naur oftpd-0.3.7.orig/src/ftp_session.h oftpd-0.3.7/src/ftp_session.h
|
||
|
--- oftpd-0.3.7.orig/src/ftp_session.h 2001-05-10 23:29:12.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/ftp_session.h 2010-01-05 21:50:11.160303781 +0000
|
||
|
@@ -12,7 +12,6 @@
|
||
|
#include <netinet/in.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <limits.h>
|
||
|
-#include "af_portability.h"
|
||
|
#include "watchdog.h"
|
||
|
#include "error.h"
|
||
|
|
||
|
@@ -54,12 +53,20 @@
|
||
|
int epsv_all_set;
|
||
|
|
||
|
/* address of client */
|
||
|
- sockaddr_storage_t client_addr;
|
||
|
+#ifdef INET6
|
||
|
+ struct sockaddr_storage client_addr;
|
||
|
+#else
|
||
|
+ struct sockaddr_in client_addr;
|
||
|
+#endif
|
||
|
char client_addr_str[ADDRPORT_STRLEN];
|
||
|
|
||
|
/* address of server (including IPv4 version) */
|
||
|
- sockaddr_storage_t server_addr;
|
||
|
+#ifdef INET6
|
||
|
+ struct sockaddr_storage server_addr;
|
||
|
struct sockaddr_in server_ipv4_addr;
|
||
|
+#else
|
||
|
+ struct sockaddr_in server_addr;
|
||
|
+#endif
|
||
|
|
||
|
/* telnet session to encapsulate control channel logic */
|
||
|
telnet_session_t *telnet_session;
|
||
|
@@ -70,7 +77,11 @@
|
||
|
/* data channel information, including type,
|
||
|
and client address or server port depending on type */
|
||
|
int data_channel;
|
||
|
- sockaddr_storage_t data_port;
|
||
|
+#ifdef INET6
|
||
|
+ struct sockaddr_storage data_port;
|
||
|
+#else
|
||
|
+ struct sockaddr_in data_port;
|
||
|
+#endif
|
||
|
int server_fd;
|
||
|
|
||
|
/* watchdog to handle timeout */
|
||
|
@@ -78,8 +89,8 @@
|
||
|
} ftp_session_t;
|
||
|
|
||
|
int ftp_session_init(ftp_session_t *f,
|
||
|
- const sockaddr_storage_t *client_addr,
|
||
|
- const sockaddr_storage_t *server_addr,
|
||
|
+ const struct sockaddr *client_addr,
|
||
|
+ const struct sockaddr *server_addr,
|
||
|
telnet_session_t *t,
|
||
|
const char *dir,
|
||
|
error_t *err);
|
||
|
diff -Naur oftpd-0.3.7.orig/src/oftpd.c oftpd-0.3.7/src/oftpd.c
|
||
|
--- oftpd-0.3.7.orig/src/oftpd.c 2001-05-27 22:40:27.000000000 +0000
|
||
|
+++ oftpd-0.3.7/src/oftpd.c 2010-01-05 21:50:11.160303781 +0000
|
||
|
@@ -300,7 +300,7 @@
|
||
|
|
||
|
|
||
|
fork_ret = fork();
|
||
|
- if (fork_ret == -1) {
|
||
|
+ if (fork_ret < 0) {
|
||
|
fprintf(stderr, "%s: error forking; %s\n", exe_name, strerror(errno));
|
||
|
exit(1);
|
||
|
}
|
||
|
@@ -313,7 +313,7 @@
|
||
|
exit(1);
|
||
|
}
|
||
|
fork_ret = fork();
|
||
|
- if (fork_ret == -1) {
|
||
|
+ if (fork_ret < 0) {
|
||
|
fprintf(stderr, "%s: error forking; %s\n", exe_name, strerror(errno));
|
||
|
exit(1);
|
||
|
}
|