serval-dna/conf_schema.h
2012-12-10 14:06:25 +10:30

331 lines
15 KiB
C

/*
Serval DNA configuration
Copyright (C) 2012 Serval Project Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* This file contains definitions for the schema of the Serval DNA configuration file. See comments
* in "config.h" for a description of the internal configuration API.
*
* A configuration schema is set of nested structures and arrays. By convention, the top level, or
* root of the schema is called "main", but every structure and array has its own complete API which
* can be used by itself. So if there were two independent configuration files, both could be
* defined in this file, each with a conventional name for its own root element.
*
* A configuration file consists of lines of the form:
*
* FULLKEY "=" VALUE "\n"
*
* where FULLKEY has the form KEY [ "." KEY [ "." KEY [ ... ] ] ] and VALUE is any string not
* containing newline. Lines ending with "\r\n" have the "\r" stripped from the end of VALUE.
* Otherwise VALUE is preserved exactly, with all leading and trailing spaces intact.
*
* To describe a configuration file that looks like this:
*
* some.thing.element1=integer
* some.thing.element2=string
* some.list.foo.element1=integer
* some.list.foo.element2=string
* some.list.bar.element1=integer
* some.list.bar.element2=string
* another_thing=http://my.host.com:1234/path/to/nowhere
*
* the following schema would do:
*
* STRUCT(happy)
* ATOM(int32_t, element1, 0, cf_opt_int32_nonnegative,, "An integer >= 0")
* STRING(80, element2, "boo!", cf_opt_str_nonempty, MANDATORY, "A non-empty string")
* END_STRUCT
*
* ARRAY(joy,)
* KEY_STRING(3, happy, cf_opt_str)
* VALUE_SUB_STRUCT(happy)
* END_ARRAY(16)
*
* STRUCT(love)
* SUB_STRUCT(happy, thing,)
* SUB_STRUCT(joy, list,)
* END_STRUCT
*
* STRUCT(main)
* SUB_STRUCT(love, some,)
* STRING(128, another_thing, "", cf_opt_uri,, "URL; protocol://hostname[:port][/path]")
* END_STRUCT
*
* which would produce an API based on the following definitions (see "config.h" for more
* information):
*
* struct config_happy {
* int32_t element1;
* char element2[81];
* };
* struct config_joy {
* unsigned ac;
* struct config_joy__element {
* char key[4];
* struct config_happy value;
* } av[16];
* };
* struct config_love {
* struct config_happy thing;
* struct config_joy list;
* };
* struct config_main {
* struct config_love some;
* char another_thing[129];
* };
*
* A schema definition is composed from the following STRUCT and ARRAY definitions:
*
* STRUCT(name[, validatorfunc])
* element-declaration
* element-declaration
* ...
* END_STRUCT
*
* where each element-declaration is one of:
*
* ATOM(type, element, default, parsefunc, flags, comment)
* NODE(type, element, default, parsefunc, flags, comment)
* STRING(strlen, element, default, parsefunc, flags, comment)
* SUB_STRUCT(structname, element, flags)
* NODE_STRUCT(structname, element, parsefunc, flags)
*
* ARRAY(name, flags[, validatorfunc])
* key-declaration
* value-declaration
* END_ARRAY(size)
*
* where key-declaration is one of:
*
* KEY_ATOM(type, parsefunc[, comparefunc])
* KEY_STRING(strlen, parsefunc[, comparefunc])
*
* and value-declaration is one of:
*
* VALUE_ATOM(type, parsefunc)
* VALUE_STRING(strlen, parsefunc)
* VALUE_NODE(type, parsefunc)
* VALUE_SUB_STRUCT(structname)
* VALUE_NODE_STRUCT(structname, parsefunc)
*
* The meanings of the parameters are:
*
* 'name'
* A label used to qualify this struct/array's API from the API components of other structs and
* arrays. This label does not appear anywhere in the config file itself; it is purely for
* internal code-related purposes.
* 'strlen'
* For STRING, LABEL_STRING and VALUE_STRING, gives the maximum length of the string. The
* string is declared as an array of char[strlen+1] to leave room for a terminating nul.
* 'size'
* For all ARRAYs, gives the maximum size of the array.
* 'type'
* Used for ATOM, NODE, LABEL_ATOM, VALUE_ATOM and VALUE_NODE declarations. Gives the C type
* of the element. For STRING, KEY_STRING and VALUE_STRING this is implicitly a char[].
* 'structname'
* Only used for SUB_STRUCT, NODE_STRUCT, VALUE_SUB_STRUCT and VALUE_NODE_STRUCT declarations.
* Identifies a sub- structure by 'name' to nest in the enclosing struct or array.
* 'element'
* The name of the struct element and the key in the configuration file. This name does appear
* in the config file and also in the API, so that an option mamed "some.thing.element1" in the
* file is referred to as some.thing.element1 in the C code. Arrays are more complicated:
* "some.list.foo.element1" in the config file is referred to as some.list.av[n].value.element1
* in the C code, and some.list.ac gives the size of the some.list.av array.
* 'default'
* Only used for ATOM and NODE struct elements. Gives the default value for the element if
* absent from the config file.
* 'parsefunc'
* The function used to parse a VALUE from the config file for a STRUCT element, or a KEY or
* VALUE for an array element. Parse functions for ATOM, STRING, KEY_ATOM, KEY_STRING,
* VALUE_ATOM and VALUE_STRING all take a string argument (const char *) which is a
* nul-terminated text. The parse functions for NODE, NODE_STRUCT, VALUE_NODE and
* VALUE_NODE_STRUCT take a pointer to a COM node (const struct cf_om_node *), and are
* responsible for parsing the node's text and all of its descendents (children).
* 'comparefunc'
* A function used to sort an array after all elements have been parsed, and before being
* validated (see below).
* 'validatorfunc'
* A function that is called after the struct/array is fully parsed and populated. This
* function can perform validation checks on the whole struct/array that cannot be performed by
* the parse functions of each element in isolation, and can even alter the contents of the
* struct/array, eg, sort an array or fill in default values in structs that depend on other
* elements. Takes as its second argument the CFxxx code produced by the parser, and returns
* an updated CFxxx result code (which could be the same) as documented in "config.h".
* 'flags'
* A space-separated list of flags. At present only the MANDATORY flag is supported, which
* will cause parsing to fail if the given STRUCT element is not set in the config file. In
* the case of struct elements that are arrays, the config file must set at least one element
* of the array, or parsing fails.
* 'comment'
* A human-readable string describing the value of the configuration option. Must be
* informative enough to help users diagnose parse errors. Eg, "An integer" is not enough;
* better would be "Integer >= 0, number of seconds since Unix epoch".
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
STRUCT(log)
STRING(256, file, "", cf_opt_absolute_path,, "Absolute path of log file")
ATOM(int, show_pid, 1, cf_opt_boolean,, "If true, all log lines contain PID of logging process")
ATOM(int, show_time, 1, cf_opt_boolean,, "If true, all log lines contain time stamp")
END_STRUCT
STRUCT(server)
STRING(256, chdir, "/", cf_opt_absolute_path,, "Absolute path of chdir(2) for server process")
STRING(256, dummy_interface_dir, "", cf_opt_str_nonempty,, "Path of directory containing dummy interface files, either absolute or relative to instance directory")
ATOM(int, respawn_on_crash, 0, cf_opt_boolean,, "If true, server will exec(2) itself on fatal signals, eg SEGV")
END_STRUCT
STRUCT(monitor)
STRING(256, socket, DEFAULT_MONITOR_SOCKET_NAME, cf_opt_str_nonempty,, "Name of socket for monitor interface")
ATOM(int, uid, -1, cf_opt_int,, "Allowed UID for monitor socket client")
END_STRUCT
STRUCT(mdp_iftype)
ATOM(uint32_t, tick_ms, 0, cf_opt_uint32_nonzero,, "Tick interval for this interface type")
END_STRUCT
ARRAY(mdp_iftypelist, NO_DUPLICATES)
KEY_ATOM(short, cf_opt_interface_type, cmp_short)
VALUE_SUB_STRUCT(mdp_iftype)
END_ARRAY(5)
STRUCT(mdp)
STRING(256, socket, DEFAULT_MDP_SOCKET_NAME, cf_opt_str_nonempty,, "Name of socket for MDP client interface")
SUB_STRUCT(mdp_iftypelist, iftype,)
END_STRUCT
STRUCT(olsr)
ATOM(int, enable, 1, cf_opt_boolean,, "If true, OLSR is used for mesh routing")
ATOM(uint16_t, remote_port,4130, cf_opt_uint16_nonzero,, "Remote port number")
ATOM(uint16_t, local_port, 4131, cf_opt_uint16_nonzero,, "Local port number")
END_STRUCT
ARRAY(argv, SORTED NO_DUPLICATES, vld_argv)
KEY_ATOM(unsigned short, cf_opt_ushort_nonzero, cmp_ushort)
VALUE_STRING(128, cf_opt_str)
END_ARRAY(16)
STRUCT(executable)
STRING(256, executable, "", cf_opt_absolute_path, MANDATORY, "Absolute path of dna helper executable")
SUB_STRUCT(argv, argv,)
END_STRUCT
STRUCT(dna)
SUB_STRUCT(executable, helper,)
END_STRUCT
STRUCT(rhizome_peer)
STRING(25, protocol, "http", cf_opt_protocol,, "Protocol name")
STRING(256, host, "", cf_opt_str_nonempty, MANDATORY, "Host name or IP address")
ATOM(uint16_t, port, RHIZOME_HTTP_PORT, cf_opt_uint16_nonzero,, "Port number")
END_STRUCT
ARRAY(peerlist,)
KEY_STRING(15, cf_opt_str)
VALUE_NODE_STRUCT(rhizome_peer, cf_opt_rhizome_peer)
END_ARRAY(10)
STRUCT(rhizome_direct)
SUB_STRUCT(peerlist, peer,)
END_STRUCT
STRUCT(rhizome_api_addfile)
STRING(64, uri_path, "", cf_opt_absolute_path,, "URI path for HTTP add-file request")
ATOM(struct in_addr, allow_host, (struct in_addr){htonl(INADDR_LOOPBACK)}, cf_opt_in_addr,, "IP address of host allowed to make HTTP add-file request")
STRING(256, manifest_template_file, "", cf_opt_str_nonempty,, "Path of manifest template file, either absolute or relative to instance directory")
ATOM(sid_t, default_author, SID_ANY, cf_opt_sid,, "Author of add-file bundle if sender not given")
ATOM(rhizome_bk_t, bundle_secret_key, RHIZOME_BK_NONE, cf_opt_rhizome_bk,, "Secret key of add-file bundle to try if sender not given")
END_STRUCT
STRUCT(rhizome_api)
SUB_STRUCT(rhizome_api_addfile, addfile,)
END_STRUCT
STRUCT(rhizome_http)
ATOM(int, enable, 1, cf_opt_boolean,, "If true, Rhizome HTTP server is started")
END_STRUCT
STRUCT(rhizome_mdp)
ATOM(int, enable, 1, cf_opt_boolean,, "If true, Rhizome MDP server is started")
END_STRUCT
STRUCT(rhizome_advertise)
ATOM(int, enable, 1, cf_opt_boolean,, "If true, Rhizome advertisements are sent")
END_STRUCT
STRUCT(rhizome)
ATOM(int, enable, 1, cf_opt_boolean,, "If true, server opens Rhizome database when starting")
STRING(256, datastore_path, "", cf_opt_absolute_path,, "Path of rhizome storage directory, absolute or relative to instance directory")
ATOM(uint64_t, database_size, 1000000, cf_opt_uint64_scaled,, "Size of database in bytes")
ATOM(uint32_t, fetch_delay_ms, 50, cf_opt_uint32_nonzero,, "Delay from receiving first bundle advert to initiating fetch")
SUB_STRUCT(rhizome_direct, direct,)
SUB_STRUCT(rhizome_api, api,)
SUB_STRUCT(rhizome_http, http,)
SUB_STRUCT(rhizome_mdp, mdp,)
SUB_STRUCT(rhizome_advertise, advertise,)
END_STRUCT
STRUCT(directory)
ATOM(sid_t, service, SID_ANY, cf_opt_sid,, "Subscriber ID of Serval Directory Service")
END_STRUCT
STRUCT(host)
STRING(INTERFACE_NAME_STRLEN, interface, "", cf_opt_str_nonempty,, "Interface name")
ATOM(struct in_addr, address, (struct in_addr){htonl(INADDR_NONE)}, cf_opt_in_addr, MANDATORY, "Host IP address")
ATOM(uint16_t, port, PORT_DNA, cf_opt_uint16_nonzero,, "Port number")
END_STRUCT
ARRAY(host_list, NO_DUPLICATES)
KEY_ATOM(sid_t, cf_opt_sid, cmp_sid)
VALUE_SUB_STRUCT(host)
END_ARRAY(32)
STRUCT(network_interface, vld_network_interface)
ATOM(int, exclude, 0, cf_opt_boolean,, "If true, do not use matching interfaces")
ATOM(struct pattern_list, match, PATTERN_LIST_EMPTY, cf_opt_pattern_list,, "Names that match network interface")
STRING(256, dummy, "", cf_opt_str_nonempty,, "Path of dummy file, absolute or relative to server.dummy_interface_dir")
ATOM(struct in_addr, dummy_address, (struct in_addr){htonl(0x7F000001)}, cf_opt_in_addr,, "Dummy interface address")
ATOM(struct in_addr, dummy_netmask, (struct in_addr){htonl(0xFFFFFF00)}, cf_opt_in_addr,, "Dummy interface netmask")
ATOM(int, dummy_filter_broadcasts, 0, cf_opt_boolean,, "If true, drop all incoming broadcast packets")
ATOM(short, type, OVERLAY_INTERFACE_WIFI, cf_opt_interface_type,, "Type of network interface")
ATOM(uint16_t, port, RHIZOME_HTTP_PORT, cf_opt_uint16_nonzero,, "Port number for network interface")
ATOM(uint64_t, speed, 1000000, cf_opt_uint64_scaled,, "Speed in bits per second")
ATOM(int, mdp_tick_ms, -1, cf_opt_int32_nonneg,, "Override MDP tick interval for this interface")
ATOM(int, default_route, 0, cf_opt_boolean,, "If true, use this interface as a default route")
END_STRUCT
ARRAY(interface_list, SORTED NO_DUPLICATES)
KEY_ATOM(unsigned, cf_opt_uint)
VALUE_NODE_STRUCT(network_interface, cf_opt_network_interface)
END_ARRAY(10)
// The top level.
STRUCT(main)
NODE_STRUCT(interface_list, interfaces, cf_opt_interface_list,)
SUB_STRUCT(log, log,)
SUB_STRUCT(server, server,)
SUB_STRUCT(monitor, monitor,)
SUB_STRUCT(mdp, mdp,)
SUB_STRUCT(dna, dna,)
NODE(debugflags_t, debug, 0, cf_opt_debugflags, USES_CHILDREN, "Debug flags")
SUB_STRUCT(rhizome, rhizome,)
SUB_STRUCT(directory, directory,)
SUB_STRUCT(olsr, olsr,)
SUB_STRUCT(host_list, hosts,)
END_STRUCT