Configure FTP

The :url capability supported by the server allows the server to act as an FTP client to retrieve remote configuration files.

Note

Use of an FTP server and the :url capability is optional.

Requirements:

  • Server built with WITH_CURL make flag

    • YumaPro Core and Advanced binary packages are built with this flag

  • Server using setting --with-url='true'

  • Server using setting --with-url-ftp='true'

The server uses libcurl APIs to access the FTP server.

This section describes how to use FTP with a username and password, where each user is limited to their own home directory (and sub-directories).

Install and Configure an FTP Server

An FTP server must be installed and configured somewhere in the system.

  • This step is outside the scope of the YumaPro SDK

  • This section is intended to provide an example and is not required. The FTP server may be different in your system.

The vsftpd FTP server is used.

Install vsftpd on Ubuntu 22.04

sudo apt-get update
sudo apt-get install vsftpd -y

Configure an FTP User

In this example a special user account is created but real user names could be used instead.

sudo adduser ftpuser

Additional Configuration

The default config file is used in this example. Additional configuration may be needed depending on your system.

  • Firewall settings (ufw)

  • AppArmor settings

Restart the FTP Server

Make sure the server is running with the new configuration.

 andy@myhost:~$ sudo service vsftpd restart
 andy@myhost:~$ sudo service vsftpd status
 ● vsftpd.service - vsftpd FTP server
      Loaded: loaded (/lib/systemd/system/vsftpd.service; enabled; vendor preset: enabled)
      Active: active (running) since Fri 2025-12-26 11:53:27 PST; 3s ago
     Process: 816324 ExecStartPre=/bin/mkdir -p /var/run/vsftpd/empty (code=exited, status=0/SUCCESS)
    Main PID: 816326 (vsftpd)
       Tasks: 1 (limit: 76662)
      Memory: 852.0K
         CPU: 2ms
      CGroup: /system.slice/vsftpd.service
              └─816326 /usr/sbin/vsftpd /etc/vsftpd.conf

Test the FTP Server with Curl

Try a 'curl' command

andy@myhost:~$ curl ftp://ftpuser:mypassword@localhost/site-configs/test2.xml

Success

A successful response justs displays the file and does not print any error messages.

<?xml version="1.0" encoding="UTF-8"?>
<config
  xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx"
  ncx:last-modified="2025-12-20T18:03:51Z" ncx:etag="31186"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
    <groups>
      <group>
        <name>G1</name>
        <user-name>U1</user-name>
        <user-name>U5</user-name>
      </group>
      <group>
        <name>G3</name>
        <user-name>U2</user-name>
      </group>
    </groups>
  </nacm>
</config>

Access Denied Error

If the login does not succeed (e.g. wrong username or password), then curl returns an error:

curl: (67) Access denied: 530

File Not Found Error

If the login succeeds but the file does not exist, then curl returns an error:

curl: (78) The file does not exist

Test the FTP Server with yangcli-pro

Try a NETCONF operation that supports the :url capability.

andy@localhost> compare-config source-backup=test1.xml target-url="ftp://ftpuser:mypassword@localhost/site-configs/test2.xml"

The server request received:

<?xml version="1.0" encoding="UTF-8"?>
<rpc message-id="6"
 xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <compare-config xmlns="urn:yumaworks:params:xml:ns:yang:yumaworks-compare">
  <source-backup>test1.xml</source-backup>
  <target-url>ftp://ftpuser:mypassword@localhost/site-configs/test2.xml</target-url>
 </compare-config>
</rpc>

The server log will show the FTP retrieval attempt if the --log-level parameter is set to debug3 or higher.

