NcFTPd Event Daemon

Starting with version 2.4.0 of NcFTPd, you can use an external process to react to user activity in near real-time. This can be useful if you need to take action immediately when a remote user does something that's important to your site.  Such "events" include logging in, logging out, uploading files, downloading files, removal of files and directories, directory creations, mode changes.

An example would be the case when the administrator wants to be notified by e-mail when an important customer uploads a file that needs to be processed immediately.  In this case, your event processing daemon would be responsible for running a mail agent when a file that matched your criteria was been uploaded.

If you do have a need for event processing, then you need to write a program using the Event Daemon Software Development Kit.  The SDK includes ready-to-use source code for quick deployment using the C or Perl programming languages, so all that needs to be implemented is the code that processes the events.  The ncftpd_eventd option in the general.cf file is used to configure NcFTPd to send event messages to your process.

Note:  As an alternative, you could take advantage of the general.cf configuration options upload-event-processor, et al.  These options tell the server to run a program each time that event occurs.  The disadvantage to doing that is that this program would be run each time an upload occurs and this could degrade system performance.  There are also security implications, since this program or script is run with superuser privileges.

 

Choices of Event Message Delivery

As of NcFTPd 2.7.1, there are two options on how your event daemon can communicate with NcFTPd: UDP/IP packets and System V IPC.  UDP exchanges messages with NcFTPd and your event daemon with IP packets, while the System V IPC option uses a global system message queue to exchange messages.

Using UDP, your event daemon can be located on a different server machine than the machine that NcFTPd is running on.  Doing so can be undesirable because UDP does not guarantee delivery possibly resulting in dropped event messages, can duplicate messages, or deliver messages out-of-order.  It also introduces the possibility that a packet sniffer could examine event messages, or have some other rogue client spoof event messages.

The message queue option provides the advantage of being able to have very large message backlogs, and since the message queue is global to the system, the message queue can be added to without necessarily having a receiver up and ready to receive the messages, i.e., your event daemon could exit, restart five minutes later, and be able to process messages dropped into the queue in the five minutes it wasn't running.  The message queue also provides reasonable security, since messages cannot be sniffed, nor can unauthorized programs add messages to the queue.

The disadvantages to the message queue option are that it requires that the event daemon run on the same machine as NcFTPd, and that some operating systems may not support System V IPC (shared memory, semaphores, and message queues).  Most modern UNIX variants now support by default, or can be configured to support System V IPC, so we feel this is the best option to choose if possible.

 

Server Setup

After building your program, you set the ncftpd_eventd option in the general.cf file to point to your program.  For example, if you chose the UDP option, and your program listens on UDP port 9721 on IP address 127.0.0.1, you would set:

ncftpd_eventd=127.0.0.1:9721

If you chose the message queue option, you use the special keyword "mqueue:" along with the message queue key ID.  The key is simply an arbitrary 32-bit identifier that distinguishes your message queue from other message queues on the system (i.e., very similar to a port number).  We suggest using the hex number 78C0FFEE, as your key, so your general.cf option might look like:

ncftpd_eventd=mqueue:0x78C0FFEE

Consult the documentation for the ncftpd_eventd option, whose syntax allows you to set other properties of the message queue such as permission bits.  Once you have set the option, NcFTPd will start sending messages the next time you restart NcFTPd, so don't restart it until your event daemon is completed.

 

Message Handling

It is important to note that your event daemon should not spend too much time on each event.  This is especially important with UDP, since if the socket receive buffer fills up while your event daemon is doing something, subsequent messages will be lost.  Therefore, it may be advisable to make your event daemon multi-threaded, or at least spawn a new process for each event that needs significant processing time.

Your event daemon need not worry about the actual communications details between itself and NcFTPd, since the SDK's boilerplate code handles this for you.  You should be aware that your event daemon does not acknowledge or otherwise send messages to NcFTPd; your event daemon receives messages only.

