EXPERIMENTAL ftp IPV6 Support
This commit is contained in:
parent
c3733722e6
commit
34401dbd7e
@ -199,18 +199,18 @@ void close_tcp_connection(struct ftpclient* client) {
|
|||||||
client->data_socket = -1;
|
client->data_socket = -1;
|
||||||
}
|
}
|
||||||
if (strlen(client->data_ip) > 0) {
|
if (strlen(client->data_ip) > 0) {
|
||||||
memset(client->data_ip, 0, 20);
|
memset(client->data_ip, 0, INET6_ADDRSTRLEN);
|
||||||
client->data_port = 0;
|
client->data_port = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int open_tcp_connection(struct ftpserver *cfg, struct ftpclient *client) {
|
int open_tcp_connection(struct ftpserver *cfg, struct ftpclient *client) {
|
||||||
if (strlen(client->data_ip) != 0) {
|
if (strlen(client->data_ip) != 0) {
|
||||||
client->data_socket = socket(AF_INET, SOCK_STREAM, 0);
|
client->data_socket = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
struct sockaddr_in servaddr;
|
struct sockaddr_in6 servaddr;
|
||||||
servaddr.sin_family = AF_INET;
|
servaddr.sin6_family = AF_INET6;
|
||||||
servaddr.sin_port = htons(client->data_port);
|
servaddr.sin6_port = htons(client->data_port);
|
||||||
if (inet_aton(client->data_ip, &(servaddr.sin_addr)) <= 0) {
|
if (inet_pton(AF_INET6, client->data_ip, &(servaddr.sin6_addr)) <= 0) {
|
||||||
fprintf(stderr, "Error in port command\n");
|
fprintf(stderr, "Error in port command\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -220,7 +220,7 @@ int open_tcp_connection(struct ftpserver *cfg, struct ftpclient *client) {
|
|||||||
}
|
}
|
||||||
} else if (client->data_srv_socket != 0) {
|
} else if (client->data_srv_socket != 0) {
|
||||||
socklen_t sock = sizeof(struct sockaddr);
|
socklen_t sock = sizeof(struct sockaddr);
|
||||||
struct sockaddr_in data_client;
|
struct sockaddr_in6 data_client;
|
||||||
client->data_socket = accept(client->data_srv_socket, (struct sockaddr*) &data_client, &sock);
|
client->data_socket = accept(client->data_srv_socket, (struct sockaddr*) &data_client, &sock);
|
||||||
|
|
||||||
if (client->data_socket < 0) {
|
if (client->data_socket < 0) {
|
||||||
@ -295,7 +295,7 @@ void handle_STOR(struct ftpserver *cfg, struct ftpclient *client, char *path) {
|
|||||||
send_msg(client, "451 STOR Failed.\r\n");
|
send_msg(client, "451 STOR Failed.\r\n");
|
||||||
} else {
|
} else {
|
||||||
client->data_socket = -1;
|
client->data_socket = -1;
|
||||||
memset(client->data_ip, 0, 20);
|
memset(client->data_ip, 0, INET6_ADDRSTRLEN);
|
||||||
client->data_srv_socket = -1;
|
client->data_srv_socket = -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -309,6 +309,52 @@ void handle_STOR(struct ftpserver *cfg, struct ftpclient *client, char *path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_EPSV(struct ftpserver *cfg, struct ftpclient *client) {
|
||||||
|
if (client->data_socket > 0) {
|
||||||
|
close(client->data_socket);
|
||||||
|
client->data_socket = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client->data_srv_socket > 0) {
|
||||||
|
close(client->data_srv_socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
client->data_srv_socket = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
|
if (client->data_srv_socket < 0) {
|
||||||
|
send_msg(client, "500 EPSV failure.\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct sockaddr_in6 server;
|
||||||
|
server.sin6_family = AF_INET6;
|
||||||
|
server.sin6_addr = in6addr_any;
|
||||||
|
|
||||||
|
cfg->last_passive_port++;
|
||||||
|
if (cfg->last_passive_port == cfg->max_passive_port) {
|
||||||
|
cfg->last_passive_port = cfg->min_passive_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
int port = cfg->last_passive_port;
|
||||||
|
|
||||||
|
server.sin6_port = htons(port);
|
||||||
|
|
||||||
|
if (bind(client->data_srv_socket, (struct sockaddr*) &server, sizeof(struct sockaddr)) < 0) {
|
||||||
|
send_msg(client, "500 EPSV failure\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(client->data_srv_socket, 1) < 0) {
|
||||||
|
send_msg(client, "500 EPSV failure\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in6 file_addr;
|
||||||
|
socklen_t file_sock_len = sizeof(struct sockaddr);
|
||||||
|
getsockname(client->data_srv_socket, (struct sockaddr*) &file_addr, &file_sock_len);
|
||||||
|
char buffer[256];
|
||||||
|
sprintf(buffer, "229 Entering Extended Passive Mode (|||%d|)", port);
|
||||||
|
|
||||||
|
send_msg(client, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
void handle_PASV(struct ftpserver *cfg, struct ftpclient *client) {
|
void handle_PASV(struct ftpserver *cfg, struct ftpclient *client) {
|
||||||
char buffer[200];
|
char buffer[200];
|
||||||
char *ipcpy;
|
char *ipcpy;
|
||||||
@ -322,14 +368,14 @@ void handle_PASV(struct ftpserver *cfg, struct ftpclient *client) {
|
|||||||
close(client->data_srv_socket);
|
close(client->data_srv_socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
client->data_srv_socket = socket(AF_INET, SOCK_STREAM, 0);
|
client->data_srv_socket = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
if (client->data_srv_socket < 0) {
|
if (client->data_srv_socket < 0) {
|
||||||
send_msg(client, "426 PASV failure.\r\n");
|
send_msg(client, "426 PASV failure.\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct sockaddr_in server;
|
struct sockaddr_in6 server;
|
||||||
server.sin_family = AF_INET;
|
server.sin6_family = AF_INET6;
|
||||||
server.sin_addr.s_addr = INADDR_ANY;
|
server.sin6_addr = in6addr_any;
|
||||||
|
|
||||||
cfg->last_passive_port++;
|
cfg->last_passive_port++;
|
||||||
if (cfg->last_passive_port == cfg->max_passive_port) {
|
if (cfg->last_passive_port == cfg->max_passive_port) {
|
||||||
@ -338,7 +384,7 @@ void handle_PASV(struct ftpserver *cfg, struct ftpclient *client) {
|
|||||||
|
|
||||||
int port = cfg->last_passive_port;
|
int port = cfg->last_passive_port;
|
||||||
|
|
||||||
server.sin_port = htons(port);
|
server.sin6_port = htons(port);
|
||||||
|
|
||||||
if (bind(client->data_srv_socket, (struct sockaddr*) &server, sizeof(struct sockaddr)) < 0) {
|
if (bind(client->data_srv_socket, (struct sockaddr*) &server, sizeof(struct sockaddr)) < 0) {
|
||||||
send_msg(client, "426 PASV failure\r\n");
|
send_msg(client, "426 PASV failure\r\n");
|
||||||
@ -349,23 +395,11 @@ void handle_PASV(struct ftpserver *cfg, struct ftpclient *client) {
|
|||||||
send_msg(client, "426 PASV failure\r\n");
|
send_msg(client, "426 PASV failure\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sockaddr_in file_addr;
|
struct sockaddr_in6 file_addr;
|
||||||
socklen_t file_sock_len = sizeof(struct sockaddr);
|
socklen_t file_sock_len = sizeof(struct sockaddr_in6);
|
||||||
getsockname(client->data_srv_socket, (struct sockaddr*) &file_addr, &file_sock_len);
|
getsockname(client->data_srv_socket, (struct sockaddr*) &file_addr, &file_sock_len);
|
||||||
|
|
||||||
ipcpy = strdup(client->hostip);
|
|
||||||
|
|
||||||
ipptr = strtok(ipcpy, ".");
|
|
||||||
|
|
||||||
strcpy(buffer, "227 Entering Passive Mode (");
|
strcpy(buffer, "227 Entering Passive Mode (");
|
||||||
|
|
||||||
while (ipptr != NULL) {
|
|
||||||
sprintf(buffer, "%s%s,", buffer, ipptr);
|
|
||||||
ipptr = strtok(NULL, ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(buffer, "%s%d,%d)\r\n", buffer, port / 256, port % 256);
|
|
||||||
|
|
||||||
send_msg(client, buffer);
|
send_msg(client, buffer);
|
||||||
free(ipcpy);
|
free(ipcpy);
|
||||||
}
|
}
|
||||||
@ -392,7 +426,7 @@ void handle_RETR(struct ftpserver *cfg, struct ftpclient *client, char *file) {
|
|||||||
if (pid > 0) {
|
if (pid > 0) {
|
||||||
// nothing
|
// nothing
|
||||||
client->data_socket = -1;
|
client->data_socket = -1;
|
||||||
memset(client->data_ip, 0, 20);
|
memset(client->data_ip, 0, INET6_ADDRSTRLEN);
|
||||||
client->data_srv_socket = -1;
|
client->data_srv_socket = -1;
|
||||||
|
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
@ -443,7 +477,7 @@ void handle_LIST(struct ftpserver *cfg, struct ftpclient *client) {
|
|||||||
if (pid > 0) {
|
if (pid > 0) {
|
||||||
// nothing
|
// nothing
|
||||||
client->data_socket = -1;
|
client->data_socket = -1;
|
||||||
memset(client->data_ip, 0, 20);
|
memset(client->data_ip, 0, INET6_ADDRSTRLEN);
|
||||||
client->data_srv_socket = -1;
|
client->data_srv_socket = -1;
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
dirp = opendir(newpath);
|
dirp = opendir(newpath);
|
||||||
@ -498,11 +532,55 @@ void handle_PORT(struct ftpserver *cfg, struct ftpclient *client, char *arg) {
|
|||||||
int a,b,c,d,e,f;
|
int a,b,c,d,e,f;
|
||||||
|
|
||||||
sscanf(arg, "%d,%d,%d,%d,%d,%d", &a, &b, &c, &d, &e, &f);
|
sscanf(arg, "%d,%d,%d,%d,%d,%d", &a, &b, &c, &d, &e, &f);
|
||||||
sprintf(client->data_ip, "%d.%d.%d.%d", a, b, c, d);
|
sprintf(client->data_ip, "::ffff:%d.%d.%d.%d", a, b, c, d);
|
||||||
client->data_port = e * 256 + f;
|
client->data_port = e * 256 + f;
|
||||||
send_msg(client, "200 PORT command successful.\r\n");
|
send_msg(client, "200 PORT command successful.\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_EPRT(struct ftpserver *cfg, struct ftpclient *client, char *arg) {
|
||||||
|
if (client->data_socket > 0) {
|
||||||
|
close(client->data_socket);
|
||||||
|
}
|
||||||
|
int a,b,c,d,e,f;
|
||||||
|
char delim[2];
|
||||||
|
char *ptr;
|
||||||
|
int addrtype;
|
||||||
|
|
||||||
|
delim[0] = arg[0];
|
||||||
|
delim[1] = '\0';
|
||||||
|
|
||||||
|
ptr = strtok(arg, delim);
|
||||||
|
if (ptr != NULL) {
|
||||||
|
addrtype = atoi(ptr);
|
||||||
|
if (addrtype == 1) {
|
||||||
|
//ipv4
|
||||||
|
ptr = strtok(NULL, delim);
|
||||||
|
if (ptr != NULL) {
|
||||||
|
sprintf(client->data_ip, "::ffff:%s", ptr);
|
||||||
|
ptr = strtok(NULL, delim);
|
||||||
|
if (ptr != NULL) {
|
||||||
|
client->data_port = atoi(ptr);
|
||||||
|
send_msg(client, "200 EPRT command successful.\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (addrtype == 2) {
|
||||||
|
//ipv6
|
||||||
|
ptr = strtok(NULL, delim);
|
||||||
|
if (ptr != NULL) {
|
||||||
|
sprintf(client->data_ip, "%s", ptr);
|
||||||
|
ptr = strtok(NULL, delim);
|
||||||
|
if (ptr != NULL) {
|
||||||
|
client->data_port = atoi(ptr);
|
||||||
|
send_msg(client, "200 EPRT command successful.\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handle_CWD(struct ftpserver *cfg, struct ftpclient *client, char *dir) {
|
void handle_CWD(struct ftpserver *cfg, struct ftpclient *client, char *dir) {
|
||||||
char *newpath;
|
char *newpath;
|
||||||
char fullpath[PATH_MAX];
|
char fullpath[PATH_MAX];
|
||||||
@ -689,6 +767,12 @@ int handle_client(struct ftpserver *cfg, struct ftpclient *client, char *buf, in
|
|||||||
} else
|
} else
|
||||||
if (strcmp(cmd, "STOR") == 0) {
|
if (strcmp(cmd, "STOR") == 0) {
|
||||||
handle_STOR(cfg, client, argument);
|
handle_STOR(cfg, client, argument);
|
||||||
|
} else
|
||||||
|
if (strcmp(cmd, "EPRT") == 0) {
|
||||||
|
handle_EPRT(cfg, client, argument);
|
||||||
|
} else
|
||||||
|
if (strcmp(cmd, "EPSV") == 0) {
|
||||||
|
handle_EPSV(cfg, client);
|
||||||
} else {
|
} else {
|
||||||
send_msg(client, "500 Command not recognized.\r\n");
|
send_msg(client, "500 Command not recognized.\r\n");
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,11 @@ struct ftpclient {
|
|||||||
int fd;
|
int fd;
|
||||||
int data_socket;
|
int data_socket;
|
||||||
char current_path[PATH_MAX];
|
char current_path[PATH_MAX];
|
||||||
char data_ip[20];
|
char data_ip[INET6_ADDRSTRLEN];
|
||||||
int data_port;
|
int data_port;
|
||||||
int type;
|
int type;
|
||||||
char ip[20];
|
char ip[INET6_ADDRSTRLEN];
|
||||||
char hostip[20];
|
char hostip[INET6_ADDRSTRLEN];
|
||||||
char name[16];
|
char name[16];
|
||||||
char password[32];
|
char password[32];
|
||||||
int data_srv_socket;
|
int data_srv_socket;
|
||||||
|
Reference in New Issue
Block a user