2013-05-29 01:22:35 +00:00
|
|
|
Configuring Serval DNA
|
|
|
|
======================
|
2016-02-29 05:49:59 +00:00
|
|
|
[Serval Project][], March 2016
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
Introduction
|
|
|
|
------------
|
|
|
|
|
|
|
|
The [Serval DNA][] daemon, also called **servald**, is designed to operate in a
|
|
|
|
wide variety of environments (GNU/Linux, Android, Solaris, iOS) with different
|
|
|
|
kinds of network links (Wi-Fi, Ethernet, packet radio, dummy), different levels
|
|
|
|
of resources (CPU, memory, persistent storage) and for different purposes
|
|
|
|
(development, testing, deployment).
|
|
|
|
|
|
|
|
In order to adapt to all of these requirements, **servald** can be *configured*
|
|
|
|
to adjust its behaviour in the following areas:
|
|
|
|
|
|
|
|
* [file system layout](#file-system-layout)
|
|
|
|
* [logging](#logging)
|
|
|
|
* [network interfaces](#network-interfaces)
|
|
|
|
* [Rhizome][]
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2013-03-21 03:44:12 +00:00
|
|
|
Configuration options
|
|
|
|
---------------------
|
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
The [Serval DNA][] configuration is expressed as an unordered set of
|
|
|
|
textual LABEL=VALUE pairs called *options*. For example:
|
2013-04-16 03:14:47 +00:00
|
|
|
|
|
|
|
debug.verbose=true
|
|
|
|
interfaces.0.file=/var/tmp/serval/dummy
|
|
|
|
interfaces.0.socket_type=file
|
|
|
|
log.file.directory_path=/var/tmp/serval-logs
|
|
|
|
log.file.duration=20m
|
|
|
|
log.file.rotate=10
|
|
|
|
rhizome.direct.peer.0.host=129.96.12.91
|
|
|
|
server.respawn_on_crash=true
|
|
|
|
|
2013-05-29 01:22:35 +00:00
|
|
|
An option **LABEL** is a sequence of one or more [US-ASCII][] alphanumeric
|
|
|
|
words separated by period characters, eg, `log.file.directory_path`. If a
|
|
|
|
LABEL is not recognised, it is *unsupported*.
|
|
|
|
|
|
|
|
An option **VALUE** is a string of [US-ASCII][] characters, excluding newline
|
|
|
|
(character 10), which is parsed according to the option's *type*:
|
|
|
|
|
|
|
|
* decimal integer, eg: `10`, `0`, `-1000000`
|
|
|
|
* boolean, eg: `true`, `false`, `on`, `off`, `1`, `0`, `yes`, `no`
|
|
|
|
* internet address (in\_addr), eg: `192.168.1.1`
|
|
|
|
* time interval, eg: `12h`, `1w3d`, `2h15m30s`
|
|
|
|
* absolute path, eg: `/var/lib/serval`
|
|
|
|
* relative path, eg: `../lib/hostlist`
|
|
|
|
* Serval ID (SID), eg: `EEBF3AC19E7EE58722A0F6D4A4D5894A72F5C71030C3399FE75808DCF6C6254B`
|
|
|
|
* scaled decimal integer with optional suffix **k** (10^3), **K** (2^10),
|
|
|
|
**m** (10^6), **M** (2^20), **g** (10^9) or **G** (2^30), eg:
|
2013-04-16 03:14:47 +00:00
|
|
|
`1M` = 1,048,576
|
2013-04-15 07:00:45 +00:00
|
|
|
|
2013-05-29 01:22:35 +00:00
|
|
|
If a VALUE does not parse correctly, it is *invalid*.
|
2013-04-15 07:00:45 +00:00
|
|
|
|
2013-03-21 03:44:12 +00:00
|
|
|
Configuration persistence
|
|
|
|
-------------------------
|
|
|
|
|
|
|
|
**servald** stores its configuration option settings in a file called
|
2013-05-29 01:22:35 +00:00
|
|
|
`serval.conf` in its instance directory. It reads this file upon every
|
|
|
|
invocation. This means that each instance's option settings persist until
|
|
|
|
changed or until its `serval.conf` file is altered or removed.
|
2013-04-16 03:14:47 +00:00
|
|
|
|
|
|
|
The format of the file is as shown in the example above: each option is
|
|
|
|
represented by a single line in the file. Each line may have one of the forms:
|
|
|
|
|
|
|
|
[ WHITE ] LABEL "=" VALUE "\n"
|
|
|
|
[ WHITE ] "#" COMMENT "\n"
|
|
|
|
[ WHITE ] "\n"
|
|
|
|
|
|
|
|
where WHITE is any sequence of zero or more space or tab characters (as
|
|
|
|
classified by [isspace(3)][]), COMMENT is any sequence of characters except
|
|
|
|
newline, and LABEL and VALUE are as defined above.
|
|
|
|
|
|
|
|
Blank lines are ignored, as are lines beginning with the comment character `#`.
|
|
|
|
VALUE is parsed very strictly: all spaces are significant. A leading or
|
|
|
|
trailing space in VALUE can cause a numerical option to be invalid.
|
2013-03-21 03:44:12 +00:00
|
|
|
|
2016-01-11 06:15:08 +00:00
|
|
|
The order of the lines in the file has no significance. Changing the order of
|
|
|
|
lines will produce exactly the same result.
|
|
|
|
|
2013-03-21 03:44:12 +00:00
|
|
|
Invalid configuration
|
2012-10-30 02:14:43 +00:00
|
|
|
---------------------
|
|
|
|
|
2013-04-15 07:00:45 +00:00
|
|
|
Although `serval.conf` is usually written and read only by **servald**, in fact
|
|
|
|
it is an external file which may be modified, so **servald** has no control
|
|
|
|
over its contents. The semantics of the configuration loading anticipate the
|
2013-05-29 01:22:35 +00:00
|
|
|
possibility of encountering a *defective* file:
|
2013-03-21 03:44:12 +00:00
|
|
|
|
|
|
|
* If `serval.conf` is syntactically malformed, then **servald** will log a
|
|
|
|
warning, skip the malformed line and continue parsing;
|
|
|
|
|
2013-05-29 01:22:35 +00:00
|
|
|
* If the same LABEL appears more than once, then **servald** will log a
|
|
|
|
warning and ignore the second and all subsequent lines with the *duplicate*
|
|
|
|
LABEL;
|
|
|
|
|
|
|
|
* If an *unsupported* LABEL is encountered (which could be a mis-spelling of a
|
|
|
|
supported option), then **servald** will log a warning and ignore the line;
|
|
|
|
|
|
|
|
* If a configuration option has an *invalid* VALUE, then **servald** will log
|
|
|
|
a warning and leave the option with its built-in default value;
|
2013-03-21 03:44:12 +00:00
|
|
|
|
2013-05-29 01:22:35 +00:00
|
|
|
* If a logical relation, such as mutually incompatible or mandatory options,
|
|
|
|
is violated, then **servald** will log a warning and ignore the *illogical*
|
|
|
|
options or use default values.
|
2013-04-12 07:48:53 +00:00
|
|
|
|
|
|
|
In all the above cases, most **servald** commands will reject the defective
|
2013-05-29 01:22:35 +00:00
|
|
|
file by logging an error and exiting with error status (255). In this case,
|
|
|
|
logging is done using options salvaged from the defective file (see the [config
|
|
|
|
dump](#config-dump) command, described below).
|
2013-04-12 07:48:53 +00:00
|
|
|
|
|
|
|
Some “permissive” commands, such as `help`, `stop`, and the various `config`
|
|
|
|
commands described below, will not fail on a defective configuration file.
|
2013-04-15 07:00:45 +00:00
|
|
|
Instead they will log a warning and carry on using options salvaged from the
|
|
|
|
defective file. This means that **servald** may always be used to inspect and
|
|
|
|
correct the configuration, and to stop a running daemon, despite a defective
|
|
|
|
configuration file.
|
2013-03-21 03:44:12 +00:00
|
|
|
|
2014-03-26 05:05:43 +00:00
|
|
|
Configuration reloading
|
|
|
|
-----------------------
|
2013-04-16 03:14:47 +00:00
|
|
|
|
2014-03-26 05:05:43 +00:00
|
|
|
A running daemon re-loads its configuration whenever the `serval.conf` file is
|
|
|
|
changed. It does this by periodically checking the file's size and
|
|
|
|
modification time, and if they have changed, parses the file and updates its
|
|
|
|
own internal copy of the configuration settings.
|
|
|
|
|
|
|
|
As described above, the **servald** `start` command will not start a daemon
|
|
|
|
process if the `serval.conf` file is defective. However, the file may become
|
|
|
|
defective *after* the daemon has started.
|
|
|
|
|
|
|
|
In this case, the daemon will not terminate, nor load the defective file, but
|
|
|
|
will log an error and continue execution with its internal configuration
|
|
|
|
unchanged. The daemon's internal configuration will no longer be consistent
|
|
|
|
with the contents of the file. If the daemon is stopped or killed, it cannot
|
|
|
|
be re-started while `serval.conf` remains defective.
|
|
|
|
|
|
|
|
Despite detecting a defective configuration file, the daemon continues to check
|
|
|
|
for changes to the file, and attempts to re-load whenever it changes. As soon
|
|
|
|
as the defective `serval.conf` is fixed, the running daemon will load it
|
|
|
|
successfully and continue execution with the new configuration. The internal
|
|
|
|
configuration and the file contents will once again be consistent.
|
|
|
|
|
|
|
|
Daemon instances
|
|
|
|
----------------
|
2013-03-21 03:44:12 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
It order to support more than one [Serval DNA][] daemon running on the same
|
|
|
|
host, each daemon can be configured to use its own *instance directory*, as
|
|
|
|
follows:
|
2014-03-26 05:05:43 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
* A daemon's [instance directory](#instance-directory) can be set at run time
|
|
|
|
by setting the `SERVALINSTANCE_PATH` environment variable prior to starting
|
|
|
|
the daemon. This overrides the daemon's [standard file system
|
|
|
|
layout](#standard-file-system-layout). Once a daemon is running, the only
|
|
|
|
way to change its instance directory is to stop it and start another daemon
|
2014-03-26 05:05:43 +00:00
|
|
|
with a different value for the environment variable.
|
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
* If no [instance directory](#instance-directory) is set at run time, then if
|
|
|
|
**servald** was built with the `./configure INSTANCE_PATH=DIR` option, then
|
|
|
|
the **servald** executable will use the instance directory in `DIR` by
|
|
|
|
default, not the [standard file system layout](#standard-file-system-layout).
|
2014-03-26 05:05:43 +00:00
|
|
|
|
|
|
|
* On an Android system, if none of the above are used, then **servald** will
|
2016-02-29 05:49:59 +00:00
|
|
|
use the [instance directory](#instance-directory)
|
|
|
|
`/data/data/org.servalproject/var/serval-node`, not the [standard file
|
|
|
|
system layout](#standard-file-system-layout).
|
2014-03-26 05:05:43 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
* If none of the above apply, then the daemon uses the [standard file system
|
|
|
|
layout](#standard-file-system-layout). Only one daemon can run with the
|
|
|
|
standard layout on a host, since the single, common PID file will prevent
|
2016-10-13 22:53:04 +00:00
|
|
|
more than one being started.
|
2014-03-26 05:05:43 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
The main use for multiple instances on a single host is for testing, and so the
|
|
|
|
[instance directory](#instance-directory) is used extensively in the [automated
|
|
|
|
tests][]. Environments other than Android are unlikely to use an instance
|
|
|
|
path, so the [standard file system layout](#standard-file-system-layout) is
|
|
|
|
most likely to be used in most other deployments.
|
2014-03-26 05:05:43 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
File system layout
|
|
|
|
------------------
|
|
|
|
|
|
|
|
### Standard file system layout
|
2014-03-26 05:05:43 +00:00
|
|
|
|
|
|
|
By default, **servald** locates its files such as configuration, logs, Rhizome
|
|
|
|
storage, etc. in accordance with the [Filesystem Heirarchy Standard][FHS] 2.3:
|
|
|
|
|
|
|
|
* the **servald** executable is installed in `/usr/local/bin/servald`
|
|
|
|
* the configuration is stored in `/etc/serval/serval.conf`
|
|
|
|
* the keyring is stored in `/etc/serval/serval.keyring`
|
|
|
|
* the PID file is `/var/run/serval/servald.pid`
|
|
|
|
* the daemon creates its process information files under
|
|
|
|
`/var/run/serval/proc/`
|
|
|
|
* the daemon creates and rotates log files files under
|
|
|
|
`/var/log/serval/`
|
|
|
|
* the daemon creates and updates a symbolic link to the latest log file in
|
|
|
|
`/var/log/servald.log`
|
|
|
|
* the Rhizome store is in `/var/cache/serval/` (unless overridden by
|
|
|
|
configuration):
|
|
|
|
* the SQLite database is `/var/cache/serval/rhizome.db`
|
|
|
|
* large payloads are stored under `/var/cache/serval/blob/`
|
|
|
|
* the SQLite temporary directory is `/tmp/serval/sqlite3tmp/`
|
|
|
|
* dummy interface files are created under `/tmp/serval/` (unless overridden
|
|
|
|
by configuration)
|
|
|
|
|
|
|
|
The **servald** `start` command will create all sub-directories within the
|
|
|
|
standard FHS paths as needed, and any failure will cause the daemon not to
|
|
|
|
start.
|
|
|
|
|
|
|
|
The following build-time configuration options are available to alter the paths
|
|
|
|
described above, which can help adapt **servald** to systems which use a
|
|
|
|
different software installation convention (eg, all packages are installed
|
|
|
|
under `/opt/packagename`) or which have a volatile `/var` directory (eg, on
|
|
|
|
OpenWRT, `/var` is a symlink to `/tmp`):
|
|
|
|
|
|
|
|
* If **servald** is built with the `./configure --prefix=DIR` option, then
|
|
|
|
the executable is installed in `DIR/bin` instead of `/usr/local/bin`
|
|
|
|
|
|
|
|
* If **servald** is built with the `./configure --sysconfdir=DIR` option,
|
|
|
|
then it will use `DIR` in place of `/etc`
|
|
|
|
|
|
|
|
* If **servald** is built with the `./configure --localstatedir=DIR` option,
|
|
|
|
then it will use `DIR` in place of `/var`
|
|
|
|
|
|
|
|
* If **servald** is built with the `./configure SERVAL_ETC_PATH=DIR` option,
|
|
|
|
then it will use `DIR` in place of `/etc/serval`
|
|
|
|
|
|
|
|
* If **servald** is built with the `./configure SERVAL_RUN_PATH=DIR` option,
|
|
|
|
then it will use `DIR` in place of `/var/run/serval`
|
|
|
|
|
|
|
|
* If **servald** is built with the `./configure SYSTEM_LOG_PATH=DIR` option,
|
|
|
|
then it will use `DIR` in place of `/var/log`
|
|
|
|
|
|
|
|
* If **servald** is built with the `./configure SERVAL_LOG_PATH=DIR` option,
|
|
|
|
then it will use `DIR` in place of `/var/log/serval`
|
|
|
|
|
|
|
|
* If **servald** is built with the `./configure RHIZOME_STORE_PATH=DIR`
|
|
|
|
option, then it will use `DIR` in place of `/var/cache/serval` for the
|
|
|
|
Rhizome store
|
|
|
|
|
|
|
|
* If **servald** is built with the `./configure SERVAL_TMP_PATH=DIR` option,
|
|
|
|
then it will use `DIR` in place of `/tmp/serval`
|
|
|
|
|
|
|
|
The **servald** `config paths` command will display all the paths in use, based
|
|
|
|
on the built-in defaults as overridden by configuration settings and run-time
|
|
|
|
environment variables available to the command. This command will work even if
|
|
|
|
configuration is defective, so is a useful diagnostic tool.
|
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
### Instance directory
|
2014-03-26 05:05:43 +00:00
|
|
|
|
|
|
|
If **servald** is started with an *instance directory*, then all configuration,
|
|
|
|
state, and temporary files are stored in or beneath that directory, denoted
|
|
|
|
`IDIR`:
|
|
|
|
|
|
|
|
* the configuration is stored in `IDIR/serval.conf`
|
|
|
|
* the keyring is stored in `IDIR/serval.keyring`
|
|
|
|
* the PID file is `IDIR/servald.pid`
|
|
|
|
* the daemon creates its process information files under `IDIR/proc/`
|
|
|
|
* the daemon creates and rotates log files files under `IDIR/log/`
|
|
|
|
* the daemon creates and updates a symbolic link to the latest log file in
|
|
|
|
`IDIR/servald.log`
|
|
|
|
* the Rhizome store is in `IDIR/` (unless overridden by configuration):
|
|
|
|
* the SQLite database is `IDIR/rhizome.db`
|
|
|
|
* large payloads are stored under `IDIR/blob/`
|
|
|
|
* the SQLite temporary directory is `IDIR/sqlite3tmp/`
|
|
|
|
* dummy interface files are created under `IDIR/` (unless overridden by
|
|
|
|
configuration)
|
|
|
|
|
|
|
|
The **servald** `start` command will create its instance directory (and all
|
|
|
|
enclosing parent directories) if it does not already exist. Failure will cause
|
|
|
|
the daemon not to start.
|
2013-03-21 03:44:12 +00:00
|
|
|
|
2013-04-16 03:14:47 +00:00
|
|
|
About the examples
|
|
|
|
------------------
|
|
|
|
|
|
|
|
The examples in this document are [Bourne shell][] commands, using standard
|
|
|
|
quoting and variable expansion. Commands issued by the user are prefixed with
|
|
|
|
the shell prompt `$` to distinguish them from the output of the command.
|
|
|
|
Single and double quotes around arguments are part of the shell syntax, so are
|
|
|
|
not seen by the command. Lines ending in backslash `\` continue the command on
|
|
|
|
the next line.
|
|
|
|
|
2013-03-21 03:44:12 +00:00
|
|
|
Configuration commands
|
|
|
|
----------------------
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2013-05-29 01:22:35 +00:00
|
|
|
### config set
|
|
|
|
|
2012-10-30 02:14:43 +00:00
|
|
|
To set a configuration option:
|
|
|
|
|
|
|
|
$ servald config set name.of.option 'value'
|
|
|
|
$
|
|
|
|
|
2013-05-29 01:22:35 +00:00
|
|
|
### config del
|
|
|
|
|
2013-03-21 03:44:12 +00:00
|
|
|
To unset (remove) a configuration option, returning it to its default value:
|
2012-12-13 07:05:46 +00:00
|
|
|
|
|
|
|
$ servald config del name.of.option
|
|
|
|
$
|
|
|
|
|
2013-05-29 01:22:35 +00:00
|
|
|
### config set del
|
|
|
|
|
|
|
|
Several **set** and **del** commands can be chained together in a single
|
|
|
|
command:
|
|
|
|
|
|
|
|
$ servald config set debug.verbose 1 \
|
|
|
|
del debug.dnahelper \
|
|
|
|
set log.file.path /tmp/log.txt
|
|
|
|
$
|
|
|
|
|
|
|
|
### config get
|
|
|
|
|
|
|
|
To examine a single option's current value as defined in the `serval.conf` file
|
|
|
|
(invalid, unsupported and illogical options may be examined, but not duplicate
|
|
|
|
options):
|
2012-10-30 02:14:43 +00:00
|
|
|
|
|
|
|
$ servald config get name.of.option
|
|
|
|
name.of.option=value
|
|
|
|
$
|
|
|
|
|
2013-04-12 07:48:53 +00:00
|
|
|
To examine all option settings defined in the `serval.conf` file, including
|
2013-05-29 01:22:35 +00:00
|
|
|
invalid, unsupported and illogical options, but not duplicate options:
|
2012-10-30 02:14:43 +00:00
|
|
|
|
|
|
|
$ servald config get
|
|
|
|
interfaces=+eth0,+wifi0
|
|
|
|
name.of.option=value
|
|
|
|
name.of.other_option=value2
|
|
|
|
$
|
|
|
|
|
2013-05-29 01:22:35 +00:00
|
|
|
### config schema
|
|
|
|
|
2013-04-12 07:48:53 +00:00
|
|
|
To list the names and types of all supported configuration options (the
|
|
|
|
“configuration schema”):
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2012-12-13 07:05:46 +00:00
|
|
|
$ servald config schema
|
2013-03-05 02:05:30 +00:00
|
|
|
debug.broadcasts=(boolean)
|
|
|
|
debug.dnahelper=(boolean)
|
|
|
|
debug.dnaresponses=(boolean)
|
2012-12-13 07:05:46 +00:00
|
|
|
...
|
2013-03-05 02:05:30 +00:00
|
|
|
server.chdir=(absolute_path)
|
2013-03-21 03:44:12 +00:00
|
|
|
server.interface_path=(str_nonempty)
|
2013-03-05 02:05:30 +00:00
|
|
|
server.respawn_on_crash=(boolean)
|
2012-12-13 07:05:46 +00:00
|
|
|
$
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2013-04-12 07:48:53 +00:00
|
|
|
The configuration schema, with its default values, is defined in the
|
|
|
|
[conf_schema.h](../conf_schema.h) source header file.
|
|
|
|
|
2013-05-29 01:22:35 +00:00
|
|
|
### config dump
|
|
|
|
|
2013-04-12 07:48:53 +00:00
|
|
|
To examine all current *valid* configuration option settings, as produced by
|
2013-05-29 01:22:35 +00:00
|
|
|
parsing `serval.conf` and omitting invalid, unsupported, duplicate and
|
|
|
|
illogical options (ie, the configuration used by permissive commands and for
|
|
|
|
logging):
|
2012-12-13 07:05:46 +00:00
|
|
|
|
2013-03-21 03:44:12 +00:00
|
|
|
$ servald config dump --full
|
|
|
|
debug.broadcasts=false
|
|
|
|
debug.dnahelper=false
|
|
|
|
debug.dnaresponses=false
|
|
|
|
...
|
|
|
|
rhizome.rhizome_mdp_block_size=512
|
|
|
|
server.chdir=/
|
|
|
|
server.respawn_on_crash=true
|
|
|
|
$
|
2012-12-13 07:05:46 +00:00
|
|
|
|
2013-03-21 03:44:12 +00:00
|
|
|
Omitting the `--full` argument omits all options which have their default
|
|
|
|
value, leaving only the minimal settings that need be present in `serval.conf`
|
|
|
|
to produce the current configuration:
|
2012-12-13 07:05:46 +00:00
|
|
|
|
2013-03-21 03:44:12 +00:00
|
|
|
$ servald config dump
|
|
|
|
debug.rhizome=true
|
|
|
|
interfaces.0.file=/var/serval-node/dummy
|
|
|
|
interfaces.0.socket_type=file
|
|
|
|
rhizome.direct.peer.0.host=129.128.127.126
|
|
|
|
server.respawn_on_crash=true
|
|
|
|
$
|
2012-12-13 07:05:46 +00:00
|
|
|
|
|
|
|
Logging configuration
|
|
|
|
---------------------
|
|
|
|
|
|
|
|
**servald** logging is controlled by the following config options:
|
|
|
|
|
2013-04-12 07:48:53 +00:00
|
|
|
log.console.level=debug|info|hint|warn|error|none
|
|
|
|
log.console.dump_config=BOOLEAN
|
|
|
|
log.console.show_pid=BOOLEAN
|
|
|
|
log.console.show_time=BOOLEAN
|
|
|
|
|
|
|
|
log.android.level=debug|info|hint|warn|error|none
|
|
|
|
log.android.dump_config=BOOLEAN
|
|
|
|
log.android.show_pid=BOOLEAN
|
|
|
|
log.android.show_time=BOOLEAN
|
|
|
|
|
|
|
|
log.file.level=debug|info|hint|warn|error|none
|
|
|
|
log.file.dump_config=BOOLEAN
|
|
|
|
log.file.show_pid=BOOLEAN
|
|
|
|
log.file.show_time=BOOLEAN
|
|
|
|
log.file.path=PATH
|
|
|
|
log.file.directory_path=PATH
|
|
|
|
log.file.duration=INTERVAL
|
|
|
|
log.file.rotate=UINT
|
|
|
|
|
|
|
|
There are three log output destinations, each of which can be configured
|
|
|
|
independently of the others:
|
|
|
|
|
|
|
|
* The *console* log destination is the standard error of the **servald**
|
2013-04-15 07:00:45 +00:00
|
|
|
process, which is available in all command invocations of **servald**, but
|
|
|
|
not in the background daemon process (the daemon closes all its standard IO
|
|
|
|
streams when started in background mode).
|
2013-04-12 07:48:53 +00:00
|
|
|
|
2013-04-15 07:00:45 +00:00
|
|
|
* The *android* log destination is available in **servald** executables built
|
|
|
|
for the Android platform, and sends to the Android Log buffer that is
|
|
|
|
accessible via the `adb logcat` command. On non-Android platforms, the
|
2013-04-12 07:48:53 +00:00
|
|
|
`log.android` configuration options are supported but have no effect.
|
|
|
|
|
|
|
|
* The *file* log destination is a log file created and appended directly by
|
2013-04-15 07:00:45 +00:00
|
|
|
the **servald** process using the O\_APPEND option of [open(2)][] and a
|
|
|
|
single [write(2)][] system call per log line (so concurrent **servald**
|
|
|
|
processes will not corrupt each others' log lines). If the file does not
|
|
|
|
exist, **servald** will create it and all its enclosing directories as
|
|
|
|
needed.
|
2013-04-12 07:48:53 +00:00
|
|
|
|
|
|
|
All log destinations support the following configuration options:
|
|
|
|
|
|
|
|
* `log.DESTINATION.level` Log messages below this level are not sent to the
|
|
|
|
destination. The lowest level is `debug`, and the highest is `error`.
|
|
|
|
Setting this option to `none` suppresses all log messages.
|
|
|
|
|
|
|
|
* `log.DESTINATION.dump_config` If true, then the current configuration is
|
|
|
|
written to the destination (in `servald config dump` format), prior to
|
|
|
|
other messages.
|
|
|
|
|
|
|
|
* `log.DESTINATION.show_pid` If true, then every line written to this
|
|
|
|
destination is prefixed with the Process ID of the process that produced
|
|
|
|
it.
|
|
|
|
|
|
|
|
* `log.DESTINATION.show_time` If true, then every line written to this
|
|
|
|
destination is prefixed with the system time in millisecond resolution
|
|
|
|
(if available) in the format `HH:MM:SS.mmm`.
|
|
|
|
|
|
|
|
In addition, the *file* destination has these extra configuration options:
|
|
|
|
|
|
|
|
* `log.file.directory_path` If set, log files are created in this directory,
|
2014-03-26 05:05:43 +00:00
|
|
|
which is created if it does not exist. Relative paths are interpreted
|
|
|
|
relative to the `log` sub-directory of the instance directory. The default
|
|
|
|
setting (empty string) causes log files to be created within the `log`
|
|
|
|
sub-directory of the instance directory.
|
2013-04-12 07:48:53 +00:00
|
|
|
|
|
|
|
* `log.file.path` If set, all log messages are appended directly to the file
|
|
|
|
at the given path. If the path is not absolute, it is interpreted relative
|
|
|
|
the `log.file.directory_path` option. If `log.file.path` is not set, then
|
|
|
|
log files have names of the form `serval-YYYYMMDDHHMMSS.log`, using the
|
|
|
|
date/time of creation of the file.
|
|
|
|
|
|
|
|
* `log.file.duration` If non zero, then a new log file is created every new
|
|
|
|
interval. Interval boundaries are measured from the Unix epoch, so if the
|
|
|
|
interval is an integral divisor of one day then a new file will always
|
|
|
|
start at midnight. The interval can be given as a plain number of seconds,
|
|
|
|
but a convenient scaled notation is supported: `[Nw][Nd][Nh][Nm][N[s]]`,
|
|
|
|
eg, `2h40m20s` means two hours plus 40 minutes plis 20 seconds.
|
|
|
|
|
|
|
|
* `log.file.rotate` If non zero, then old log files are deleted so that no
|
|
|
|
more than this many files exist at one time.
|
|
|
|
|
|
|
|
Every log message is written to all destinations according to their
|
|
|
|
configuration.
|
|
|
|
|
2012-10-30 02:14:43 +00:00
|
|
|
Network interfaces
|
|
|
|
------------------
|
|
|
|
|
|
|
|
The **servald** daemon periodically scans its operating system's network
|
|
|
|
interfaces and uses its `interfaces` configuration option to select which to
|
|
|
|
ignore and which to use.
|
|
|
|
|
2012-12-13 07:05:46 +00:00
|
|
|
For example, the following configuration will use any interface whose name
|
2013-04-15 09:29:49 +00:00
|
|
|
starts with `eth` (eg, `eth0`, `eth1`) on port 7333 and any interface whose
|
|
|
|
name starts with `wifi` or `wlan` but is not `wifi0` or `wlan0` as a [Wi-Fi][]
|
|
|
|
on the default port number:
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2012-12-13 07:05:46 +00:00
|
|
|
$ servald config set interfaces.0.match 'eth*' \
|
|
|
|
set interfaces.0.type ethernet \
|
|
|
|
set interfaces.0.port 7333 \
|
|
|
|
set interfaces.1.match 'wifi0,wlan0' \
|
|
|
|
set interfaces.1.exclude true \
|
|
|
|
set interfaces.2.match 'wifi*,wlan*' \
|
2013-04-15 09:29:49 +00:00
|
|
|
set interfaces.2.type wifi
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2012-12-13 07:05:46 +00:00
|
|
|
The following configuration is equivalent to the above example, but uses the
|
|
|
|
“legacy”, single-option syntax (see below):
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2013-04-15 09:29:49 +00:00
|
|
|
$ servald config set interfaces \
|
2013-04-16 03:14:47 +00:00
|
|
|
'+eth=ethernet:7333,-wifi0,-wlan0,+wifi=wifi,+wlan=wifi'
|
2012-12-13 07:05:46 +00:00
|
|
|
|
2013-04-15 09:29:49 +00:00
|
|
|
The following two equivalent configurations will use all available interfaces,
|
|
|
|
treating all as Wi-Fi (the default type) with a 400 µs inter-packet delay (the
|
|
|
|
default packet interval for Wi-Fi):
|
2012-12-13 07:05:46 +00:00
|
|
|
|
|
|
|
$ servald config set interfaces.0.match '*'
|
2012-10-30 02:14:43 +00:00
|
|
|
$ servald config set interfaces '+'
|
|
|
|
|
2012-12-13 07:05:46 +00:00
|
|
|
Network interface rules
|
|
|
|
-----------------------
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2012-12-13 07:05:46 +00:00
|
|
|
As shown in the first example above, the `interfaces` config option contains a
|
|
|
|
numbered list of *rules* that are applied to all detected system interfaces in
|
|
|
|
order of ascending number. The general form of an interface rule is:
|
|
|
|
|
|
|
|
interfaces.UINT.match=PATTERN[, PATTERN ...]
|
2013-04-15 07:00:45 +00:00
|
|
|
interfaces.UINT.file=PATH
|
2012-12-13 07:05:46 +00:00
|
|
|
interfaces.UINT.exclude=BOOLEAN
|
2013-04-15 07:00:45 +00:00
|
|
|
interfaces.UINT.socket_type=SOCKTYPE
|
2012-12-13 07:05:46 +00:00
|
|
|
interfaces.UINT.port=PORT
|
2013-04-15 07:00:45 +00:00
|
|
|
interfaces.UINT.encapsulation=ENCAPSULATION
|
2012-12-13 07:05:46 +00:00
|
|
|
interfaces.UINT.default_route=BOOLEAN
|
2013-04-15 07:00:45 +00:00
|
|
|
interfaces.UINT.prefer_unicast=BOOLEAN
|
|
|
|
interfaces.UINT.send_broadcasts=BOOLEAN
|
|
|
|
interfaces.UINT.type=IFTYPE
|
|
|
|
interfaces.UINT.mdp_tick_ms=UINT_NONZERO
|
|
|
|
interfaces.UINT.packet_interval=UINT_NONZERO
|
2012-10-30 02:14:43 +00:00
|
|
|
|
|
|
|
where:
|
|
|
|
|
2013-05-29 01:22:35 +00:00
|
|
|
* PATTERN is a [shell wildcard][] pattern
|
|
|
|
* BOOLEAN is `true`, `false`, `1`, `0`, `yes`, `no`, `on` or `off`
|
|
|
|
* SOCKTYPE is `dgram`, `stream` or `file`
|
|
|
|
* ENCAPSULATION is `overlay` or `single`
|
|
|
|
* IFTYPE is `wifi`, `ethernet`, `catear` or `other`
|
|
|
|
* PORT is an unsigned decimal integer in the range 1 to 65535
|
|
|
|
* UINT is any unsigned decimal integer (with no `+` or `-` prefix)
|
|
|
|
* UINT\_NONZERO is an unsigned decimal integer ≥ 1
|
|
|
|
* PATH is an absolute or relative file path
|
|
|
|
* IN\_ADDR is an Internet address as accepted by [inet_aton(3)][], ie,
|
2012-12-13 07:05:46 +00:00
|
|
|
`N.N.N.N` where `N` is an integer in the range 0 to 255.
|
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
Exactly one of the [match](#match) and [file](#file) options must be set on an
|
|
|
|
interface. If neither or both are set, it is an error; the whole interface
|
|
|
|
rule is omitted from the configuration and `serval.conf` is treated as
|
|
|
|
defective (see above).
|
|
|
|
|
|
|
|
### `match`
|
2013-04-15 07:00:45 +00:00
|
|
|
|
|
|
|
If a rule specifies a `match` option, then each PATTERN is applied to the names
|
|
|
|
of the real system interfaces using the [fnmatch(3)][] standard library
|
2016-02-29 05:49:59 +00:00
|
|
|
function. If any PATTERN matches, then the rule's [exclude](#exclude) option
|
|
|
|
is checked: if true, then the interface is not activated, otherwise a socket on
|
|
|
|
that system interface is opened and the interface's
|
|
|
|
[socket\_type](#socket_type) is implicitly set to `dgram`. (It is invalid to
|
|
|
|
explicitly set `socket_type` to other than `dgram` for a match interface.)
|
|
|
|
|
|
|
|
### `exclude`
|
|
|
|
|
|
|
|
If a rule sets its a `exclude` option to *true*, then the interface will never
|
|
|
|
be activated. This can be useful for writing negative [match](#match) rules to
|
|
|
|
exclude specific interface names before a final match-all rule.
|
|
|
|
|
|
|
|
### `file`
|
|
|
|
|
|
|
|
If a rule specifies a `file` path, then an interface is created *only if the
|
|
|
|
given file exists*. The rule's [exclude](#exclude) option is ignored. The
|
|
|
|
interface's [socket\_type](#socket_type) determines how the file is written and
|
|
|
|
read.
|
|
|
|
|
|
|
|
### `socket_type`
|
2013-04-15 07:00:45 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
An interface's `socket_type` determines how the its socket file descriptor is
|
|
|
|
written and read: descriptor is written and read:
|
2013-04-16 03:14:47 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
* `file` (the default) creates a [dummy interface](#dummy-interface) for
|
|
|
|
closed communication with other **servald** daemons on the same host. If
|
|
|
|
the dummy file does not exist, a warning is logged and the interface is not
|
|
|
|
activated.
|
2013-04-16 03:14:47 +00:00
|
|
|
|
2013-04-15 07:00:45 +00:00
|
|
|
* `stream` reads and writes the file as though it were a [character special
|
|
|
|
device][]. If the file does not exist, an error is logged and the
|
|
|
|
interface is not activated.
|
2013-04-16 03:14:47 +00:00
|
|
|
|
2013-04-15 07:00:45 +00:00
|
|
|
* `dgram` is not valid for a file interface.
|
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
### `type`
|
|
|
|
|
|
|
|
The `type` option affects the default settings of the
|
|
|
|
[packet\_interval](#packet_interval) and [mdp\_tick\_ms](#mdp_tick_ms) options,
|
|
|
|
for convenience. In future it may also change the way the interface behaves,
|
|
|
|
for example, an `ethernet` interface may automatically assume that broadcast
|
|
|
|
packets will be filtered out, so will start using MDP unicast protocols
|
|
|
|
immediately rather than waiting to detect that broadcast packets are not
|
|
|
|
acknowledged.
|
|
|
|
|
|
|
|
### `packet_interval`
|
2013-04-15 07:00:45 +00:00
|
|
|
|
|
|
|
The `packet_interval` option controls the maximum rate at which packets are
|
2013-04-16 03:14:47 +00:00
|
|
|
tramsmitted on the interface. It sets the *average* interval, in microseconds,
|
|
|
|
between individual packets. If the interval is less than the time it takes to
|
|
|
|
transmit a packet, then packets will be sent at maximum speed with no
|
|
|
|
intervening delay. Otherwise, delays are inserted between packets as needed to
|
|
|
|
keep to the average.
|
2013-04-15 07:00:45 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
### `mdp_tick_ms`
|
|
|
|
|
2013-04-16 03:14:47 +00:00
|
|
|
The `mdp_tick_ms` option controls the time interval, in milliseconds, between
|
2013-04-15 07:00:45 +00:00
|
|
|
MDB broadcast announcements on the interface. If set to zero, it disables MDP
|
|
|
|
announcements altogether on the interface (called “tickless” mode). If not
|
|
|
|
set, then the value of the `mdp.iftype.IFTYPE.tick_ms` option is used. If that
|
|
|
|
is not set, then **servald** uses a built-in interval that depends on the
|
2016-02-29 05:49:59 +00:00
|
|
|
[type](#type).
|
2013-04-15 07:00:45 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
### `encapsulation`
|
|
|
|
|
|
|
|
The `encapsulation` option controls how [MDP message][]s are written to the
|
2013-04-15 07:00:45 +00:00
|
|
|
interface's socket:
|
2016-02-29 05:49:59 +00:00
|
|
|
|
|
|
|
* `overlay` (the default) aggregates as many messages as possible into
|
|
|
|
[overlay packet][]s that fit into each [UDP][] packet, in order to take
|
|
|
|
full advantage of the bandwidth on conventional [Wi-Fi][] interfaces which
|
|
|
|
have a fixed packet size (the [IEEE 802.11][] [MTU][]) over the air;
|
|
|
|
|
|
|
|
* `single` sends each [MDP message][] on its own to the socket using [SLIP][]
|
2013-04-15 09:50:35 +00:00
|
|
|
encoding, and is suited to data links with a variable packet size on the
|
|
|
|
air (eg, a serial connection to a [packet radio][] modem).
|
2013-04-15 07:00:45 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
### `default_route`
|
|
|
|
|
|
|
|
The `default_route` option, if true, causes all [MDP message][]s with an
|
|
|
|
unresolved [recipient][] address ([SID][]) to be sent to this interface instead
|
|
|
|
of just dropped. This will allow the node to use [Serval Infrastructure][] to
|
|
|
|
route its packets. Many interfaces may have the `default_route` set to true,
|
|
|
|
but only the first one will be used as the default route.
|
|
|
|
|
|
|
|
### `prefer_unicast`
|
2013-04-15 07:00:45 +00:00
|
|
|
|
|
|
|
The `prefer_unicast` option, if true, causes the interface to send to unicast
|
|
|
|
IP addresses instead of the broadcast IP address if both have been observed to
|
|
|
|
reach the destination.
|
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
### `send_broadcasts`
|
|
|
|
|
|
|
|
Normally, any [MDP message][] with an unresolvable [recipient][] gets broadcast
|
|
|
|
on all active interfaces. The `send_broadcasts` option, if *false*, prevents
|
|
|
|
the interface from sending any broadcast packets whenever a recipient address
|
|
|
|
(SID) cannot be resolved to an interface.
|
2012-12-13 07:05:46 +00:00
|
|
|
|
|
|
|
Network interface “legacy” syntax
|
|
|
|
---------------------------------
|
|
|
|
|
|
|
|
Instead of using the multi-option schema described above, the `interfaces`
|
|
|
|
configuration option can be set using a less capable “legacy” format, for
|
|
|
|
compatibility with older config files. The “legacy” interfaces syntax is a
|
|
|
|
single text string consisting of a comma-separated list of rule stanzas, each
|
|
|
|
stanza having one of the following forms:
|
2012-10-30 04:35:24 +00:00
|
|
|
|
2012-12-13 07:05:46 +00:00
|
|
|
+
|
|
|
|
-
|
|
|
|
+PREFIX=IFTYPE
|
|
|
|
+PREFIX=IFTYPE:PORT
|
2013-04-15 07:00:45 +00:00
|
|
|
+PREFIX=IFTYPE:PORT:IGNORED
|
2012-12-13 07:05:46 +00:00
|
|
|
-PREFIX
|
|
|
|
+>PATH
|
|
|
|
|
|
|
|
The rule `+` matches all interfaces.
|
|
|
|
|
|
|
|
The rule `-` excludes all interfaces.
|
|
|
|
|
|
|
|
Rules beginning with `+PREFIX` match any interface whose name starts with
|
|
|
|
`PREFIX`; so for example a rule starting with `+foo` is equivalent to a `match`
|
|
|
|
option with a single PATTERN of `foo*`
|
2012-10-30 04:35:24 +00:00
|
|
|
|
2012-12-13 07:05:46 +00:00
|
|
|
The rule `-PREFIX` excludes interfaces whose name starts with `PREFIX`.
|
2012-10-30 04:35:24 +00:00
|
|
|
|
2012-12-13 07:05:46 +00:00
|
|
|
The rule `+>PATH` specifies a dummy interface (see below) with no address or
|
|
|
|
netmask or broadcast filter.
|
2012-10-30 04:35:24 +00:00
|
|
|
|
2013-04-15 07:00:45 +00:00
|
|
|
Interface rules are numbered in the order they appear, and are applied in that
|
|
|
|
order. For example, an `interfaces` option of `+,-eth0` will not reject the
|
|
|
|
*eth0* interface because the leading `+` will match it first, but `-eth0,+`
|
2012-12-13 07:05:46 +00:00
|
|
|
will reject *eth0* and accept all others.
|
|
|
|
|
|
|
|
The “legacy” format is only provided for backward compatibility and will
|
|
|
|
eventually be deprecated and removed. The “legacy” interfaces configuration is
|
|
|
|
incompatible with the modern form; an instance that uses one cannot use the
|
|
|
|
other.
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2016-02-29 05:49:59 +00:00
|
|
|
Dummy interface
|
|
|
|
---------------
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2012-10-30 04:35:24 +00:00
|
|
|
Sometimes it is helpful to run an isolated group of connected **servald**
|
|
|
|
instances on a single machine for testing purposes. To make this possible,
|
|
|
|
**servald** supports a *dummy* network interface.
|
2012-10-30 02:14:43 +00:00
|
|
|
|
|
|
|
A dummy interface is simply a regular file to which all instances append their
|
|
|
|
network packets. The file grows without limit. Each instance advances its own
|
2013-04-15 07:00:45 +00:00
|
|
|
read pointer through the file, packet by packet, skipping packets which are not
|
|
|
|
addressed to it. A single dummy file simulates a lossless mesh network with
|
|
|
|
total connectivity, ie, all nodes that read and write the file are neighbours.
|
2012-10-30 02:14:43 +00:00
|
|
|
|
|
|
|
To use a dummy interface, first create an empty file, eg, `/tmp/dummy`, and for
|
|
|
|
each servald instance, include the dummy file in its *interfaces* list, eg:
|
|
|
|
|
2013-04-15 07:00:45 +00:00
|
|
|
$ servald config set interfaces.0.file '/tmp/dummy'
|
2012-12-13 07:05:46 +00:00
|
|
|
|
|
|
|
NOTE: Because dummynets are files, not sockets, the [poll(2)][] system call
|
|
|
|
does not work on them. As a result the **servald** daemon main loop has
|
|
|
|
slightly different behaviour and timing characteristics when a dummynet is in
|
|
|
|
use.
|
|
|
|
|
2013-04-15 09:29:49 +00:00
|
|
|
If a dummy interface's `file` PATH is not absolute (ie, does not start with
|
|
|
|
`/`) then it is interpreted relative to the instance directory.
|
2012-12-13 07:05:46 +00:00
|
|
|
|
|
|
|
The following config options adorn a dummy interface with properties that real
|
|
|
|
interfaces normally obtain directly from the operating system:
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2012-12-13 07:05:46 +00:00
|
|
|
interfaces.UINT.dummy_address=IN_ADDR
|
|
|
|
interfaces.UINT.dummy_netmask=IN_ADDR
|
2013-04-15 07:00:45 +00:00
|
|
|
interfaces.UINT.drop_unicasts=BOOLEAN
|
|
|
|
interfaces.UINT.drop_broadcasts=BOOLEAN
|
|
|
|
|
|
|
|
The `dummy_address` option sets the interface's unicast (receive) IP address.
|
|
|
|
|
|
|
|
The `dummy_netmask` option sets the interface's unicast (receive) IP network
|
|
|
|
mask, which together with `dummy_address` determines the interface's IP
|
|
|
|
broadcast address.
|
|
|
|
|
2016-10-13 22:53:04 +00:00
|
|
|
The `drop_unicasts` option, if true, will drop overlay frames addressed to the
|
2013-04-15 07:00:45 +00:00
|
|
|
interface's unicast IP address, so that only broadcast packets will be read.
|
|
|
|
|
2016-10-13 22:53:04 +00:00
|
|
|
The `drop_broadcasts` option, if true, will drop overlay frames addressed to
|
2013-04-15 07:00:45 +00:00
|
|
|
the interface's broadcast IP address, so that only unicast packets will be
|
|
|
|
read. This can simulate the effects of the Fi-Fi drivers on some Android
|
|
|
|
devices that filter out broadcast packets (to prevent the device from waking up
|
|
|
|
unless there is traffic explicitly sent to it).
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2014-05-19 07:58:42 +00:00
|
|
|
-----
|
|
|
|
**Copyright 2013 Serval Project Inc.**
|
2016-02-29 05:49:59 +00:00
|
|
|
**Copyright 2016 Flinders University**
|
2014-05-19 07:58:42 +00:00
|
|
|
![CC-BY-4.0](./cc-by-4.0.png)
|
|
|
|
Available under the [Creative Commons Attribution 4.0 International licence][CC BY 4.0].
|
|
|
|
|
2012-10-30 02:14:43 +00:00
|
|
|
|
2013-04-15 09:50:35 +00:00
|
|
|
[Serval Project]: http://www.servalproject.org/
|
2014-05-21 07:59:22 +00:00
|
|
|
[CC BY 4.0]: ../LICENSE-DOCUMENTATION.md
|
2016-02-29 05:49:59 +00:00
|
|
|
[Serval DNA]: ../README.md
|
|
|
|
[SID]: ./REST-API-Keyring.md#serval-id
|
2013-04-15 07:00:45 +00:00
|
|
|
[Serval Infrastructure]: ./Serval-Infrastructure.md
|
2016-02-29 05:49:59 +00:00
|
|
|
[Rhizome]: ./REST-API-Rhizome.md
|
|
|
|
[recipient]: ./Mesh-Datagram-Protocol.md#recipient
|
|
|
|
[MDP message]: ./Mesh-Datagram-Protocol.md#mdp-message
|
|
|
|
[overlay packet]: ./Mesh-Datagram-Protocol.md#overlay-packet
|
2013-04-16 03:14:47 +00:00
|
|
|
[US-ASCII]: http://en.wikipedia.org/wiki/ASCII
|
2012-10-30 02:14:43 +00:00
|
|
|
[Bourne shell]: http://en.wikipedia.org/wiki/Bourne_shell
|
2016-02-29 05:49:59 +00:00
|
|
|
[FHS]: https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
|
2013-04-16 03:14:47 +00:00
|
|
|
[isspace(3)]: http://linux.die.net/man/3/isspace
|
2012-12-13 07:05:46 +00:00
|
|
|
[shell wildcard]: http://www.kernel.org/doc/man-pages/online/pages/man7/glob.7.html
|
2013-04-12 07:48:53 +00:00
|
|
|
[open(2)]: http://www.kernel.org/doc/man-pages/online/pages/man2/open.2.html
|
|
|
|
[write(2)]: http://www.kernel.org/doc/man-pages/online/pages/man2/write.2.html
|
|
|
|
[poll(2)]: http://www.kernel.org/doc/man-pages/online/pages/man2/poll.2.html
|
2012-12-13 07:05:46 +00:00
|
|
|
[fnmatch(3)]: http://www.kernel.org/doc/man-pages/online/pages/man3/fnmatch.3.html
|
|
|
|
[inet_aton(3)]: http://www.manpagez.com/man/3/inet_aton
|
2013-04-15 07:00:45 +00:00
|
|
|
[Wi-Fi]: http://en.wikipedia.org/wiki/Wi-fi
|
|
|
|
[IEEE 802.11]: http://en.wikipedia.org/wiki/IEEE_802.11
|
|
|
|
[UDP]: http://en.wikipedia.org/wiki/User_Datagram_Protocol
|
|
|
|
[MTU]: http://en.wikipedia.org/wiki/Maximum_transmission_unit
|
|
|
|
[SLIP]: http://en.wikipedia.org/wiki/Serial_Line_Internet_Protocol
|
|
|
|
[packet radio]: http://en.wikipedia.org/wiki/Packet_radio
|
|
|
|
[character special device]: http://en.wikipedia.org/wiki/Device_file#Character_devices
|
2016-10-13 22:53:04 +00:00
|
|
|
[FHS]: https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
|
2016-02-29 05:49:59 +00:00
|
|
|
[automated tests]: ./Testing.md
|