i'm writing a command-line ftp program, but i've got an error on the LIST command.
i suspect the error might be inside the create-data-connection function, but don't konow where exactly
Code:
int
main(int argc, char *argv[])
{
int c_sockfd; // socket file descriptor for control connection
int d_sockfd; // socket file descriptor for data connection
char *f_ext; // file extension
int d_depth; // directory depth
char *s_addr; // server address
char *l_dir; // local directory
char *s_dir; // server dirctory
char *command; // command
char *echoString; // string to send to echo server
char echo_buffer[32]; // buffer for echo string
int bytes_received, total_bytes_received; // bytes read in single recv(), and total bytes read
if (argc < 5)
{
usage_prompt();
exit(0);
}
// get input parameters
f_ext = (char*) (malloc(sizeof(char)*32));
s_addr = (char*) (malloc(sizeof(char)*32));
l_dir = (char*) (malloc(sizeof(char)*32));
s_dir = (char*) (malloc(sizeof(char)*32));
strcpy(f_ext, argv[1]);
d_depth = 3;
strcpy(s_addr, argv[3]);
strcpy(l_dir, argv[4]);
strcpy(s_dir, "/");
if (argc > 5)
{
strcpy(s_dir, argv[5]);
}
// create control connection
c_sockfd = create_control_connection(s_addr);
command = (char*) (malloc(sizeof(char)*32));
strcpy(command,"USER anonymous\r\n");
send(c_sockfd, command, strlen(command), 0);
strcpy(command,"PASS URL\r\n");
send(c_sockfd, command, strlen(command), 0);
strcpy(command,"MODE S\r\n");
send(c_sockfd, command, strlen(command), 0);
strcpy(command,"TYPE A\r\n");
send(c_sockfd, command, strlen(command), 0);
// create data connection
d_sockfd = create_data_connection(c_sockfd, s_addr, command);
// temporary output display
while (1)
{
if ((bytes_received = recv(c_sockfd, echo_buffer, 32 - 1, 0)) <= 0)
{
fprintf(stderr, "\nError: FTP server not available!\n");
exit(1);
}
total_bytes_received += bytes_received;
echo_buffer[bytes_received] = '\0';
printf(echo_buffer);
}
close(c_sockfd);
exit(0);
}
int
create_control_connection(char *host_ip)
{
int csock_fd; // socket file descriptor
char *server_name;
unsigned long server_inaddr;
struct hostent *hp; // struct used to get address of the server
struct sockaddr_in cli_addr, serv_addr; // structs for client and server ip address
// allocate memory for name of host
server_name = (char*) (malloc(sizeof(char)*32));
if (!server_name)
{
fprintf(stderr, "\nError: Failed to allocate memory!\n");
exit(1);
}
strcpy(server_name, host_ip);
// printf("%s\n", server_name);
// set server details
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
// determine wheteher the host address is given as dot-notation or word-form
if ( (server_inaddr = inet_addr(server_name)) != INADDR_NONE )
{
// by dot-notation
serv_addr.sin_addr.s_addr = server_inaddr;
}
else
{
// by name
if ( (hp = gethostbyname(server_name)) == NULL)
{
fprintf(stderr, "ERROR: failed to resolve host name: %s\n ", server_name);
usage_prompt();
exit(1);
}
bcopy( hp->h_addr, (char *) &serv_addr.sin_addr, hp->h_length);
}
serv_addr.sin_port = htons(SERV_COMMAND_PORT);
// create the socket
if ((csock_fd = socket(AF_INET, SOCK_STREAM, 0)) <0)
{
printf("errno = %d\n", errno);
printf("client: can't open stream socket\n");
exit(1);
}
// connecting
if (connect(csock_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
printf("errno = %d\n", errno);
printf("client: can't connect host address\n");
exit(3);
}
return csock_fd;
}
int
create_data_connection(int c_sockfd, char *host_ip, char *cmd)
{
int dsock_fd, ndsock_fd; // socket file descriptor
int newdsock_fd;
int serv_len;
int cli_port; // client port
int cli_len;
char *server_name;
unsigned long server_inaddr;
struct hostent *hp; // struct used to get address of the server
struct sockaddr_in cli_addr, serv_addr; // structs for client and server ip address
// allocate memory for name of host
server_name = (char*) (malloc(sizeof(char)*32));
if (!server_name)
{
fprintf(stderr, "\nError: Failed to allocate memory!\n");
exit(1);
}
strcpy(server_name, host_ip);
// printf("%s\n", server_name);
// set server details
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
// determine wheteher the host address is given as dot-notation or word-form
if ( (server_inaddr = inet_addr(server_name)) != INADDR_NONE )
{
// by dot-notation
serv_addr.sin_addr.s_addr = server_inaddr;
}
else
{
// by name
if ( (hp = gethostbyname(server_name)) == NULL)
{
fprintf(stderr, "ERROR: failed to resolve host name: %s\n ", server_name);
usage_prompt();
exit(1);
}
bcopy( hp->h_addr, (char *) &serv_addr.sin_addr, hp->h_length);
}
serv_addr.sin_port = htons(SERV_DATA_PORT);
// create the socket
if ((dsock_fd = socket(AF_INET, SOCK_STREAM, 0)) <0)
{
printf("errno = %d\n", errno);
printf("client: can't open stream socket\n");
exit(1);
}
bzero((char *) &cli_addr, sizeof(cli_addr));
// set client details
cli_addr.sin_family = AF_INET;
cli_addr.sin_addr.s_addr = htons(INADDR_ANY);
cli_addr.sin_port = htons(0);
// binding
if (bind(dsock_fd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0)
{
printf("client: can't bind local address\n");
exit(2);
}
// listening
if (listen(dsock_fd, 10) < 0)
{
printf("client: can't listen to local address\n");
exit(3);
}
serv_len = sizeof(serv_addr);
cli_len = sizeof(cli_addr);
getsockname(dsock_fd, (struct sockaddr *) &cli_addr, &cli_len);
cli_port = cli_addr.sin_port;
// printf("%d\n", cli_port);
sprintf(cmd, "PORT %d,%d,%d,%d,%d,%d\r\n", (serv_addr.sin_addr.s_addr & 0x000000FF),
(serv_addr.sin_addr.s_addr & 0x0000FF00) >> 8,
(serv_addr.sin_addr.s_addr & 0x00FF0000) >> 16,
(serv_addr.sin_addr.s_addr & 0xFF000000) >> 24,
(cli_addr.sin_port & 0xFF00) >> 8,
(cli_addr.sin_port & 0x00FF));
// puts(cmd);
send(c_sockfd, cmd, strlen(cmd), 0);
strcpy(cmd, "LIST\r\n");
newdsock_fd = send(c_sockfd, cmd, strlen(cmd), 0);
// newdsock_fd = accept(dsock_fd, (struct sockaddr *) &serv_addr, &serv_len);
return newdsock_fd;
}
void
usage_prompt()
{
printf("Usage: ftpget [file extension] [directory depth] [server name] [local directory] [server directory (optional)]");
}