Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 103284 Details for
Bug 157005
net-ftp/oftpd-0.3.7: Fix for ipv6 support
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch against oftpd-0.3.7
oftpd-0.3.7-r3.patch (text/plain), 18.39 KB, created by
Bruno
on 2006-12-03 09:44:25 UTC
(
hide
)
Description:
Patch against oftpd-0.3.7
Filename:
MIME Type:
Creator:
Bruno
Created:
2006-12-03 09:44:25 UTC
Size:
18.39 KB
patch
obsolete
>diff -NurpP oftpd-0.3.7/src/daemon_assert.c oftpd-0.3.7-r3/src/daemon_assert.c >--- oftpd-0.3.7/src/daemon_assert.c 2001-04-22 09:50:41.000000000 +0200 >+++ oftpd-0.3.7-r3/src/daemon_assert.c 2006-12-03 13:43:47.459738389 +0100 >@@ -3,6 +3,7 @@ > #include <pthread.h> > #include <syslog.h> > #include <stdio.h> >+#include <stdlib.h> > > #ifndef NDEBUG > void daemon_assert_fail(const char *assertion, >diff -NurpP oftpd-0.3.7/src/ftp_command.c oftpd-0.3.7-r3/src/ftp_command.c >--- oftpd-0.3.7/src/ftp_command.c 2004-03-25 21:46:57.000000000 +0100 >+++ oftpd-0.3.7-r3/src/ftp_command.c 2006-12-03 13:43:47.459738389 +0100 >@@ -137,7 +137,7 @@ int ftp_command_parse(const char *input, > 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; > } >@@ -325,6 +325,7 @@ static const char *parse_host_port(struc > struct in_addr in_addr; > > daemon_assert(addr != NULL); >+ daemon_assert(SAFAM(addr) == AF_INET); > daemon_assert(s != NULL); > > /* scan in 5 pairs of "#," */ >@@ -448,8 +449,8 @@ static const char *parse_host_port_long( > if (port_len != 2) { > return NULL; > } >- memcpy(&SINADDR(sa), addr, addr_len); >- SINPORT(sa) = htons((port[0] << 8) + port[1]); >+ memcpy(&SIN4ADDR(sa), addr, addr_len); >+ SIN4PORT(sa) = htons((port[0] << 8) + port[1]); > } > #ifdef INET6 > else if (family == 6) { >@@ -461,7 +462,7 @@ static const char *parse_host_port_long( > return NULL; > } > memcpy(&SIN6ADDR(sa), addr, addr_len); >- SINPORT(sa) = htons((port[0] << 8) + port[1]); >+ SIN6PORT(sa) = htons((port[0] << 8) + port[1]); > } > #endif > else { >@@ -550,7 +551,7 @@ static const char *parse_host_port_ext(s > #else > { > struct addrinfo hints; >- struct *res; >+ struct addrinfo*res; > > memset(&hints, 0, sizeof(hints)); > hints.ai_flags = AI_NUMERICHOST; >@@ -567,7 +568,12 @@ static const char *parse_host_port_ext(s > #endif /* INET6 */ > > SAFAM(sa) = family; >- SINPORT(sa) = htons(port); >+#ifdef INET6 >+ if (family == AF_INET6) >+ SIN6PORT(sa) = htons(port); >+ else >+#endif >+ SIN4PORT(sa) = htons(port); > > /* return new pointer */ > return s; >diff -NurpP oftpd-0.3.7/src/ftp_listener.c oftpd-0.3.7-r3/src/ftp_listener.c >--- oftpd-0.3.7/src/ftp_listener.c 2001-05-11 01:29:46.000000000 +0200 >+++ oftpd-0.3.7-r3/src/ftp_listener.c 2006-12-03 14:20:52.382787389 +0100 >@@ -135,17 +135,23 @@ int ftp_listener_init(ftp_listener_t *f, > * -- Matthew Danish [3/20/2001] > */ > >+ hints.ai_flags = AI_PASSIVE; > #ifdef INET6 >+ /* For IPv6, try provided host/address as IPv6 address, but fall >+ * back to IPv4 if we fail >+ */ > hints.ai_family = AF_INET6; >+ gai_err = getaddrinfo(address, NULL, &hints, &res); >+ if (gai_err == EAI_ADDRFAMILY) { >+ hints.ai_family = AF_INET; >+ gai_err = getaddrinfo(address, NULL, &hints, &res); >+ } > #else > hints.ai_family = AF_INET; >-#endif >- >- hints.ai_flags = AI_PASSIVE; >- > gai_err = getaddrinfo(address, NULL, &hints, &res); >+#endif > if (gai_err != 0) { >- error_init(err, gai_err, "error parsing server socket address; %s", >+ error_init(err, -gai_err, "error parsing server socket address; %s", > gai_strerror(gai_err)); > return 0; > } >@@ -154,17 +160,25 @@ int ftp_listener_init(ftp_listener_t *f, > freeaddrinfo(res); > } > >- if (port == 0) { >- SINPORT(&sock_addr) = htons(DEFAULT_FTP_PORT); >- } else { >- SINPORT(&sock_addr) = htons(port); >- } >- >- >- inet_ntop_ret = inet_ntop(SAFAM(&sock_addr), >- (void *)&SINADDR(&sock_addr), >+#ifdef INET6 >+ if (SAFAM(&sock_addr) == AF_INET6) >+ SIN6PORT(&sock_addr) = htons(port == 0 ? DEFAULT_FTP_PORT : port); >+ else >+#endif >+ SIN4PORT(&sock_addr) = htons(port == 0 ? DEFAULT_FTP_PORT : port); >+#ifdef INET6 >+ if (SAFAM(&sock_addr) == AF_INET6) >+ inet_ntop_ret = inet_ntop(AF_INET6, >+ (void *)&SIN6ADDR(&sock_addr), > buf, > sizeof(buf)); >+ else >+#endif >+ inet_ntop_ret = inet_ntop(SAFAM(&sock_addr), >+ (void *)&SIN4ADDR(&sock_addr), >+ buf, >+ sizeof(buf)); >+ > if (inet_ntop_ret == NULL) { > error_init(err, errno, "error converting server address to ASCII; %s", > strerror(errno)); >@@ -177,7 +191,7 @@ int ftp_listener_init(ftp_listener_t *f, > > > /* okay, finally do some socket manipulation */ >- fd = socket(AF_INET, SOCK_STREAM, 0); >+ fd = socket(SAFAM(&sock_addr), SOCK_STREAM, 0); > if (fd == -1) { > error_init(err, errno, "error creating socket; %s", strerror(errno)); > return 0; >@@ -194,7 +208,7 @@ int ftp_listener_init(ftp_listener_t *f, > } > > if (bind(fd, (struct sockaddr *)&sock_addr, >- sizeof(struct sockaddr_in)) != 0) >+ SAFAM(&sock_addr) == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0) > { > close(fd); > error_init(err, errno, "error binding address; %s", strerror(errno)); >@@ -461,7 +475,7 @@ static char *addr2string(const sockaddr_ > 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; >diff -NurpP oftpd-0.3.7/src/ftp_session.c oftpd-0.3.7-r3/src/ftp_session.c >--- oftpd-0.3.7/src/ftp_session.c 2004-03-25 21:46:40.000000000 +0100 >+++ oftpd-0.3.7-r3/src/ftp_session.c 2006-12-03 16:48:17.175552389 +0100 >@@ -44,6 +44,7 @@ > #define ADDRPORT_STRLEN 58 > > /* prototypes */ >+static int alloc_ipv4(ftp_session_t *f); > static int invariant(const ftp_session_t *f); > static void reply(ftp_session_t *f, int code, const char *fmt, ...); > static void change_dir(ftp_session_t *f, const char *new_dir); >@@ -137,39 +138,7 @@ int ftp_session_init(ftp_session_t *f, > daemon_assert(strlen(dir) <= PATH_MAX); > 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) { >- struct addrinfo hints; >- struct addrinfo *res; >- int errcode; >- >- /* getaddrinfo() does the job nicely */ >- 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", >- gai_strerror(errcode)); >- return 0; >- } >- >- /* 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); >- >- /* 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; >- } >-#else >- f->server_ipv4_addr = *server_addr; >-#endif >+ memset(&f->server_ipv4_addr, 0, sizeof(f->server_ipv4_addr)); > > f->session_active = 1; > f->command_number = 0; >@@ -291,6 +260,46 @@ void ftp_session_destroy(ftp_session_t * > } > } > >+#ifdef INET6 >+static int alloc_ipv4(ftp_session_t *f) >+{ >+ /* if the control connection is on IPv6, we need to get an IPv4 address */ >+ /* to bind the socket to */ >+ if (SSFAM(&f->server_addr) == AF_INET6) { >+ struct addrinfo hints; >+ struct addrinfo *res; >+ int errcode; >+ >+ /* getaddrinfo() does the job nicely */ >+ memset(&hints, 0, sizeof(struct addrinfo)); >+ hints.ai_family = AF_INET; >+ hints.ai_flags = AI_PASSIVE; >+ if ((errcode = getaddrinfo(NULL, "ftp", &hints, &res)) != 0) { >+ syslog(LOG_ERR, "Unable to determing IPv4 address: %s", gai_strerror(errcode)); >+ return 0; >+ } >+ >+ /* let's sanity check */ >+ daemon_assert(res != NULL); >+ daemon_assert(sizeof(f->server_ipv4_addr) >= res->ai_addrlen); >+ daemon_assert(SSFAM(&f->server_ipv4_addr) == 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(&f->server_addr) == AF_INET); >+ memcpy(&f->server_ipv4_addr, &f->server_addr, sizeof(f->server_ipv4_addr)); >+ } >+ return 1; >+} >+#else >+inline static int alloc_ipv4(ftp_session_t *f) >+{ >+ return 0; >+} >+#endif >+ > #ifndef NDEBUG > static int invariant(const ftp_session_t *f) > { >@@ -333,7 +342,8 @@ static int invariant(const ftp_session_t > return 0; > } > break; >- case DATA_PASSIVE: >+ case DATA_PASSIVE_4: >+ case DATA_PASSIVE_6: > if (f->server_fd < 0) { > return 0; > } >@@ -424,16 +434,16 @@ static void get_addr_str(const sockaddr_ > /* buf must be able to contain (at least) a string representing an > * ipv4 addr, followed by the string " port " (6 chars) and the port > * number (which is 5 chars max), plus the '\0' character. */ >- daemon_assert(bufsiz >= (INET_ADDRSTRLEN + 12)); >+ daemon_assert(bufsiz >= (INET6_ADDRSTRLEN + 12)); > >- error = getnameinfo(client_addr, sizeof(sockaddr_storage_t), buf, >+ error = getnameinfo((struct sockaddr *)s, sizeof(sockaddr_storage_t), 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", ntohs(SINPORT(s))); > } > #else > static void get_addr_str(const sockaddr_storage_t *s, char *buf, int bufsiz) >@@ -639,7 +649,7 @@ static void set_port(ftp_session_t *f, c > reply(f, 500, "Port may not be less than 1024, which is reserved."); > } else { > /* close any outstanding PASSIVE port */ >- if (f->data_channel == DATA_PASSIVE) { >+ if (f->data_channel == DATA_PASSIVE_4 || f->data_channel == DATA_PASSIVE_6) { > close(f->server_fd); > f->server_fd = -1; > } >@@ -733,12 +743,19 @@ static int set_pasv(ftp_session_t *f, so > > for (;;) { > port = get_passive_port(); >- SINPORT(bind_addr) = htons(port); >+#ifdef INET6 >+ if (SAFAM(bind_addr) == AF_INET6) >+ SIN6PORT(bind_addr) = htons(port); >+ else >+ SIN4PORT(bind_addr) = htons(port); > if (bind(socket_fd, (struct sockaddr *)bind_addr, >- sizeof(struct sockaddr)) == 0) >- { >+ SAFAM(bind_addr) == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) == 0) > break; >- } >+#else >+ SIN4PORT(bind_addr) = htons(port); >+ if (bind(socket_fd, (struct sockaddr *)bind_addr, sizeof(struct sockaddr_in)) == 0) >+ break; >+#endif > if (errno != EADDRINUSE) { > reply(f, 500, "Error binding server port; %s.", strerror(errno)); > close(socket_fd); >@@ -771,14 +788,28 @@ static void do_pasv(ftp_session_t *f, co > goto exit_pasv; > } > >- socket_fd = set_pasv(f, &f->server_ipv4_addr); >+ if (SAFAM(&f->server_addr) == AF_INET) >+ socket_fd = set_pasv(f, (sockaddr_storage_t *)&f->server_addr); >+ else if (SAFAM(&f->server_ipv4_addr) == AF_UNSPEC) { >+ if (!alloc_ipv4(f)) { >+ reply(f, 522, "PASV not possible, use EPSV"); >+ goto exit_pasv; >+ } >+ socket_fd = set_pasv(f, (sockaddr_storage_t *)&f->server_ipv4_addr); >+ } else >+ socket_fd = set_pasv(f, (sockaddr_storage_t *)&f->server_ipv4_addr); > if (socket_fd == -1) { > goto exit_pasv; > } > > /* report port to client */ >- addr = ntohl(f->server_ipv4_addr.sin_addr.s_addr); >- port = ntohs(f->server_ipv4_addr.sin_port); >+ if (SAFAM(&f->server_addr) == AF_INET) { >+ addr = ntohl(SIN4ADDR(&f->server_addr).s_addr); >+ port = ntohs(SIN4PORT(&f->server_addr)); >+ } else { >+ addr = ntohl(SIN4ADDR(&f->server_ipv4_addr).s_addr); >+ port = ntohs(SIN4PORT(&f->server_ipv4_addr)); >+ } > reply(f, 227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d).", > addr >> 24, > (addr >> 16) & 0xff, >@@ -788,10 +819,10 @@ static void do_pasv(ftp_session_t *f, co > port & 0xff); > > /* close any outstanding PASSIVE port */ >- if (f->data_channel == DATA_PASSIVE) { >+ if (f->data_channel == DATA_PASSIVE_4 || f->data_channel == DATA_PASSIVE_6) { > close(f->server_fd); > } >- f->data_channel = DATA_PASSIVE; >+ f->data_channel = DATA_PASSIVE_4; > f->server_fd = socket_fd; > > exit_pasv: >@@ -841,10 +872,14 @@ static void do_lpsv(ftp_session_t *f, co > reply(f, 228, "Entering Long Passive Mode %s", addr); > > /* close any outstanding PASSIVE port */ >- if (f->data_channel == DATA_PASSIVE) { >+ if (f->data_channel == DATA_PASSIVE_4 || f->data_channel == DATA_PASSIVE_6) { > close(f->server_fd); > } >- f->data_channel = DATA_PASSIVE; >+#ifdef INET6 >+ f->data_channel = SSFAM(&f->server_addr) == AF_INET6 ? DATA_PASSIVE_6 : DATA_PASSIVE_4; >+#else >+ f->data_channel = DATA_PASSIVE_4; >+#endif > f->server_fd = socket_fd; > > exit_lpsv: >@@ -875,11 +910,24 @@ static void do_epsv(ftp_session_t *f, co > reply(f, 200, "EPSV ALL command successful."); > goto exit_epsv; > case 1: >- addr = (sockaddr_storage_t *)&f->server_ipv4_addr; >+ if (SAFAM(&f->server_addr) == AF_INET) >+ addr = &f->server_addr; >+ else if (SAFAM(&f->server_ipv4_addr) == AF_UNSPEC) { >+ if (!alloc_ipv4(f)) { >+ reply(f, 522, "Only IPv6 supported, use (2)"); >+ goto exit_epsv; >+ } >+ addr = &f->server_ipv4_addr; >+ } else >+ addr = &f->server_ipv4_addr; > break; > #ifdef INET6 > case 2: >- addr = &f->server_addr; >+ if (SAFAM(&f->server_addr) == AF_INET) { >+ reply(f, 522, "Only IPv4 supported, use (1)"); >+ goto exit_epsv; >+ } >+ addr = &f->server_addr; > break; > default: > reply(f, 522, "Only IPv4 and IPv6 supported, use (1,2)"); >@@ -903,10 +951,16 @@ static void do_epsv(ftp_session_t *f, co > ntohs(SINPORT(&f->server_addr))); > > /* close any outstanding PASSIVE port */ >- if (f->data_channel == DATA_PASSIVE) { >+ if (f->data_channel == DATA_PASSIVE_4 || f->data_channel == DATA_PASSIVE_6) { > close(f->server_fd); > } >- f->data_channel = DATA_PASSIVE; >+ f->data_port = *addr; >+#ifdef INET6 >+ if (cmd->num_arg == 0) >+ f->data_channel = SAFAM(&f->server_addr) == AF_INET6 ? DATA_PASSIVE_6 : DATA_PASSIVE_4; >+ else >+#endif >+ f->data_channel = cmd->arg[0].num == 2 ? DATA_PASSIVE_6 : DATA_PASSIVE_4; > f->server_fd = socket_fd; > > exit_epsv: >@@ -1278,11 +1332,12 @@ static void do_stor(ftp_session_t *f, co > static int open_connection(ftp_session_t *f) > { > int socket_fd; >- struct sockaddr_in addr; >+ sockaddr_storage_t addr; > unsigned addr_len; > > daemon_assert((f->data_channel == DATA_PORT) || >- (f->data_channel == DATA_PASSIVE)); >+ (f->data_channel == DATA_PASSIVE_4) || >+ (f->data_channel == DATA_PASSIVE_6)); > > if (f->data_channel == DATA_PORT) { > socket_fd = socket(SSFAM(&f->data_port), SOCK_STREAM, 0); >@@ -1298,9 +1353,9 @@ static int open_connection(ftp_session_t > return -1; > } > } else { >- daemon_assert(f->data_channel == DATA_PASSIVE); >+ daemon_assert(f->data_channel == DATA_PASSIVE_4 || f->data_channel == DATA_PASSIVE_6); > >- 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,24 +1365,26 @@ static int open_connection(ftp_session_t > /* 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; >- } >- } >-#else >- if (memcmp(&f->client_addr.sin_addr, >- &addr.sin_addr, sizeof(struct in_addr))) >- { >- reply(f, 425, >- "Error accepting connection; connection from invalid IP."); >- close(socket_fd); >- return -1; >+ if (SAFAM(&addr) == SSFAM(&f->client_addr)) { >+ if (SAFAM(&addr) == AF_INET6) { >+ if (memcmp(&SIN6ADDR(&f->client_addr), &SIN6ADDR(&addr), >+ sizeof(struct in6_addr))) { >+ reply(f, 425, "Error accepting connection; " >+ "connection from invalid IP."); >+ close(socket_fd); >+ return -1; >+ } >+ } else { >+#endif >+ if (memcmp(&SIN4ADDR(&f->client_addr), &SIN4ADDR(&addr), >+ sizeof(struct in_addr))) { >+ reply(f, 425, "Error accepting connection; " >+ "connection from invalid IP."); >+ close(socket_fd); >+ return -1; >+ } >+#ifdef INET6 >+ } > } > #endif > } >@@ -1822,9 +1879,17 @@ static int ip_equal(const sockaddr_stora > if (SSFAM(a) != SSFAM(b)) { > return 0; > } >- if (memcmp(&SINADDR(a), &SINADDR(b), sizeof(SINADDR(a))) != 0) { >- return 0; >+#ifdef INET6 >+ if (SSFAM(a) == AF_INET6) { >+ if (memcmp(&SIN6ADDR(a), &SIN6ADDR(b), sizeof(struct in6_addr)) != 0) >+ return 0; >+ } else { >+#endif >+ if (memcmp(&SIN4ADDR(a), &SIN4ADDR(b), sizeof(struct in_addr)) != 0) >+ return 0; >+#ifdef INET6 > } >+#endif > return 1; > } > >diff -NurpP oftpd-0.3.7/src/ftp_session.h oftpd-0.3.7-r3/src/ftp_session.h >--- oftpd-0.3.7/src/ftp_session.h 2001-05-11 01:29:12.000000000 +0200 >+++ oftpd-0.3.7-r3/src/ftp_session.h 2006-12-03 13:43:47.459738389 +0100 >@@ -25,8 +25,9 @@ > #define STRU_RECORD 1 > > /* data path chosen */ >-#define DATA_PORT 0 >-#define DATA_PASSIVE 1 >+#define DATA_PORT 0 >+#define DATA_PASSIVE_4 1 >+#define DATA_PASSIVE_6 2 > > /* space required for text representation of address and port, > e.g. "192.168.0.1 port 1024" or >@@ -59,7 +60,7 @@ typedef struct { > > /* address of server (including IPv4 version) */ > sockaddr_storage_t server_addr; >- struct sockaddr_in server_ipv4_addr; >+ sockaddr_storage_t server_ipv4_addr; > > /* telnet session to encapsulate control channel logic */ > telnet_session_t *telnet_session;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 157005
: 103284 |
211361
|
220543
|
220545
|
220547