Note: By default, transfers are not logged in real-time.  To understand why this is the case, consult the documentation for the require-implicit-ack-for-downloads option.

Message Structure

NcFTPd sends you messages whose contents is simply a string of ASCII characters.  In fact, it is really just 8 bytes plus a variable-length string that is also used for logging.  To make things a bit easier to parse and verify, the message beings with the characters "STR" followed by a newline (linefeed) character.

Note: Although this document details the message exchange protocol, you don't need to worry about this unless you're not using the prefab code.  In that case, you can safely skip to the bottom and start working on applying the changes you need to the prefab event daemon.

This is followed by the length of the variable contents of the message, which is always a four character field with a the fourth character being a newline (linefeed).  The remaining characters of the length field is the number of characters, expressed as an ASCII string.  For example, if the length of the variable area was 158 bytes, you woulds see (in hex) 3135380A, which is simply an ASCII '1' character followed by a '5', an '8', and a newline.  Therefore, an easy way to get the length in C would be to use the atoi() or sscanf() function.

Followed by the header, the variable-length string is expressed as a sequence of newline-delimited tokens.  You must inspect the contents of the variable-length portion to figure out which event was received and what it's parameters were.  The first field determines the message type.  This can be:

To illustrate, here's an example message in entirety:
STR
101
UPLOAD
anonymous

a@localhost
loopback
localhost
/home/ftp/incoming/services
4570
0.020
227.408

OK
I

1001169129
The next 5 fields are the same for all event types: The remaining fields are dependent on the event type.
Download and Upload Message
Directory Listing Message
Login Message
(no additional fields)
Logout Message
Delete Message
Mkdir Message
Rename Message
Symlink Message
Chmod Message

 

The software development kit

To get you started, source code for a sample NcFTPd Event Daemon is available, in both C and Perl language kits.  Download the kit below, which contains both the C and Perl source code.

Once you've downloaded the SDK, use the gzip and tar programs as you normally would to extract the archive, i.e.:

gzip -d -c eventd.tar.gz | tar xvf -
cd ./ncftpd_eventd_sdk

If you wish to use the Perl version, you will need to edit and run the ncftpd_eventd.pl script file.  The top of the script contains further instructions on how to configure and customize your event daemon.  The script was written using Perl 5.005, so you may need upgrade your system's version of Perl if the script fails to run.

Otherwise, if you're using the C version, you'll need to configure and build the program.  To do that you simply run "/bin/sh ./configure" and "make".  To customize it, you need to edit on_event.c and modify the event handlers. So, to process upload messages, you simply modify the OnUpload() function in on_event.c.

To run your ncftpd_eventd event daemon, you can simply invoke it from a shell prompt with "./ncftpd_eventd -p 9721 -v".  The "-p" flag specifies a UDP port number, and the "-v" flag tells it to run in debug mode so it outputs log messages.  If you're using the message queue option, you would use the "-k" option instead of the "-p" option, i.e., "./ncftpd_eventd -k 0x78C0FFEE -v".  Like NcFTPd, it doesn't put itself in the background automatically -- this allows you to use it in the /etc/inittab so you can have it respawn automatically if it dies.  If you do want it to go in the background automatically, you can use the "-d" option.

The Perl version is invoked similarly, only you use "ncftpd_eventd.pl" in place of "ncftpd_eventd".  So, if you're using the message queue option, you might run your script like "./ncftpd_eventd.pl -k 0x78C0FFEE -v".

Once you have your event daemon running, set the ncftpd_eventd general.cf option and restart NcFTPd to have it start sending event messages.  If you're running your event daemon from a shell prompt, you should see messages logged to the screen if you're using the "-v" option and you haven't disabled the verbose logging messages.

After you've finished customizing your event daemon, you should install it permanently (we suggest in /usr/local/sbin) and configure your operating system so that it starts up automatically when the system starts up.  Usually this means creating an "rc" script in "init.d", editing rc.local, the inittab, etc.

Up
NcFTPd HomeNext: Example 1