Main page | Install | ttyreplay(1) | rpldev(4) | rpl(5) | ttyrpld(7) | rplctl(8) | rpld(8) | Netlogging | Support


Name > rpldev - tty logger kernel module
 
Description >

/dev/rpl is a character device file which returns the data captured from ttys through the rpldev kernel module. It has no fixed device number, since it asks for a dynamic major/minor number. Usually, it will get char(10,63) or char(10,62) on Linux -- the Kernel module will emit a notice where it actually landed. The hotplug framework and udev will then create a device node in /dev.

On FreeBSD, devfs takes care of all this, so when the module is loaded, a working /dev/rpl is also present. For OpenBSD, it always loads at the same number, char(128,0). Use mknod /dev/rpl b 128 0 to create the node. It should be made mode 0400.

Linux 2.4 is a special case. Unless you backported hotplug and udev, you will need to load it with a static minor number using the Minor_nr parameter and create a device node for it like for OpenBSD.

 
Module parameters >

The rpldev module has the following options. Some of them may be changed dynamically at run-time via /sys/module/rpldev/.

Bufsize Size of the ring buffer in bytes. Default is 64K.
Minor_nr Force a minor number rather than automatically deciding for one. Passing 255 here will use auto-selection, and is the default.

These options can be provided to modprobe like this:

# modprobe rpldev Minor_nr=37

If you cannot influence the modprobe call, or do not should (do not modify /etc/init.d/rpld if you can avoid it), you can put the options into /etc/modules.conf (2.4) or /etc/modprobe.conf (2.6):

options rpldev Minor_nr=37

I have not found any way for passing or modifying options under BSD, so you are stuck with a fixed 64K buffer.

 
Data structures >

Everytime the kernel functions for reading/writing from/to a terminal are executed, the call chain is extened into the rpldev hooks, i.e. an external function in the rpldev kernel module is called, which transfers the tty buffer into so-called packets, which are then returned as /dev/rpl is read.

A packet consists of a device number, magic byte (always 0xEE), size of the data, timestamp, and of course, the data itself. All fields are little-endian and packed, i.e. there are no alignment gaps. It can be represented in this C struct:

struct rpldev_packet {
    uint32_t dev;
    uint16_t size;
    uint8_t event, magic;
    struct timeval time;
} __attribute__((packed));

The data itself is actually not included in the struct, since it is of dynamic length. For further reference, the struct alone will be called packet header, whereas packet header plus data (or payload) equals packet. There are no byte-aligning gaps between the members, i.e. it is a so-called packed structure. (No pun between packet and packed.)

The .dev member contains the device number on which the event occurred. Since both the master and the slave side of a pty pair can generate events, and we usually do not need the master side events, they are already dropped at the kernel level.

The device field is made up of the in-kernel dev_t thing in Linux 2.6, i.e. major is in bits 20-31, minor in bits 0-19, all little-endian. BSD rpldev will convert device numbers to this scheme. As a result, a truncation is involved, since BSD uses 8-bit majors and 24-bit minors, so minors greater than 1048575 will be truncated.

The following event types exist:

enum {
    EVT_INIT = 'i',
    EVT_OPEN = 1,
    EVT_READ = 2,
    EVT_WRITE = 3,
    EVT_IOCTL = 4,
    EVT_CLOSE = 5,
    EVT_DEINIT = 'd',
    EVT_ID_DEVPATH = 241,
};

EVT_INIT is generated is generated when the tty is initialized. This usually happens when you open() it the first time.

EVT_OPEN, EVT_READ, EVT_WRITE and EVT_CLOSE are generated whenever an open(), read(), write() or close(), respectively, is done.

EVT_DEINIT is generated when the tty is about to be deinitialized. In theory, you do not know when a device will do this (i.e. deferred deinit). However, you've got the Kernel sources, and as such know when it actually happens (e.g. when the last open filedescriptor is closed).

EVT_IOCTL is generated when ioctl() is called on a tty. The data will consist of one uint32_t describing the cmd parameter. (See ioctl(2).)

During an open() on a tty line, the filename of the accessed dentry is extracted for convenience, so that rpld does not need to search for it.

 

by Jan Engelhardt