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);
     }