From abb675cbe2a68504e07515c9916cb087f46ede2c Mon Sep 17 00:00:00 2001 From: geos_one Date: Tue, 5 Jan 2010 22:09:27 +0000 Subject: [PATCH] add oftp with proper ipv6 patch git-svn-id: https://svn.disconnected-by-peer.at/svn/linamh/trunk/linamh@1805 6952d904-891a-0410-993b-d76249ca496b --- net-ftp/oftpd/Manifest | 6 + net-ftp/oftpd/files/conf.d.oftpd-r1 | 17 + net-ftp/oftpd/files/init.d.oftpd-r1 | 29 + .../oftpd/files/oftpd-0.3.7-family-1.patch | 23 + .../oftpd/files/oftpd-0.3.7-ipv6rel2-1.patch | 1308 +++++++++++++++++ net-ftp/oftpd/oftpd-0.3.7-r5.ebuild | 40 + 6 files changed, 1423 insertions(+) create mode 100644 net-ftp/oftpd/Manifest create mode 100644 net-ftp/oftpd/files/conf.d.oftpd-r1 create mode 100644 net-ftp/oftpd/files/init.d.oftpd-r1 create mode 100644 net-ftp/oftpd/files/oftpd-0.3.7-family-1.patch create mode 100644 net-ftp/oftpd/files/oftpd-0.3.7-ipv6rel2-1.patch create mode 100644 net-ftp/oftpd/oftpd-0.3.7-r5.ebuild diff --git a/net-ftp/oftpd/Manifest b/net-ftp/oftpd/Manifest new file mode 100644 index 00000000..a85af1e1 --- /dev/null +++ b/net-ftp/oftpd/Manifest @@ -0,0 +1,6 @@ +AUX conf.d.oftpd-r1 578 RMD160 84ba38720a6a2ac8f0873ebbc4cab82f0394232c SHA1 821a500ff9a3d8e35f7aaf39c4c3935546399ae1 SHA256 6ba360cac50935ee9c8ed2961b95e57d7c63c5f63dc0ce7befb942756e054f62 +AUX init.d.oftpd-r1 722 RMD160 3e24790f4d56d2eff46ce810c8433a10f852c1ad SHA1 49e4d235f382eedd24b25955c1cf2764a94ee08b SHA256 cd3c98cc8bc3255503d9cc9946749d53d90410bf9d4c0a3a9ddb6819c87ab84e +AUX oftpd-0.3.7-family-1.patch 936 RMD160 0668323bb69fac190d8b1c4bcb0f5ed1c9c2b692 SHA1 945970c75cd4d23b4027f72521f4390a8b8ee4e6 SHA256 fe903d6fbb4a523f7b85dfb4c112f489da07764e8d67e15faa9b8380d400ba2a +AUX oftpd-0.3.7-ipv6rel2-1.patch 44765 RMD160 563fafe68e9e1be6b96116b7ae0c24204147b6f7 SHA1 5b7fd9a9b46cdcb2e3d081bdecb255b584826d42 SHA256 4ae576a749c26dd66432c273ec71c0d7fc34a4159cd7fd7760e484304eeb1ccc +DIST oftpd-0.3.7.tar.gz 97364 RMD160 9430607bf0c51847a4e4cc97c84be0495c931183 SHA1 d6d3ce43c009bb68736d50739e9a2f60bede99c1 SHA256 b135cd2bc6c54e03e5374845964eab73d5e567160c15bb4226c1c922b1e6d64e +EBUILD oftpd-0.3.7-r4.ebuild 1030 RMD160 0754f5ee486989d5703e9215b9765678d757fcb4 SHA1 65b01a4c08f8c5fe47e49c15388939fa9438173e SHA256 96739a8ff08100c97ca1d0f00bf5e5f803e7eb563ee8e9cc1bd85eced93ea4ad diff --git a/net-ftp/oftpd/files/conf.d.oftpd-r1 b/net-ftp/oftpd/files/conf.d.oftpd-r1 new file mode 100644 index 00000000..67c40c89 --- /dev/null +++ b/net-ftp/oftpd/files/conf.d.oftpd-r1 @@ -0,0 +1,17 @@ +# Please read the oftd(8) man page for a more detailed explaination of these +# variables. +# +# FTPUSER (user-name in the man page): +# Set this variable to the user to run the ftp daemon as +FTPUSER=ftp + +# FTPROOT (root-directory in the man page): +# The server uses chroot(2) to change the root directory of the server to this +# directory. When a user connects, this is the directory that they will start +# in, and is the top of their directory tree. +# +FTPROOT=/home/ftp + +# FTPPORT (TCP port) +# 22 is the standard ftp port, but you can change it here to something else +FTPPORT=22 diff --git a/net-ftp/oftpd/files/init.d.oftpd-r1 b/net-ftp/oftpd/files/init.d.oftpd-r1 new file mode 100644 index 00000000..a910b92f --- /dev/null +++ b/net-ftp/oftpd/files/init.d.oftpd-r1 @@ -0,0 +1,29 @@ +#!/sbin/runscript +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/net-ftp/oftpd/files/init.d.oftpd-r1,v 1.3 2009/06/13 19:31:06 grobian Exp $ + +depend() { + need net +} + +checkconfig() { + if [ -z "${FTPUSER}" ] || [ -z "${FTPROOT}" ] || [ -z "${FTPPORT}" ] ; then + eerror "You need to setup FTPUSER, FTPROOT and FTPPORT in /etc/conf.d/oftpd" + return 1 + fi +} + +start() { + checkconfig || return 1 + + ebegin "Starting oftpd" + start-stop-daemon --start --exec /usr/sbin/oftpd -- -p ${FTPPORT} ${FTPUSER} ${FTPROOT} + eend $? +} + +stop() { + ebegin "Stopping oftpd" + start-stop-daemon --stop --quiet --exec /usr/sbin/oftpd + eend $? +} diff --git a/net-ftp/oftpd/files/oftpd-0.3.7-family-1.patch b/net-ftp/oftpd/files/oftpd-0.3.7-family-1.patch new file mode 100644 index 00000000..490612d8 --- /dev/null +++ b/net-ftp/oftpd/files/oftpd-0.3.7-family-1.patch @@ -0,0 +1,23 @@ +Submitted By: Mario Fetka (geos_one) (mario dot fetka at gmail dot com) +Date: 2010-01-05 +Initial Package Version: 0.3.7 +Origin: http://gentoo.mirror.solnet.ch/net-ftp/oftpd/files/oftpd-0.3.7-family.patch +Upstream Status: unkonwn +Description: dont crash on wrong protocol family + +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 2010-01-05 21:56:48.540303543 +0000 ++++ oftpd-0.3.7/src/ftp_session.c 2010-01-05 21:57:29.995553119 +0000 +@@ -708,10 +708,12 @@ + 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)"); ++ return; + } + #else + if (((struct sockaddr *)host_port)->sa_family != AF_INET) { + reply(f, 521, "Only IPv4 supported, address family (4)"); ++ return; + } + #endif + diff --git a/net-ftp/oftpd/files/oftpd-0.3.7-ipv6rel2-1.patch b/net-ftp/oftpd/files/oftpd-0.3.7-ipv6rel2-1.patch new file mode 100644 index 00000000..36c76209 --- /dev/null +++ b/net-ftp/oftpd/files/oftpd-0.3.7-ipv6rel2-1.patch @@ -0,0 +1,1308 @@ +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 ++#include ++#include ++ ++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 +-#include + + /* _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 header file. */ + #undef HAVE_LIMITS_H + ++/* Define if you have the header file. */ ++#undef HAVE_SYSLOG_H ++ + /* Define if you have the header file. */ + #undef HAVE_SYS_TIME_H + + /* Define if you have the header file. */ + #undef HAVE_SYS_TYPES_H + +-/* Define if you have the header file. */ +-#undef HAVE_SYSLOG_H +- + /* Define if you have the 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 + #include + #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 + #include + #include +-#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 + #include + #include +-#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); + } diff --git a/net-ftp/oftpd/oftpd-0.3.7-r5.ebuild b/net-ftp/oftpd/oftpd-0.3.7-r5.ebuild new file mode 100644 index 00000000..81ae2b62 --- /dev/null +++ b/net-ftp/oftpd/oftpd-0.3.7-r5.ebuild @@ -0,0 +1,40 @@ +# Copyright 1999-2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +EAPI=2 +inherit eutils autotools + +DESCRIPTION="Secure, small, anonymous only ftpd" +HOMEPAGE="http://www.time-travellers.org/oftpd" +SRC_URI="http://www.time-travellers.org/oftpd/${P}.tar.gz" + +LICENSE="as-is" +SLOT="0" +KEYWORDS="~amd64 ~arm ~ppc ~ppc64 ~sh ~sparc ~x86" +IUSE="ipv6" + +DEPEND="net-ftp/ftpbase" +RDEPEND="${DEPEND}" + +src_prepare() { + epatch "${FILESDIR}"/oftpd-0.3.7-ipv6rel2-1.patch + # Don't crash when using an unsupported address family, #159178. + epatch "${FILESDIR}"/oftpd-0.3.7-family-1.patch + eautoreconf +} + +src_configure() { + # local myconf + # ipv6 support busted according to lamer + # use ipv6 && myconf="${myconf} --enable-ipv6" + econf --bindir=/usr/sbin $(use_enable ipv6) || die +} + +src_install() { + emake DESTDIR="${D}" install || die + dodoc AUTHORS BUGS FAQ NEWS README TODO + keepdir /home/ftp + newinitd "${FILESDIR}"/init.d.oftpd-r1 oftpd + newconfd "${FILESDIR}"/conf.d.oftpd-r1 oftpd +}