This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new a4b6b8b8bf3 Documentation/netutils: add comprehensive guide for ftpd
a4b6b8b8bf3 is described below
commit a4b6b8b8bf3d6eb286c78f540354f4a322f09870
Author: Swatantra Yadav <[email protected]>
AuthorDate: Thu Oct 8 17:36:27 2026 +0530
Documentation/netutils: add comprehensive guide for ftpd
Provide a complete documentation guide for the ftpd (FTP server) network
utility in Documentation/applications/netutils/ftpd/index.rst, replacing
the previous 6-line placeholder stub.
Includes:
- Protocol architecture overview (control/data connection separation,
multi-session worker pthreads, VFS mapping)
- Security considerations regarding unencrypted plaintext FTP credentials,
mandatory credential hardening, home directory isolation, and encrypted
password authentication
- Comprehensive supported RFC 959 / RFC 2428 / RFC 3659 FTP commands
reference table
- Configuration options table and networking prerequisites
(CONFIG_NETUTILS_FTPD, worker stack size, buffer sizes)
- NSH terminal usage (ftpd -4 / -6, ftpd_stop) with address-family flag
requirements and configured account placeholders
- External client connection walkthroughs (FTP CLI, cURL) using configured
account and anonymous workflows
- Public C API reference for types, account flags, and lifecycle functions
(ftpd_open, ftpd_adduser, ftpd_session, ftpd_close)
- Complete, runnable C application example demonstrating multi-user server
setup, signal-driven termination (SIGINT/SIGTERM) with atomic sig_atomic_t
state, POSIX kill stop routine, and credential placeholders
- Embedded design and resource tuning guidelines (stack sizing, flash/SD
card I/O buffering, and NAT passive mode)
Addresses #11081
Assisted-by: Google Gemini
Signed-off-by: Swatantra Yadav <[email protected]>
---
Documentation/applications/netutils/ftpd/index.rst | 522 ++++++++++++++++++++-
1 file changed, 520 insertions(+), 2 deletions(-)
diff --git a/Documentation/applications/netutils/ftpd/index.rst
b/Documentation/applications/netutils/ftpd/index.rst
index 42dea03f001..8598313f453 100644
--- a/Documentation/applications/netutils/ftpd/index.rst
+++ b/Documentation/applications/netutils/ftpd/index.rst
@@ -1,5 +1,523 @@
===================
-``ftpd`` FTP server
+``ftpd`` FTP Server
===================
-FTP server. See ``apps/include/netutils/ftpd.h`` for interface information.
+The ``ftpd`` utility is a lightweight File Transfer Protocol (FTP) server
implementation
+for Apache NuttX, conforming to the core protocol specification defined in
:rfc:`959`,
+with modern extensions for IPv6 networking (:rfc:`2428`) and file metadata
inspection
+(:rfc:`3659`).
+
+It provides embedded microcontrollers with bidirectional network file transfer
+capabilities, allowing remote desktop computers, automated update utilities,
and
+monitoring tools to inspect, upload, download, and delete files on the NuttX
Virtual
+File System (VFS), SD cards, or flash partitions over local Ethernet or Wi-Fi
links.
+
+.. note::
+
+ **Security Consideration**: Standard FTP (:rfc:`959`) transmits usernames,
passwords,
+ and file contents in unencrypted plaintext across the network. On untrusted
or public
+ networks, credentials and transferred data can be intercepted by network
sniffers.
+ When deploying ``ftpd`` in production environments:
+
+ - Restrict FTP traffic to isolated, trusted local networks or private
maintenance VLANs.
+ - Where possible, enforce strong passwords via the encrypted password
subsystem
+ (``CONFIG_FTPD_LOGIN_PASSWD`` with ``CONFIG_FSUTILS_PASSWD``).
+ - Confine guest accounts to dedicated subdirectories using home directory
isolation
+ (``FTPD_ACCOUNTFLAG_GUEST``).
+ - For mission-critical external transfers, prefer encrypted protocols such
as SSH/SFTP
+ or HTTPS.
+
+Operational Architecture
+========================
+
+The NuttX FTP server operates using a multi-threaded daemon model:
+
+1. **Master Server Socket**: A listening TCP socket bound to the FTP control
port (default
+ port 21) accepts incoming client connections.
+2. **Worker Pthreads**: When a remote FTP client connects, ``ftpd_session()``
accepts the
+ TCP connection and spawns a dedicated worker thread (with stack size
governed by
+ ``CONFIG_FTPD_WORKERSTACKSIZE``) to handle control session interactions.
+3. **Dual Connection Model**: The server maintains a persistent control
connection
+ for ASCII commands and reply codes (e.g., ``USER``, ``PASS``, ``PASV``), and
+ establishes transient data connections on demand for directory listings
+ (``LIST``, ``NLST``) and file transfers (``RETR``, ``STOR``).
+4. **VFS Integration**: Directory navigation, file creation, reading, and
writing map
+ directly to standard POSIX file system system calls (``open()``,
``read()``, ``write()``,
+ ``stat()``, ``opendir()``, ``unlink()``, ``rename()``).
+
+Key Features
+============
+
+- **RFC 959 Core Protocol Support**: Full support for standard FTP file
retrieval, storage,
+ and directory management.
+- **Active and Passive Modes**: Supports both Active (``PORT`` / ``EPRT``) and
Passive
+ (``PASV`` / ``EPSV``) data connections, ensuring seamless operation across
client firewalls
+ and NAT gateways.
+- **IPv4 and IPv6 Dual-Stack**: Implements :rfc:`2428` commands (``EPRT`` and
``EPSV``) to
+ support both ``AF_INET`` and ``AF_INET6`` address families.
+- **Resumable Transfers**: Supports the ``REST`` (restart marker) command to
resume
+ interrupted file transfers without retransmitting previously transferred
blocks.
+- **Extended File Metadata**: Implements :rfc:`3659` commands (``SIZE`` and
``MDTM``) to
+ report file byte lengths and last-modification timestamps.
+- **User Account Management**: In-memory user database supporting multiple
concurrent
+ accounts with configurable privileges (administrator, system, or guest) and
directory
+ isolation.
+- **Encrypted Password Integration**: Optional integration with
``apps/fsutils/passwd``
+ to authenticate users against encrypted password databases.
+
+Supported FTP Commands
+======================
+
+The NuttX FTP server implements a comprehensive command subset:
+
+.. list-table::
+ :widths: 20 80
+ :header-rows: 1
+
+ * - Command
+ - Description & Protocol Standard
+ * - ``USER``
+ - Specify client username (:rfc:`959`).
+ * - ``PASS``
+ - Specify client password (:rfc:`959`).
+ * - ``QUIT``
+ - Terminate the control connection (:rfc:`959`).
+ * - ``SYST``
+ - Return server system type (reports ``UNIX Type: L8``) (:rfc:`959`).
+ * - ``TYPE``
+ - Set transfer type: ASCII (``A``) or Image/Binary (``I``) (:rfc:`959`).
+ * - ``MODE``
+ - Set transfer mode: Stream (``S``) (:rfc:`959`).
+ * - ``STRU``
+ - Set file structure: File (``F``) (:rfc:`959`).
+ * - ``PWD`` / ``XPWD``
+ - Print working directory (:rfc:`959`).
+ * - ``CWD`` / ``XCWD``
+ - Change working directory (:rfc:`959`).
+ * - ``CDUP`` / ``XCUP``
+ - Change to parent directory (:rfc:`959`).
+ * - ``MKD`` / ``XMKD``
+ - Create a directory (:rfc:`959`).
+ * - ``RMD`` / ``XRMD``
+ - Remove an empty directory (:rfc:`959`).
+ * - ``DELE``
+ - Delete a file (:rfc:`959`).
+ * - ``RNFR`` / ``RNTO``
+ - Rename file from / rename file to sequence (:rfc:`959`).
+ * - ``PORT``
+ - Initiate active IPv4 data connection (:rfc:`959`).
+ * - ``PASV``
+ - Request passive IPv4 data connection (:rfc:`959`).
+ * - ``EPRT``
+ - Initiate extended active data connection (IPv4/IPv6) (:rfc:`2428`).
+ * - ``EPSV``
+ - Request extended passive data connection (IPv4/IPv6) (:rfc:`2428`).
+ * - ``LIST``
+ - Transmit detailed directory listing (:rfc:`959`).
+ * - ``NLST``
+ - Transmit filename-only directory list (:rfc:`959`).
+ * - ``RETR``
+ - Download a file from the server (:rfc:`959`).
+ * - ``STOR``
+ - Upload a file to the server (:rfc:`959`).
+ * - ``APPE``
+ - Append uploaded data to an existing file (:rfc:`959`).
+ * - ``REST``
+ - Set byte offset for resuming a transfer (:rfc:`959`).
+ * - ``SIZE``
+ - Return the exact byte size of a file (:rfc:`3659`).
+ * - ``MDTM``
+ - Return the last modification timestamp of a file (:rfc:`3659`).
+ * - ``ABOR``
+ - Abort the active data transfer (:rfc:`959`).
+ * - ``NOOP``
+ - No operation; keeps connection alive (:rfc:`959`).
+ * - ``HELP``
+ - Display supported commands (:rfc:`959`).
+
+Requirements & Dependencies
+===========================
+
+To enable the FTP server in your NuttX build, ensure the following subsystem
+dependencies are configured:
+
+- Core Networking: ``CONFIG_NET=y``
+- TCP Protocol: ``CONFIG_NET_TCP=y``
+- POSIX Pthreads: ``CONFIG_DISABLE_PTHREAD=n`` (required for multi-session
handling)
+- File System: ``CONFIG_NFILE_DESCRIPTORS > 0`` (with mounted storage, e.g.,
ROMFS, FAT, LittleFS)
+- Client Library: ``CONFIG_NETUTILS_FTPD=y``
+- Password Support (Optional): ``CONFIG_FTPD_LOGIN_PASSWD=y`` and
``CONFIG_FSUTILS_PASSWD=y``
+- Standalone Example Daemon (Optional): ``CONFIG_EXAMPLES_FTPD=y``
+
+Configuration Options
+=====================
+
+The behavior and resource consumption of the FTP server can be configured via
Kconfig:
+
+.. list-table::
+ :widths: 35 15 50
+ :header-rows: 1
+
+ * - Kconfig Option
+ - Default
+ - Description
+ * - ``CONFIG_NETUTILS_FTPD``
+ - ``n``
+ - Enables compilation of the FTP server library in ``apps/netutils/ftpd``.
+ * - ``CONFIG_FTPD_WORKERSTACKSIZE``
+ - ``DEFAULT_TASK_STACKSIZE``
+ - Stack size in bytes allocated for each FTP session worker pthread.
+ * - ``CONFIG_FTPD_LOGIN_PASSWD``
+ - ``n``
+ - Validates login credentials against an encrypted password database via
+ ``apps/fsutils/passwd``.
+ * - ``CONFIG_FTPD_VENDORID``
+ - ``"NuttX"``
+ - Vendor identification string reported in server greeting banners.
+ * - ``CONFIG_FTPD_SERVERID``
+ - ``"NuttX FTP Server"``
+ - Server product name string reported in the ``220`` greeting message.
+ * - ``CONFIG_FTPD_CMDBUFFERSIZE``
+ - ``128``
+ - Size in bytes of the command line buffer for incoming FTP instructions.
+ * - ``CONFIG_FTPD_DATABUFFERSIZE``
+ - ``512``
+ - Buffer size in bytes used for I/O chunks during data socket transfers.
+ * - ``CONFIG_EXAMPLES_FTPD``
+ - ``n``
+ - Builds the standalone ``ftpd`` / ``ftpd_stop`` command line example in
NSH.
+ * - ``CONFIG_EXAMPLES_FTPD_PORT``
+ - ``21``
+ - Default TCP port used by the standalone example daemon.
+
+Running the FTP Daemon from NSH
+===============================
+
+When ``CONFIG_EXAMPLES_FTPD=y`` is enabled, the FTP server can be started and
stopped
+interactively from the NuttShell.
+
+Starting the Daemon
+-------------------
+
+The standalone daemon requires an address family parameter specifying either
``-4`` (IPv4)
+or ``-6`` (IPv6):
+
+.. code-block:: console
+
+ nsh> ftpd -4
+ Initializing the network
+ Starting the FTP daemon
+ FTP daemon [3] started
+ Adding accounts:
+ 1. Root account: USER=root PASSWORD=<configured-password> HOME=(none)
+ 2. User account: USER=ftp PASSWORD=(none) HOME=(none)
+ 3. User account: USER=anonymous PASSWORD=(none) HOME=(none)
+
+.. warning::
+
+ **Mandatory Credential Hardening**:
+ The standalone example in ``apps/examples/ftpd`` is intended for local
hardware
+ testing. Before enabling ``ftpd`` in any networked or production
environment,
+ change the demonstration credentials to strong, unique passwords or
authenticate
+ against an encrypted password database via ``CONFIG_FTPD_LOGIN_PASSWD``.
Never
+ deploy publicly known default passwords.
+
+The daemon initializes the network interface if not already active, opens a
listening
+socket on ``CONFIG_EXAMPLES_FTPD_PORT`` (default port 21), registers the
configured accounts,
+and awaits incoming connections in a background task.
+
+Stopping the Daemon
+-------------------
+
+To cleanly terminate the running FTP daemon:
+
+.. code-block:: console
+
+ nsh> ftpd_stop
+ Stopping the FTP daemon, pid=3
+
+Connecting from an External FTP Client
+======================================
+
+Once the daemon is running, connect using standard command-line FTP clients,
``curl``,
+or graphical transfer tools like FileZilla:
+
+Using Command-Line FTP
+----------------------
+
+Authenticate using the configured ``root`` account and password:
+
+.. code-block:: console
+
+ $ ftp 192.168.1.150
+ Connected to 192.168.1.150.
+ 220 NuttX FTP Server ready.
+ Name (192.168.1.150:user): root
+ 331 Password required for root.
+ Password: <your-password>
+ 230 User logged in.
+ Remote system type is UNIX.
+ Using binary mode to transfer files.
+ ftp> pwd
+ 257 "/" is current directory.
+ ftp> ls
+ 200 PORT command successful.
+ 150 Opening data connection for directory list.
+ drwxr-xr-x 1 root root 0 Jan 01 00:00 dev
+ drwxr-xr-x 1 root root 0 Jan 01 00:00 etc
+ drwxr-xr-x 1 root root 0 Jan 01 00:00 mnt
+ 226 Transfer complete.
+ ftp> put firmware.bin /mnt/sdcard/firmware.bin
+ 200 PORT command successful.
+ 150 Opening data connection for firmware.bin.
+ 226 Transfer complete. 524288 bytes sent in 2.1 secs.
+ ftp> quit
+ 221 Goodbye.
+
+Alternatively, connect anonymously without a password using the ``anonymous``
account:
+
+.. code-block:: console
+
+ $ ftp 192.168.1.150
+ Connected to 192.168.1.150.
+ 220 NuttX FTP Server ready.
+ Name (192.168.1.150:user): anonymous
+ 230 User logged in.
+ ftp> ls
+ 200 PORT command successful.
+ 150 Opening data connection for directory list.
+ drwxr-xr-x 1 root root 0 Jan 01 00:00 mnt
+ 226 Transfer complete.
+ ftp> quit
+ 221 Goodbye.
+
+Using cURL
+----------
+
+Files can also be transferred programmatically from external scripts using
``curl``
+(for interactive use, omit the password to receive a prompt; for scripts, load
credentials
+from a protected source such as ``~/.netrc`` or environment variables):
+
+.. code-block:: console
+
+ # Download a file from NuttX VFS using root credentials (prompts for
password):
+ curl -u root ftp://192.168.1.150/mnt/sdcard/log.txt -o downloaded_log.txt
+
+ # Upload a file to NuttX VFS using root credentials (prompts for password):
+ curl -u root -T config.ini ftp://192.168.1.150/mnt/sdcard/config.ini
+
+ # Download anonymously without credentials:
+ curl ftp://192.168.1.150/mnt/sdcard/log.txt -o downloaded_log.txt
+
+C API Reference
+===============
+
+The public C interface for ``ftpd`` is declared in
``apps/include/netutils/ftpd.h``.
+
+Types & Constants
+-----------------
+
+.. code-block:: c
+
+ /* Opaque FTP session handle */
+ typedef FAR void *FTPD_SESSION;
+
+ /* User Account Flags */
+ #define FTPD_ACCOUNTFLAG_NONE (0) /* Standard unprivileged user */
+ #define FTPD_ACCOUNTFLAG_ADMIN (1 << 0) /* Administrative privileges */
+ #define FTPD_ACCOUNTFLAG_SYSTEM (1 << 1) /* System root access */
+ #define FTPD_ACCOUNTFLAG_GUEST (1 << 2) /* Restricted guest access */
+
+Functions
+---------
+
+Creating the Server Instance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+
+ FTPD_SESSION ftpd_open(int port, sa_family_t family);
+
+- Allocates and initializes the FTP server instance, binding the listening
socket
+ to the designated port and address family.
+- ``port``: TCP listen port (typically 21, or any unreserved port).
+- ``family``: Socket address family (``AF_INET`` for IPv4 or ``AF_INET6`` for
IPv6).
+- *Returns*: A non-``NULL`` ``FTPD_SESSION`` handle on success, or ``NULL`` on
failure.
+
+Adding User Accounts
+~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+
+ int ftpd_adduser(FTPD_SESSION handle, uint8_t accountflags,
+ FAR const char *user, FAR const char *passwd,
+ FAR const char *home);
+
+- Registers an account in the FTP server's user database.
+- ``handle``: Server handle returned by ``ftpd_open()``.
+- ``accountflags``: Bitmask of ``FTPD_ACCOUNTFLAG_*`` defining privilege level.
+- ``user``: Username string. Pass ``NULL`` to allow anonymous login without a
username.
+- ``passwd``: Password string. Pass ``NULL`` to permit login without a
password.
+- ``home``: Initial home directory path for the user (e.g., ``"/mnt/sdcard"``).
+- *Returns*: ``0`` (``OK``) on success, or a negated errno value (e.g.,
``-ENOMEM``) on failure.
+
+Driving the Server Session Loop
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+
+ int ftpd_session(FTPD_SESSION handle, int timeout);
+
+- Listens for an incoming client connection on the server socket.
+- When a connection arrives, it accepts the connection and spawns a worker
thread to
+ service the FTP session.
+- ``handle``: Server handle returned by ``ftpd_open()``.
+- ``timeout``: Connection wait timeout in milliseconds.
+- *Returns*: ``0`` (``OK``) on connection acceptance and worker thread
creation,
+ ``-ETIMEDOUT`` if the timeout elapsed with no incoming connection (normal
loop
+ condition), or a negative errno value on failure.
+
+Destroying the Server Instance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+
+ void ftpd_close(FTPD_SESSION handle);
+
+- Closes listening sockets, terminates active sessions, and deallocates all
internal
+ resources and account records associated with the handle.
+
+Application Example
+===================
+
+Below is a complete, standalone example demonstrating how an embedded task
initializes
+an FTP server daemon with multiple accounts, drives the connection loop, and
provides
+a signal-safe, thread-safe shutdown path:
+
+.. code-block:: c
+
+ #include <nuttx/config.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <stdbool.h>
+ #include <signal.h>
+ #include <unistd.h>
+ #include <errno.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+
+ #include <netutils/ftpd.h>
+
+ /* Signal-safe termination flag modified exclusively by signal handlers */
+ static volatile sig_atomic_t g_ftp_stop = 0;
+
+ /* PID of the running FTP server daemon */
+ static pid_t g_server_pid = -1;
+
+ /* Signal handler to request graceful shutdown (async-signal-safe) */
+ static void ftp_signal_handler(int signo)
+ {
+ g_ftp_stop = 1;
+ }
+
+ /* Thread-safe stop API callable from other tasks/threads via POSIX kill */
+ int stop_my_ftp_server(void)
+ {
+ if (g_server_pid > 0)
+ {
+ return kill(g_server_pid, SIGTERM);
+ }
+
+ return -ESRCH;
+ }
+
+ int start_my_ftp_server(void)
+ {
+ FTPD_SESSION handle;
+ int ret;
+
+ /* Initialize PID and clear stop flag BEFORE installing signal handlers */
+ g_server_pid = getpid();
+ g_ftp_stop = 0;
+
+ /* Install signal handlers to allow clean shutdown via kill or Ctrl+C */
+ signal(SIGINT, ftp_signal_handler);
+ signal(SIGTERM, ftp_signal_handler);
+
+ /* 1. Open the FTP server listening on standard port 21 (IPv4) */
+
+ handle = ftpd_open(21, AF_INET);
+ if (handle == NULL)
+ {
+ fprintf(stderr, "ERROR: Failed to open FTP server on port 21\n");
+ g_server_pid = -1;
+ return -EIO;
+ }
+
+ /* 2. Configure user accounts (replace placeholders with strong
credentials) */
+
+ /* Admin account: full access starting at filesystem root */
+ ret = ftpd_adduser(handle, FTPD_ACCOUNTFLAG_ADMIN,
+ "admin", "<strong-admin-password>", "/");
+ if (ret < 0)
+ {
+ fprintf(stderr, "Failed to add admin user: %d\n", ret);
+ ftpd_close(handle);
+ g_server_pid = -1;
+ return ret;
+ }
+
+ /* Guest account: unprivileged access restricted to /mnt/sdcard */
+ ret = ftpd_adduser(handle, FTPD_ACCOUNTFLAG_GUEST,
+ "guest", "<strong-guest-password>", "/mnt/sdcard");
+ if (ret < 0)
+ {
+ fprintf(stderr, "Failed to add guest user: %d\n", ret);
+ ftpd_close(handle);
+ g_server_pid = -1;
+ return ret;
+ }
+
+ printf("FTP server running on port 21. Waiting for connections...\n");
+
+ /* 3. Server connection loop: runs until g_ftp_stop is set */
+
+ while (!g_ftp_stop)
+ {
+ /* Wait up to 5000 ms for incoming connection requests */
+ ret = ftpd_session(handle, 5000);
+ if (ret == 0)
+ {
+ printf("FTP client connected and session worker spawned.\n");
+ }
+ else if (ret != -ETIMEDOUT)
+ {
+ fprintf(stderr, "ftpd_session error: %d\n", ret);
+ break;
+ }
+ }
+
+ /* 4. Cleanup and shutdown upon loop exit */
+
+ printf("Shutting down FTP server...\n");
+ ftpd_close(handle);
+ g_server_pid = -1;
+ return OK;
+ }
+
+Embedded Design & Resource Tuning
+=================================
+
+1. **Stack Sizing for Worker Threads**: Each active FTP client connection
creates a
+ worker thread. Ensure ``CONFIG_FTPD_WORKERSTACKSIZE`` is sized
appropriately for
+ the underlying filesystem driver (e.g., FAT filesystems or LittleFS
typically
+ require at least 2048 to 3072 bytes of stack space).
+2. **Buffer Sizing for Network vs. Flash Throughput**:
``CONFIG_FTPD_DATABUFFERSIZE``
+ controls the chunk size read and written during file transfers (default: 512
+ bytes). Increasing this buffer to match the storage block size (e.g., 1024
or 2048
+ bytes) improves throughput on high-speed Ethernet targets at the expense of
RAM.
+3. **Passive Mode on NAT / Firewalled Networks**: Embedded devices positioned
+ behind firewalls should instruct remote clients to use **Passive Mode**
+ (``PASV`` or ``EPSV``), ensuring the data connection is initiated by the
client
+ toward the embedded server rather than requiring the server to initiate
inbound
+ connections to client ports.