Lunatik

linuxModule

Various Linux kernel facilities.

This library includes functions for random number generation, sleeping, tracing, time retrieval, kernel symbol lookup, network interface and namespace ids and errno names. Kernel constants live in the linux.* modules, as require("linux.stat") for file modes and require("linux.task") for task states.

Functions

errname (err) Returns the symbolic name of a kernel error number.
hwaddr (ifindex) Gets the HW address for the network interface index.
ifindex (interface_name) Gets the interface index for a network device name.
lookup (symbol_name) Looks up a kernel symbol by name.
netns ([pid]) Gets the inode number that identifies a network namespace, the one /proc/<pid>/ns/net links to and lsns prints.
random ([m[, n]]) Generates pseudo-random integers.
schedule ([timeout[, state]]) Puts the current task to sleep.
time () Gets the current real time.
tracing ([on]) Reads or sets whether kernel tracing is on.

Functions in detail

errname (err)
Returns the symbolic name of a kernel error number. For example, it converts 2 to "ENOENT".

Parameters

  • err integer error number (e.g., 2), from -INT_MAX to INT_MAX.

Returns

    string symbolic error name (e.g., “ENOENT”), or “unknown” if the name cannot be resolved. The sign of err is ignored.

Raises

“out of bounds” for an err outside that range.

Usage

local name = linux.errname(2)
print("Error name:", name) -- "ENOENT"
hwaddr (ifindex)
Gets the HW address for the network interface index. Resolved in the initial network namespace: a device of another namespace is not found there (see linux.netns).

Parameters

  • ifindex integer interface index number, from 1 to INT_MAX.

Returns

    string interface HW address, or nil if no device has that index.

Raises

“out of bounds” for an index outside that range.

Usage

local addr = linux.hwaddr(index)
print(string.byte(addr,1,6))
ifindex (interface_name)
Gets the interface index for a network device name. Resolved in the initial network namespace: a device of another namespace is not found there (see linux.netns).

Parameters

  • interface_name string network interface name (e.g., “eth0”).

Returns

    integer interface index, or nil if no device has that name.

Usage

local index = linux.ifindex("lo")
print("Index of lo:", index)
lookup (symbol_name)
Looks up a kernel symbol by name. Uses kallsyms_lookup_name (potentially via kprobes) to find the address of a kernel symbol. In a module build, the usual one, that function is resolved through a kprobe when lunatik loads: without CONFIG_KPROBES, or if that kprobe fails to register, every lookup returns nil. Safe to call from softirq and hardirq.

Parameters

  • symbol_name string kernel symbol name to look up.

Returns

    lightuserdata symbol address if found, otherwise nil.

Usage

local addr = linux.lookup("jiffies")
if addr then print("Address of jiffies:", addr) end
netns ([pid])
Gets the inode number that identifies a network namespace, the one /proc/<pid>/ns/net links to and lsns prints. Without a pid it is the initial namespace’s, where linux.ifindex resolves a name; a device notifier.netdevice reports is in that namespace when the number it hands the callback is this one.

Parameters

  • pid integer a task whose network namespace to identify, 1 to PID_MAX_LIMIT, in the initial pid namespace: the number task:pid() returns, whichever task makes the call. (optional)

Returns

    integer inode number of the namespace; nil and "ESRCH" if no task has that pid, or the task has exited.

Raises

Error if the pid is out of bounds, and “not allowed once the runtime is armed” for a pid from an interrupt-context runtime past its body, where the task’s lock would be taken in softirq or hardirq.

Usage

local home = linux.netns()
random ([m[, n]])
Generates pseudo-random integers. Mimics the behavior of Lua’s math.random but uses kernel’s random number generation facilities (get_random_u32 or get_random_u64).

Parameters

  • m integer Lower bound of the range. If only one argument n is provided, m defaults to 1. (optional)
  • n integer Upper bound of the range. (optional)

Returns

    integer A pseudo-random integer. - If called without arguments, returns an integer with all bits pseudo-random. - If called with one integer n, returns a pseudo-random integer in the range [1, n]. - If called with two integers m and n, returns a pseudo-random integer in the range [m, n].

Raises

Error if m > n or if the interval is too large.

Usage

local r1 = linux.random()       -- Full range random integer
local r2 = linux.random(100)    -- Random integer between 1 and 100
local r3 = linux.random(50, 60) -- Random integer between 50 and 60
schedule ([timeout[, state]])
Puts the current task to sleep. Sets the current task’s state and schedules it out until a timeout occurs or it is woken up.

Parameters

  • timeout integer Duration in milliseconds to sleep, from 0 to 231 - 1; omitted or nil, the sleep lasts until the task is woken. (optional)
  • state integer task state to set before sleeping: linux.task.INTERRUPTIBLE (the default), UNINTERRUPTIBLE, KILLABLE or IDLE; any other raises “invalid task state”. (optional)

Returns

    integer remaining time in milliseconds if the sleep was interrupted before the full timeout, or 0 if the full timeout elapsed.

Raises

Error if an invalid task state is provided, “out of bounds” for a timeout outside its range, and “not allowed once the runtime is armed” from an interrupt-context runtime past its body.

Usage

local task = require("linux.task")
linux.schedule(1000) -- Sleep for 1 second (interruptible)
linux.schedule(500, task.UNINTERRUPTIBLE) -- Sleep for 0.5 seconds (uninterruptible)
time ()
Gets the current real time.

Returns

    integer current time in nanoseconds since the epoch (from ktime_get_real_ns).
tracing ([on])
Reads or sets whether kernel tracing is on. Given a boolean, turns tracing on through tracing_on() or off through tracing_off(), which stops the top-level ring buffer and keeps what it holds, so a hook can end the trace where the event it looks for happens. Given none or nil, changes nothing. Either way it returns tracing_is_on(), the state /sys/kernel/tracing/tracing_on shows. Safe to call from softirq and hardirq.

Parameters

  • on boolean true turns tracing on, false turns it off; omitted or nil reads it. (optional)

Returns

    boolean true if tracing is on, false if it is off, after any change.

Raises

“boolean expected” if on is neither a boolean nor nil

Usage

linux.tracing(false) -- end the trace here
if linux.tracing() then print("tracing is on") end