diff --git a/.gitignore b/.gitignore index 8a6627d..ff05ec6 100644 --- a/.gitignore +++ b/.gitignore @@ -95,3 +95,5 @@ utils/mnettoss/mnettoss mnet/* utils/mnetsubunsub/mnetsubunsub deps/libuuid/autom4te.cache +utils/mnetftpd/mnetftpd +utils/mnetftpc/mnetftpc diff --git a/utils/mnetftpc/mnetftpc.c b/utils/mnetftpc/mnetftpc.c new file mode 100644 index 0000000..396843f --- /dev/null +++ b/utils/mnetftpc/mnetftpc.c @@ -0,0 +1,217 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int imhub = 0; +int hubnode = 0; +char *baseindir = NULL; +char *baseoutdir = NULL; +char *ftphost = NULL; +char *ftpusername = NULL; +char *ftppassword = NULL; +char **filenames; +int file_count = 0; + + +size_t trimwhitespace(char *out, size_t len, const char *str) { + if(len == 0) + return 0; + + const char *end; + size_t out_size; + + // Trim leading space + while(isspace((unsigned char)*str)) str++; + + if(*str == 0) { + *out = 0; + return 1; + } + + // Trim trailing space + end = str + strlen(str) - 1; + while(end > str && isspace((unsigned char)*end)) end--; + end++; + + // Set output size to minimum of trimmed string length and buffer size minus 1 + out_size = (end - str) < len-1 ? (end - str) : len-1; + + // Copy trimmed string and add null terminator + memcpy(out, str, out_size); + out[out_size] = 0; + + return out_size; +} + +int parse_config_file(char *filename) { + FILE *fptr; + char buffer[256]; + char bufferw[256]; + char *ptr; + + fptr = fopen(filename, "r"); + if (!fptr) { + return 0; + } + + fgets(buffer, 256, fptr); + while (!feof(fptr)) { + if (buffer[0] != ';') { + if (buffer[strlen(buffer) - 1] == '\n'){ + buffer[strlen(buffer) - 1] = '\0'; + if (strncasecmp(buffer, "IMHUB", 5) == 0) { + trimwhitespace(bufferw, 256, &buffer[6]); + if (strcasecmp(bufferw, "TRUE") == 0) { + imhub = 1; + } + } else if (strncasecmp(buffer, "UPLINK", 6) == 0) { + trimwhitespace(bufferw, 256, &buffer[7]); + hubnode = atoi(bufferw); + } else if (strncasecmp(buffer, "FTPHOST", 7) == 0) { + trimwhitespace(bufferw, 256, &buffer[8]); + ftphost = strdup(bufferw); + } else if (strncasecmp(buffer, "FTPUSER", 7) == 0) { + trimwhitespace(bufferw, 256, &buffer[8]); + ftpusername = strdup(bufferw); + } else if (strncasecmp(buffer, "FTPPASS", 7) == 0) { + trimwhitespace(bufferw, 256, &buffer[8]); + ftppassword = strdup(bufferw); + } else if (strncasecmp(buffer, "INDIR", 5) == 0) { + trimwhitespace(bufferw, 256, &buffer[6]); + baseindir = strdup(bufferw); + } else if (strncasecmp(buffer, "OUTDIR", 6) == 0) { + trimwhitespace(bufferw, 256, &buffer[7]); + baseoutdir = strdup(bufferw); + } + } else { + fclose(fptr); + return 0; + } + } + fgets(buffer, 256, fptr); + } + + fclose(fptr); + return 1; +} + +int main(int argc, char **argv) { + netbuf *nb; + netbuf *nd; + char buffer[PATH_MAX]; + int len; + int i; + DIR *outdir; + struct dirent *dent; + struct stat s; + + + if (argc < 2) { + fprintf(stderr, "Usage ./mnetftpc mnet.cfg\n"); + return -1; + } + + if (!parse_config_file(argv[1])) { + fprintf(stderr, "Error parsing config file: %s\n", argv[1]); + return -1; + } + + if (baseoutdir == NULL) { + fprintf(stderr, "OUTDIR must be defined\n"); + return -1; + } + + if (baseindir == NULL) { + fprintf(stderr, "INDIR must be defined\n"); + return -1; + } + + if (ftphost == NULL) { + fprintf(stderr, "FTPHOST must be defined\n"); + return -1; + } + + if (ftpusername == NULL) { + fprintf(stderr, "FTPUSER must be defined\n"); + return -1; + } + + if (ftppassword == NULL) { + fprintf(stderr, "FTPPASS must be defined\n"); + return -1; + } + + FtpInit(); + if (FtpConnect(ftphost, &nb)) { + if (FtpLogin(ftpusername, ftppassword, nb)) { + // logged in... + // receive files in in + if (FtpChdir("in", nb)) { + if (FtpAccess("/in", FTPLIB_DIR, FTPLIB_ASCII, nb, &nd)) { + len = FtpRead(buffer, PATH_MAX-1, nd); + while(len != -1 && len != 0) { + buffer[len-1] = '\0'; + printf("%s\n", buffer); + if (strcmp(buffer, "..") != 0 && strcmp(buffer, ".") != 0) { + if (file_count == 0) { + filenames = (char **)malloc(sizeof(char *)); + } else { + filenames = (char **)realloc(filenames, sizeof(char *) * (file_count + 1)); + } + filenames[file_count] = strdup(buffer); + file_count++; + } + + len = FtpRead(buffer, PATH_MAX-1, nd); + } + + FtpClose(nd); + + for (i=0;id_name); + if (stat(buffer, &s) == 0 && !S_ISDIR(s.st_mode)) { + if (FtpPut(buffer, dent->d_name, FTPLIB_BINARY, nb)) { + fprintf(stdout, "Sent %s\n", dent->d_name); + unlink(buffer); + rewinddir(outdir); + } + } + } + closedir(outdir); + } + + } else { + fprintf(stderr, "Unable to authenticate with FTP server\n"); + } + FtpQuit(nb); + } else { + fprintf(stderr, "Unable to connect to FTP server\n"); + } + return 0; +} \ No newline at end of file diff --git a/utils/mnetftpd/mnetftpd.c b/utils/mnetftpd/mnetftpd.c index 691542c..3c17ce1 100644 --- a/utils/mnetftpd/mnetftpd.c +++ b/utils/mnetftpd/mnetftpd.c @@ -698,6 +698,69 @@ void handle_LIST(struct ftpserver *cfg, struct ftpclient *client) { } } +void handle_NLST(struct ftpserver *cfg, struct ftpclient *client) { + DIR *dirp; + struct dirent *dp; + char newpath[PATH_MAX]; + char linebuffer[PATH_MAX]; + struct stat s; + pid_t pid = fork(); + + if (pid > 0) { + // nothing + client->data_socket = -1; + memset(client->data_ip, 0, INET6_ADDRSTRLEN); + client->data_srv_socket = -1; + } else if (pid == 0) { + if (client->current_path == NULL) { + if (!open_tcp_connection(cfg, client)) { + send_msg(client, "425 TCP connection cannot be established.\r\n"); + exit(0); + } + send_msg(client, "150 Data connection accepted; transfer starting.\r\n"); + + if (stat(client->user->indir, &s) == 0) { + snprintf(linebuffer, PATH_MAX, "in\r\n"); + } + send_data(client, linebuffer, strlen(linebuffer)); + if (stat(client->user->outdir, &s) == 0) { + snprintf(linebuffer, PATH_MAX, "out\r\n"); + } + send_data(client, linebuffer, strlen(linebuffer)); + close_tcp_connection(client); + send_msg(client, "226 Transfer ok.\r\n"); + exit(0); + } else { + dirp = opendir(client->current_path); + + if (!dirp) { + send_msg(client, "451 Could not read directory.\r\n"); + exit(0); + } + + if (!open_tcp_connection(cfg, client)) { + send_msg(client, "425 TCP connection cannot be established.\r\n"); + closedir(dirp); + exit(0); + } + send_msg(client, "150 Data connection accepted; transfer starting.\r\n"); + while ((dp = readdir(dirp)) != NULL) { + snprintf(newpath, PATH_MAX, "%s/%s", client->current_path, dp->d_name); + if (stat(newpath, &s) == 0) { + snprintf(linebuffer, PATH_MAX, "%s\r\n", dp->d_name); + send_data(client, linebuffer, strlen(linebuffer)); + } + } + closedir(dirp); + close_tcp_connection(client); + send_msg(client, "226 Transfer ok.\r\n"); + exit(0); + } + } else { + send_msg(client, "451 Could not read directory.\r\n"); + } +} + void handle_PORT(struct ftpserver *cfg, struct ftpclient *client, char *arg) { if (client->data_socket > 0) { close(client->data_socket); @@ -891,6 +954,9 @@ int handle_client(struct ftpserver *cfg, struct ftpclient *client, char *buf, in if (strcmp(cmd, "PORT") == 0) { handle_PORT(cfg, client, argument); } else + if (strcmp(cmd, "NLST") == 0) { + handle_NLST(cfg, client); + } else if (strcmp(cmd, "LIST") == 0) { handle_LIST(cfg, client); } else