Getting remote source for 'ftp://ftpuser:mypassword@localhost/site-configs/test2.xml'
libcurl version: // long line removed
*   Trying 127.0.0.1:21...
* Connected to localhost (127.0.0.1) port 21 (#0)
< 220 (vsFTPd 3.0.5)
> USER ftpuser
< 331 Please specify the password.
> PASS mypassword
< 230 Login successful.
> PWD
< 257 "/home/ftpuser" is the current directory
* Entry path is '/home/ftpuser'
> CWD site-configs
* ftp_perform ends with SECONDARY: 0
< 250 Directory successfully changed.
> EPSV
* Connect data stream passively
< 229 Entering Extended Passive Mode (|||35552|)
*   Trying 127.0.0.1:35552...
* Connecting to 127.0.0.1 (127.0.0.1) port 35552
* Connected to localhost (127.0.0.1) port 21 (#0)
> TYPE I
< 200 Switching to Binary mode.
> SIZE test2.xml
< 213 527
> RETR test2.xml
< 150 Opening BINARY mode data connection for test2.xml (527 bytes).
* Maxdownload = -1
* Getting file with size: 527
* Remembering we are in dir "site-configs/"
< 226 Transfer complete.
* Connection #0 to host localhost left intact

Done getting remote source to file '/tmp/netconfd-pro-target-url3.txt' (ok)

Success

The server will return the RPC output parameters instead of an error.

<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="6"
 xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <differences xmlns="urn:yumaworks:params:xml:ns:yang:yumaworks-compare">
  <yang-patch>
   <patch-id>compare-config</patch-id>
   <edit>
    <edit-id>E1</edit-id>
    <operation>delete</operation>
    <target>/ietf-netconf-acm:nacm</target>
   </edit>
  </yang-patch>
 </differences>
</rpc-reply>

The yangcli-pro reply in JSON format:

{
  "yuma-netconf:rpc-reply": {
    "yumaworks-compare:differences": {
      "yang-patch": {
        "patch-id":"compare-config",
        "edit": [
          {
            "edit-id":"E1",
            "operation":"delete",
            "target":"/ietf-netconf-acm:nacm"
          }
        ]
      }
    }
  }
}

Access Denied Error

If the FTP server access failed, the server log might show the following type of information:

Getting remote source for 'ftp://ftpuser:mypassword@localhost/site-configs/test2.xml'
libcurl version: // long line removed
*   Trying 127.0.0.1:21...
* Connected to localhost (127.0.0.1) port 21 (#0)
< 220 (vsFTPd 3.0.5)
> USER ftpuser
< 331 Please specify the password.
> PASS mypassword
< 530 Login incorrect.
* Access denied: 530
* Closing connection 0

Done getting remote source to file '/tmp/netconfd-pro-target-url3.txt' (operation failed)

The server will return an error response:

<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="7" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
 xmlns:ypcmp="urn:yumaworks:params:xml:ns:yang:yumaworks-compare"
 xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx"
 xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <rpc-error>
  <error-type>protocol</error-type>
  <error-tag>operation-failed</error-tag>
  <error-severity>error</error-severity>
  <error-app-tag>general-error</error-app-tag>
  <error-path>/nc:rpc/ypcmp:compare-config/ypcmp:target-url</error-path>
  <error-message xml:lang="en">operation failed</error-message>
  <error-info>
   <error-number>274</error-number>
  </error-info>
 </rpc-error>
</rpc-reply>

The yangcli-pro response in JSON:

{
  "yuma-netconf:rpc-reply": {
    "rpc-error": [
      {
        "error-type":"protocol",
        "error-tag":"operation-failed",
        "error-severity":"error",
        "error-app-tag":"general-error",
        "error-path":"/nc:rpc/ypcmp:compare-config/ypcmp:target-url",
        "error-message":"operation failed",
        "error-info": {
          "error-number":"274"
        }
      }
    ]
  }
}

File Not Found Error

If the login succeeds but the file does not exist, then the FTP server returns an error.

The server log may show:

Getting remote source for 'ftp://ftpuser:mypassword@localhost/site-configs/test2.xml'
libcurl version: // long line removed
*   Trying 127.0.0.1:21...
* Connected to localhost (127.0.0.1) port 21 (#0)
< 220 (vsFTPd 3.0.5)
> USER ftpuser
< 331 Please specify the password.
> PASS mypassword
< 230 Login successful.
> PWD
< 257 "/home/ftpuser" is the current directory
* Entry path is '/home/ftpuser'
> CWD site-configs
* ftp_perform ends with SECONDARY: 0
< 250 Directory successfully changed.
> EPSV
* Connect data stream passively
< 229 Entering Extended Passive Mode (|||40649|)
*   Trying 127.0.0.1:40649...
* Connecting to 127.0.0.1 (127.0.0.1) port 40649
* Connected to localhost (127.0.0.1) port 21 (#0)
> TYPE I
< 200 Switching to Binary mode.
> SIZE test2.txt
< 550 Could not get file size.
* The file does not exist
* Remembering we are in dir "site-configs/"
* Connection #0 to host localhost left intact

Done getting remote source to file '/tmp/netconfd-pro-target-url3.xml' (operation failed)

The server will return an error response:

<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="8" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
 xmlns:ypcmp="urn:yumaworks:params:xml:ns:yang:yumaworks-compare"
 xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx"
 xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <rpc-error>
  <error-type>protocol</error-type>
  <error-tag>operation-failed</error-tag>
  <error-severity>error</error-severity>
  <error-app-tag>general-error</error-app-tag>
  <error-path>/nc:rpc/ypcmp:compare-config/ypcmp:target-url</error-path>
  <error-message xml:lang="en">operation failed</error-message>
  <error-info>
   <error-number>274</error-number>
  </error-info>
 </rpc-error>
</rpc-reply>

The yangcli-pro response in JSON:

{
  "yuma-netconf:rpc-reply": {
    "rpc-error": [
      {
        "error-type":"protocol",
        "error-tag":"operation-failed",
        "error-severity":"error",
        "error-app-tag":"general-error",
        "error-path":"/nc:rpc/ypcmp:compare-config/ypcmp:target-url",
        "error-message":"operation failed",
        "error-info": {
          "error-number":"274"
        }
      }
    ]
  }
}