From 90873cc8025a28f19b0f1a427263ad9a4a14fb75 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Tue, 28 Jun 2016 13:32:01 +1000 Subject: Add ftpd as a service. Add rtems-bsd-config.h for app libbsd set up. --- rtemsbsd/ftpd/ftpd-init.c | 39 ++++++++++ rtemsbsd/ftpd/ftpd-service.c | 179 +++++++++++++++++++++++++++++++++++++++++++ rtemsbsd/ftpd/ftpd.c | 81 +++++++++++--------- 3 files changed, 263 insertions(+), 36 deletions(-) create mode 100644 rtemsbsd/ftpd/ftpd-init.c create mode 100644 rtemsbsd/ftpd/ftpd-service.c (limited to 'rtemsbsd/ftpd') diff --git a/rtemsbsd/ftpd/ftpd-init.c b/rtemsbsd/ftpd/ftpd-init.c new file mode 100644 index 00000000..2741a633 --- /dev/null +++ b/rtemsbsd/ftpd/ftpd-init.c @@ -0,0 +1,39 @@ +/* + * FTP Server Daemon + * + * Submitted by: Jake Janovetz + * + * Changed by: Sergei Organov (OSV) + * Arnout Vandecappelle (AV) + * Sebastien Bourdeauducq (MM) + */ + +/************************************************************************* + * ftpd-init.c + ************************************************************************* + * Description: + * + * This file contains the legacy daemon initialisation. + * + *************************************************************************/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/* Configuration table */ +extern struct rtems_ftpd_configuration rtems_ftpd_configuration; + +/* + * rtems_initialize_ftpd + * + * Call the FTPD start function. + */ +int +rtems_initialize_ftpd(void) +{ + rtems_ftpd_configuration.verbose = true; + return rtems_ftpd_start(&rtems_ftpd_configuration); +} diff --git a/rtemsbsd/ftpd/ftpd-service.c b/rtemsbsd/ftpd/ftpd-service.c new file mode 100644 index 00000000..e2ee73d0 --- /dev/null +++ b/rtemsbsd/ftpd/ftpd-service.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2016 Chris Johns . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * FTPD service. To use add to rc.conf: + * + * ftpd_enable="YES" + * ftp_options="-p 21 -C 4 -P 100 -I 300 -R / -L -A rw" + * + * The options defaults are show. The options are: + * + * -p port : Port. + * -C conns : Maximum connections. + * -P priority : FTP thread priority (RTEMS Classis API). + * -I secs : Idle timeout in seconds. + * -R path : Root path. + * -L : Logins using /etc/passwd + * -A : Access, rw=read/write, rd=read, wr=write. + */ + +#include +#include +#include +#include +#include + +#define __need_getopt_newlib +#include + +#include +#include + +static int +ftpd_service(rtems_bsd_rc_conf* rc_conf) +{ + struct rtems_ftpd_configuration config = { + .priority = 100, /* FTPD task priority */ + .max_hook_filesize = 0, /* Maximum buffersize for hooks */ + .port = 21, /* Well-known port */ + .hooks = NULL, /* List of hooks */ + .root = NULL, /* Root for FTPD or NULL for "/" */ + .tasks_count = 4, /* Max. connections */ + .idle = 5 * 60, /* Idle timeout in seconds or 0 for no (infinite) timeout */ + .access = 0, /* Access: 0 - r/w, 1 - read-only, 2 - write-only, + * 3 - browse-only */ + .login = NULL /* Login */ + }; + rtems_bsd_rc_conf_argc_argv* aa; + int r; + + aa = rtems_bsd_rc_conf_argc_argv_create(); + if (aa == NULL) + return -1; + + r = rtems_bsd_rc_conf_find(rc_conf, "ftpd_enable", aa); + if (r == 0) { + rtems_status_code sc; + bool verbose = false; + if (aa->argc == 2 && strcasecmp("YES", aa->argv[1]) == 0) { + r = rtems_bsd_rc_conf_find(rc_conf, "ftpd_options", aa); + if (r == 0) { + struct getopt_data data; + char* end; + + memset(&data, 0, sizeof(data)); + + while (true) { + int c; + + c = getopt_r(aa->argc, aa->argv, "p:C:P:I:R:LA:v", &data); + if (c == -1) + break; + + switch (c) { + case 'p': + config.port = strtoul(data.optarg, &end, 10); + if (config.port == 0 || *end != '\0') { + fprintf(stderr, "error: ftpd: invalid port\n"); + config.port = 21; + } + break; + case 'C': + config.tasks_count = strtoul(data.optarg, &end, 10); + if (config.tasks_count == 0 || *end != '\0') { + fprintf(stderr, "error: ftpd: invalid port\n"); + config.tasks_count = 4; + } + break; + case 'P': + config.priority = strtoul(data.optarg, &end, 10); + if (config.priority == 0 || *end != '\0') { + fprintf(stderr, "error: ftpd: invalid priority\n"); + config.priority = 100; + } + break; + case 'I': + config.idle = strtoul(data.optarg, &end, 10); + if (config.tasks_count == 0 || *end != '\0') { + fprintf(stderr, "error: ftpd: invalid idle seconds\n"); + config.idle = 5 * 60; + } + break; + case 'R': + config.root = strdup(data.optarg); + if (config.root == NULL) { + fprintf(stderr, "error: ftpd: no memory for root path\n"); + } + break; + case 'L': + config.login = rtems_shell_login_check; + break; + case 'A': + if (strcasecmp("rw", data.optarg) == 0) + config.access = 0; + else if (strcasecmp("rd", data.optarg) == 0) + config.access = 1; + else if (strcasecmp("wr", data.optarg) == 0) + config.access = 2; + else + fprintf(stderr, "error: ftp: invalid access option\n"); + break; + case 'v': + verbose = true; + break; + case '?': + default: + fprintf(stderr, "error: ftp: unknown option: %s\n", data.optarg); + break; + } + } + } + if (verbose) { + printf("ftpd: port:%lu conns:%lu pri:%lu idle:%lu root:%s login:%s access:%s\n", + config.port, config.tasks_count, config.priority, config.idle, + config.root == NULL ? "/" : config.root, + config.login == NULL ? "no" : "yes", + config.access == 0 ? "read/write" : config.access == 1 ? "read" : "write"); + } + sc = rtems_ftpd_start(&config); + if (sc != RTEMS_SUCCESSFUL) + fprintf(stderr, "error: ftpd: %s\n", rtems_status_text(sc)); + } + } + + return 0; +} + +void +rc_conf_ftpd_init(void* arg) +{ + int r; + r = rtems_bsd_rc_conf_service_add("ftpd", + "after:network;", + ftpd_service); + if (r < 0) + fprintf(stderr, "error: ftpd service add failed: %s\n", strerror(errno)); +} diff --git a/rtemsbsd/ftpd/ftpd.c b/rtemsbsd/ftpd/ftpd.c index fddc03e6..0f1577e1 100644 --- a/rtemsbsd/ftpd/ftpd.c +++ b/rtemsbsd/ftpd/ftpd.c @@ -13,18 +13,18 @@ * Changed by: Sergei Organov (OSV) * Arnout Vandecappelle (AV) * Sebastien Bourdeauducq (MM) - * + * * * Changes: * * 2010-12-02 Sebastien Bourdeauducq * * * Support spaces in filenames - * + * * 2010-04-29 Arnout Vandecappelle (Essensium/Mind) - * + * * * Added USER/PASS authentication. - * + * * 2001-01-31 Sergei Organov * * * Hacks with current dir and root dir removed in favor of new libio @@ -244,7 +244,7 @@ enum }; /* Configuration table */ -extern struct rtems_ftpd_configuration rtems_ftpd_configuration; +static struct rtems_ftpd_configuration* ftpd_config; /* this is not prototyped in strict ansi mode */ FILE *fdopen (int fildes, const char *mode); @@ -953,7 +953,7 @@ command_store(FTPD_SessionInfo_t *info, char const *filename) wrt = &discard; } - if (!null && rtems_ftpd_configuration.hooks != NULL) + if (!null && ftpd_config->hooks != NULL) { /* Search our list of hooks to see if we need to do something special. */ @@ -961,7 +961,7 @@ command_store(FTPD_SessionInfo_t *info, char const *filename) int i; i = 0; - hook = &rtems_ftpd_configuration.hooks[i++]; + hook = &ftpd_config->hooks[i++]; while (hook->filename != NULL) { if (!strcmp(hook->filename, filename)) @@ -969,7 +969,7 @@ command_store(FTPD_SessionInfo_t *info, char const *filename) usehook = hook; break; } - hook = &rtems_ftpd_configuration.hooks[i++]; + hook = &ftpd_config->hooks[i++]; } } @@ -982,8 +982,8 @@ command_store(FTPD_SessionInfo_t *info, char const *filename) * given name. */ - char *bigBufr; - size_t filesize = rtems_ftpd_configuration.max_hook_filesize + 1; + char *bigBufr; + size_t filesize = ftpd_config->max_hook_filesize + 1; /* * Allocate space for our "file". @@ -1766,8 +1766,8 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args) free(info->pass); info->pass = NULL; info->user = strdup(fname); - if (rtems_ftpd_configuration.login && - !rtems_ftpd_configuration.login(info->user, NULL)) { + if (ftpd_config->login && + !ftpd_config->login(info->user, NULL)) { info->auth = false; send_reply(info, 331, "User name okay, need password."); } else { @@ -1784,8 +1784,8 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args) if (!info->user) { send_reply(info, 332, "Need account to log in"); } else { - if (rtems_ftpd_configuration.login && - !rtems_ftpd_configuration.login(info->user, info->pass)) { + if (ftpd_config->login && + !ftpd_config->login(info->user, info->pass)) { info->auth = false; send_reply(info, 530, "Not logged in."); } else { @@ -1826,7 +1826,7 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args) else { char *c; c = strchr(args, ' '); - if((c != NULL) && (sscanf(args, "%o", &mask) == 1) && strncpy(fname, c+1, 254) + if((c != NULL) && (sscanf(args, "%o", &mask) == 1) && strncpy(fname, c+1, 254) && (chmod(fname, (mode_t)mask) == 0)) send_reply(info, 257, "CHMOD successful."); else @@ -2009,7 +2009,7 @@ ftpd_daemon(rtems_task_argument args __attribute__((unused))) syslog(LOG_ERR, "ftpd: Error creating socket: %s", serr()); addr.sin_family = AF_INET; - addr.sin_port = htons(rtems_ftpd_configuration.port); + addr.sin_port = htons(ftpd_config->port); addr.sin_addr.s_addr = htonl(INADDR_ANY); memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); @@ -2064,7 +2064,7 @@ ftpd_daemon(rtems_task_argument args __attribute__((unused))) info->idle = ftpd_timeout; info->user = NULL; info->pass = NULL; - if (rtems_ftpd_configuration.login) + if (ftpd_config->login) info->auth = false; else info->auth = true; @@ -2088,46 +2088,54 @@ ftpd_daemon(rtems_task_argument args __attribute__((unused))) * * * Input parameters: - * + * config: constant initial setup. * Output parameters: * returns RTEMS_SUCCESSFUL on successful start of the daemon. */ int -rtems_initialize_ftpd(void) +rtems_ftpd_start(const struct rtems_ftpd_configuration* config) { rtems_status_code sc; rtems_id tid; rtems_task_priority priority; int count; - if (rtems_ftpd_configuration.port == 0) + if (ftpd_config != NULL) + return RTEMS_RESOURCE_IN_USE; + + ftpd_config = malloc(sizeof(*ftpd_config)); + if (ftpd_config == NULL) + return RTEMS_NO_MEMORY; + + *ftpd_config = *config; + + if (ftpd_config->port == 0) { - rtems_ftpd_configuration.port = FTPD_CONTROL_PORT; + ftpd_config->port = FTPD_CONTROL_PORT; } - if (rtems_ftpd_configuration.priority == 0) + if (ftpd_config->priority == 0) { - rtems_ftpd_configuration.priority = 40; + ftpd_config->priority = 40; } - priority = rtems_ftpd_configuration.priority; + priority = ftpd_config->priority; - ftpd_timeout = rtems_ftpd_configuration.idle; + ftpd_timeout = ftpd_config->idle; if (ftpd_timeout < 0) ftpd_timeout = 0; - rtems_ftpd_configuration.idle = ftpd_timeout; + ftpd_config->idle = ftpd_timeout; - ftpd_access = rtems_ftpd_configuration.access; + ftpd_access = ftpd_config->access; ftpd_root = "/"; - if ( rtems_ftpd_configuration.root && - rtems_ftpd_configuration.root[0] == '/' ) - ftpd_root = rtems_ftpd_configuration.root; + if (ftpd_config->root && ftpd_config->root[0] == '/' ) + ftpd_root = ftpd_config->root; - rtems_ftpd_configuration.root = ftpd_root; + ftpd_config->root = ftpd_root; - if (rtems_ftpd_configuration.tasks_count <= 0) - rtems_ftpd_configuration.tasks_count = 1; - count = rtems_ftpd_configuration.tasks_count; + if (ftpd_config->tasks_count <= 0) + ftpd_config->tasks_count = 1; + count = ftpd_config->tasks_count; if (!task_pool_init(count, priority)) { @@ -2157,8 +2165,9 @@ rtems_initialize_ftpd(void) return RTEMS_UNSATISFIED; } - syslog(LOG_INFO, "ftpd: FTP daemon started (%d session%s max)", - count, ((count > 1) ? "s" : "")); + if (ftpd_config->verbose) + syslog(LOG_INFO, "ftpd: FTP daemon started (%d session%s max)", + count, ((count > 1) ? "s" : "")); return RTEMS_SUCCESSFUL; } -- cgit v1.2.3