cml — Configuration Meta-Language


cml [-hv]

cml [-d dbglev] [-f cfgfile] [-k] [-r revision] [-R]

cml [-d dbglev] -f cfgfile [-k] -g

cml [-d dbglev] [-f cfgfile] [-lLicsu]


The abbreviation CML denotes both the Kernun Firewall configuration language and the command-line tool for editing and verifying the configuration and for generating proper files used by the system. The tool can be used in three modes:

  • When option -g is not given, the CML will start an interactive mode and prompts user for commands (see the section called “CML Commands” below).

  • When option -g is given, the CML run is intended to generate target configuration tree only (see option explanation below).

  • When one of options -l, -L, -i, -c, -s, -u is given, the CML performs just the requested RCS file locking operation (see option explanation below).


The CML options are as follows:


Print usage information and exit.


Display version information and exit.

-d dbglev

Set debugging level to a specific number. Permitted values are 3 through to 9, 3 being the least and 9 the most verbose. See logging(7) for details. This setting is needed for debugging until the CML prompt is ready. Then, more flexible /dbg command (see the section called “CML Commands” below) can be used.

-f cfgfile

As the first operation, the CML will load named configuration file. If not used, the CML will start with an empty configuration. The cfgfile can be then later loaded by the /load cfgfile command (see the section called “CML Commands” below).


The CML does not enter the interactive mode, just loads the configuration file (option -f must be used, too) and generates configuration files tree (see /generate command in the section called “CML Commands” below).

-r revision

If the CML is invoked with the -f option, the specified revision saved in the RCS file cfgfile,v is used instead of the current configuration file. For more details see the /load command description in the section called “CML Commands” below.


The CML runs in read-only mode (this is default, when started under AUDITOR user).


The CML does not unlock the configuration file when exiting. The file is kept locked for current user.


The CML tries to lock particular RCS file. If the file is not free, or the plaintext version differs from the RCS copy, the program will fail.


The CML tries to break the lock of particular RCS file.


Use this operation with care!


The CML tries to create particular RCS file. If the file is exists, the program will fail.


The CML tries to check whether the current user owns the lock of particular RCS file. If not, the program will fail.


The CML tries to save (check-in) current plaintext into particular RCS file. If the file is not locked for current user, the program will fail.


The CML tries to unlock particular RCS file.

CML Operation

After start, the CML checks whether running from a terminal. If so, it prepares the editline environment (see editline(3)) and Command Completion and Context Help support (see the section called “C3H Support” below). Otherwise, the CML will read commands from standard input.

If the -f option was used, the CML loads configuration from given file like if it would be ordered by the /load command (see the section called “CML Commands” below). If not, no configuration is read, the user must either use the /load command or create a new configuration from scratch.

Finally, the CML looks whether the -g option was used and if so, it generates output files using /generate command (see the section called “CML Commands” below) and exits. Otherwise the CML starts normal command processing.

The CML tool uses standard Kernun logging library for displaying messages (see logging(7)), the messages are written both to the standard error output (i.e. sent to the terminal, typically) and to the system log (as configured in /etc/syslog.conf file). This behavior can be changed by setting the environment variable KERNUN_LOG_FILE to a file name willing to be the log target. As usual, every message (produced by the CML, not by other system programs called by the CML) has a log-id prefix (e.g. CMLR-710-W) that can be found in Kernun section 6 manual pages (CMLR-710(6) in above example).

If the CML runs in read-only mode (due to current user type, or the -R option), it allows only commands they do not alter the configuration content. Other commands are disabled.

CML Commands

The maximal length of the command line depends on current system settings of the editline(3) library. However, for the purpose of configuration editing is sufficient. The the section called “C3H Support” may work slightly fuzzy on too long lines.

There are three essential types of commands in the CML:

Low-level configuration directives

Most of Kernun configuration is based on directives known for both the CML and the idividual proxies. They have the same syntax and semantics as described in section 5 manual pages, root of them is kernun.cml(5). These directives are written in the Kernun configuration file and the CML copy them into individual proxies configuration files when preparing the output. Example:

  system BILOVICE {
    hostname bns;
High-level configuration directives

There are a group of directives having the sense only in the CML. They are written in the Kernun configuration file, but they are only used by the CML when generating the output files which they are not a part of. Example:

  include "samples/root-servers.cml";
  set name = "gateway";
  for x in { INT, OUT } {
The CML control commands

These commands are used for configuration manipulation (editing, saving etc.) and therefore they are not part of saved configuration files. Hence, they also have a different syntactical form: they are prefixed by a slash ('/') character or optionally dot-slash ('./') pair. Examples:

  /load kernun.cml
  ./paste NEWNAME

All commands, configuration directives and names are case-insensitive.

Low-level configuration directives

Although general syntax of configuration files is free in the sense of whitespaces and newlines using, the CML uses strict form of line breaks, indentation etc. The reasons for it are both version difference checking and easier Command Completion and Context Help support (see the section called “C3H Support” below).

For the detail description of low-level syntax, see configuration(7). For clarity, we mention here only a few basic facts. The configuration consists of configuration directives of two types:


is a series of elements (or attributes) of simple values (integers, names, strings, IP addresses and also comma separated lists of previous types enclosed in curly braces ('{ ... }') terminated by a semicolon (';') character.


is a set of configuration directives (items and subsections) enclosed in a pair of curly braces ('{ ... }').

Both items and sections are either repeatable or non-repeatable. Repeatable sections must have a name specified between the keyword and the opening brace. The name must be at most 63 characters long, otherwise it is not recognized by parser and it is treated as string. For brevity we use the term name in the natural sense, in the case of repeatable section we distinguish between type name and name. Example:

  routes {          # non-repeatable section of type routes
    static DMZ {    # repeatable section of type static,
                    # section name is DMZ
      flags { cloning, iface };  # item with one element (list)
    }               # end of section DMZ
  }                 # end of section routes

Comment lines start with the hash ('#') character and can be inserted freely between configuration directives. Lines with a single hash character will be copied to the low-level (proxy) configuration files. If you want to make a comment hidden for the target files, simply double the hash character on the beginning of the comment. Example:

  # This comment will be generated
  ## ...while this not

If you type a configuration directive on the command line, the behavior depends on directive type and current configuration content.

  • If the directive is non-existing (i.e. not specified yet) non-repeatable section/item, then a new one is entered.

  • If the directive is existing (i.e. already specified before) non-repeatable section/item, then the old one is modified.

  • If the directive is repeatable section and its name has been already used, then the old one is modified.

  • If the directive is repeatable section and its name has not been used yet, then a new one is entered.

  • If the directive is repeatable item, then a new one is entered.

Repeatable section names must be unique within current section. On the contrary to the low-level configuration files, in the CML, this is true even for sections of different types. For instance, you cannot use the same name for doc-acl and command-acl in the ftp-proxy configuration.

When entering a configuration directive, the CML tries to check correctness of it by so called on-line verification. In fact, it tries to parse the directive by an ordinary low-level parser, the same one as will parse it later on within low-level configuration files generated for proxies. This can recover some errors in very early stage of configuration creation.

High-level configuration directives

The high-level configuration handles primarily variables and loops.


The most important value added in high-level configuration is the concept of variables. We recognize two kinds of variables:

data variables

can contain one simple value, i.e. one element of item (examples see below)

section variables

can contain several directives (items, subsections, comments, etc.) of some section.

Variable names are at most 32 characters long, they can consist from alphanumeric characters and the hyphen ('-') characters. the first character must be a letter.

When applied, variable name prefixed by a dollar ('$') character is used.

Variable is visible from the place where defined, on the level where defined and on all lower levels. Within visibility range, no other variable can have the same name. Example:

  set X = 1;
  system FIRST {
    set X = 2;     # false - repeated definition
    set Y = $X;    # correct
    set Z = $W;    # false - variable $W unknown
  set W = 3;
  system SECOND {
    set Z = $W;    # correct

In-line files

An interesting feature of the high-level configuration is the list outsourcing. If you have an external source for some list (e.g. list of valid email addresses), you can define a global shared-file section for the file and instead of writing the whole list directly into CML (using the CML syntax), you will use only a special construct < shared-file-name. Example:

  shared-file ADDRESSES {
    path "/var/adm/emails";
    format text;
  system SYS {
    smtp-proxy SMTP {
      delivery-acl ACL-2 {
        recipient ok < ADDRESSES;

The format item defines handling modes for lines from the source file:

text (default)

Whitespaces form the begining and the end of lines are stripped, rest of the line is double-quoted (like regular strings in the CML). Empty lines and lines starting by the # character are ignored.


No special handling, the lines are just double-quoted.


Lines should contain valid low-level syntax values, they are used as-is, just adding separating commas. Empty lines and lines starting by the # character are ignored.


Lines should contain IP addresses with or without mask (in slash-notation), but without brackets. Empty lines and lines starting by the # character are ignored.


Lines should contain regular expressions without delimiters (slashes). Empty lines and lines starting by the # character are ignored.

High-level directives desription

The CML recognizes following high-level directives:

include "filename";

Import variable definitions from another file. This feature was added to facilitate some standard settings, like set of root nameservers or general crontab setting. The aim of it is not to split configuration to several files and so the CML does not support for editing the included files.

Including is allowed only on the highest level of configuration and included files can contain only comments and variable definitions. The filename is either absolute, or relative to the configuration root path. This path is set to /usr/local/kernun/conf, by default, and can be changed by the /cfgpath command (see the section called “The CML Control Commands” below).

In some cases, parts of the include file can be parametrized by variables intended to be set in the main configuration file (not within the file). Such variables must be declared within the include file using the param directive.

set varname = value;

Define data variable. For the value, any type (including LISTs and SETs) can be used. Besides, for string variables, also concatenation is allowed, concatenation operator is a plus ('+') character. Examples:

  set ADMIN = root;
  set DOMAIN =;
  set EMAIL = $ADMIN + @ + $DOMAIN;
  set MY-ADDR = [];
  set DNS-ADDR = $MY-ADDR : 53;
set varname [section.path] { section variable body }

set varname prototype.path { section variable body }

Define section variable (macro). The value of the variable is a set of configuration directives. Such a variable can be primarily applied as a part of regular configuration section. For this reason, the context of the variable must be known, i.e.

  1. point of the configuration tree, where it can be applied

  2. set of subsections and items it can contain.

This context is defined by the path between the variable name and the opening brace and one of the following modes can be used:

configuration context

This mode means that variable context is derived from current point of configuration. If the current section is to be the context, the path should be omitted. If a sub-node of the current node is to be the context, the (type) name of the node should be written. If a distant descendant is to be the context, a path should be constructed by particular names of section along to the path from current point to the node desired, separating them by dots ('.'). Examples:

  set SYSTEM-DATA system { # applicable within any system
  set IN-OUT system.acl {  # applicable within system.acl
    from [];
  system BILOVICE {
    $SYSTEM-DATA;          # variable application
    acl IN-OUT {
      $IN-OUT;             # variable application

This excerpt will be expanded as:

  system BILOVICE {
    acl IN-OUT {
      from [];
prototype context

This mode means that variable context is derived from a prototype. Prototypes are templates used for building of similar configuration directives in different parts of the configuration tree (see more in configuration(7)). The prototypes can be also used as the context and such variables can be used in different evironments. Example:

  system BILOVICE {
    set IN-OUT acl-1 { ... } # prototype acl-1 used
    ftp-proxy FTP-PROXY {
      session-acl OUTGOING {
        $IN-OUT; ... } }     # used in ftp-proxy.session-acl
    tcp-proxy TCP-PROXY {
      session-acl OUTGOING {
        $IN-OUT; ... } }     # used in tcp-proxy.session-acl


Current version of the CML does not support defining of system sections within a macro body.

param varname;

Section variable (macro) parameter, or forward variable declaration for switch and include directives.

Section variables can have parameters that behaves like data variables inside the section variable definition. Values of parameters are defined when variable is applied. Example:

  set CLUSTER system {       # macro definition
    param NAME;              # parameters definition
    param PROXIES;

    hostname $NAME;
    acl IN-OUT {
      services $PROXIES;
  system FW-A {
    $CLUSTER GATE-1 { FTP }; # macro application with 2 parameters

This excerpt will be expanded as:

  system FW-A {
    hostname GATE-1;
    acl IN-OUT {
      services { FTP };

Number of parameters is fixed for all applications of parametrized variable.

for varname in { iteration list } { for loop body }

Repeat set of configuration directives several times. The loop control variable varname is set to each element of the iteration list in turn, and the for loop body is generated each time. The iteration list can consist of simple values, variables and sublists which are considered as subset rather than one element. Example:

  set ALL-ACLS = { IN-OUT, OUT-IN };
  command-acl ALLOW-ALL {
    for X in { $ALL-ACLS } { # list with variable with a sublist
      session-acl $X;        # loop control variable application

This excerpt will be expanded as:

  command-acl ALLOW-ALL {
    session-acl IN-OUT; # iteration #1
    session-acl OUT-IN; # iteration #2

In the for-loop body, besides the loop control variable, two special variables can be used, too.


Value of this variable is an iteration number.


Value of this variable is the whole iteration list.

These variables can help to construct unique names, addresses etc. within multiple times generated for-loop body.


Current version of the CML does not support defining of system, system.acl and proxy sections within a for-loop body. Also, for-loop cannot be used for constructing of list values (i.e. for-loop inside the item).

switch $varname { case value { ... } }

Differentiate parts of configuration depending on the value in a variable (typically a parameter). According to the value of the varname variable, proper case label is selected. Match means that the case label value is equal to the variable one, or the label has value *. Within case branches, normal configuration source code continues.

There is one small exception, if you want to alter the value of another variable. Simple using of the set command within a case branch, will fail due invisibility of the variable behind the switch command. In this case, such a variable must be declared in advance by the param command. Example:

  set CLUSTER {
    param HOST;
    switch $HOST {
      param ADDR;               # variable declaration
      case host-a {
        set ADDR = [];  # assigning value for "host-a"
      case host-b {
        set ADDR = [];  # assigning value for "host-b"
        interface DMZ { ... }   # some more definitions
      case * {                  # branch for other cases
    interface INT {
      ipv4 $ADDR;               # using the value


Current version of the CML does not support defining of system sections within a switch-case body.

Variable and reference paths

Wherever a simple value can be used, a data variable (of proper type) can be used, instead. Moreover, even a part of a (non-parametrized) section variable can be used, too. Proper part must be specified with dotted-path (variable path). Every path component is either a type name of a non-repeatable section/item/element or name of a repeatable section. Example:

  set SYSTEM-DATA system {
  system BILOVICE {
    set ADMIN = root@ + $;
                         # variable SYSTEM-DATA
                                     # non-repeatable item domain
                                            # item element name

Similar concept can be used for references to existing configuration directives. So called reference path starts either with a subnode name (when following path downward), or with (one or more) path item consisting of a single up-arrow ('^') character. The latter way may be more explicitly expressed by a single path item formed from an up-arrow and parent section name. Example:

  shared-file ERR-DOC {
    path "samples/error-documents";
  system BILOVICE {
    http-proxy HTTP-PROXY {
      document-root ^.^.ERR-DOC;   # twice up, then to ERR-DOC
    # or better
      document-root ^root.ERR-DOC; # up to root, then to ERR-DOC

In the example above we see also an application of a section (ERR-DOC) in a place where a simple string value is expected (element of mime-types item). In this case, name of the section is used. So, the item will be expanded as document-root "ERR-DOC";.

As for variable ones, all reference paths must lead towards the beginning of the file.


Some items have special elements called methods that can operate with other item elements and produce some output. All methods of an item are described in particular section 5 manual page describing the item. Example:

  system BILOVICE {
    interface I1 {
      ipv4 [];
    acl IN-OUT {
      from ^system.I1.ipv4.addr; # error: [] is invalid here
      from ^;  # method returning []
    ftp-proxy FTP {
      listen-on {
        transparent ^system.I1.ipv4.addr:21; # [] invalid here
        transparent ^; # method => []

Some predefined methods are available to simple data variable values, too. Namely, the two methods for IP addresses modifications (host and net, see above) are valid for them. Example:

  set ACL-INT system {
    param ADDR;
    acl FROM {
      from $;
    $ACL-INT []; # will produce ... from [];

Special usage of data variables

Data variables can be used also as a token of path. This is very useful, namely in for-loops. Example:

  system BILOVICE {
    interface I1 { ipv4 []; }
    interface I2 { ipv4 []; }
    ftp-proxy FTP {
      listen-on {
        for X in { I1, I2 } {
          transparent ^system.$;

This excerpt will be expanded as:

  system BILOVICE {
    interface I1 { ipv4 []; }
    interface I2 { ipv4 []; }
    ftp-proxy FTP {
      listen-on {
        transparent []:21;
        transparent []:21;

Data variables can be used also as a name of repeatable section (unfortunately not for proxy and ACL level 1 names in current version of CML). This is, again, useful in for-loops. Example:

  routes {
    for X in { net1, net2 } {
      set NAME = ROUTE- + $_run_;
      static $NAME { ... };

This for-loop will produce two sections named ROUTE-1 and ROUTE-2.

Special usage of section variables

Section variables, in fact, represent a container of configuration directives. Sometimes, it can be useful to apply only a part of the variable. In this case, we can use the the variable path (as discussed above, in the section called “Variable and reference paths”) and CML will insert only part of the variable definition corresponding to the path.

There are two modes of insertion:

container mode

If the variable with path is applied in the context equal to the context of the node referenced, the content of it (i.e. all subnodes) are expanded from the definition. Example:

  set FTP-PROXIES system {
    ftp-proxy FTP-IN-OUT {
      listen-on { ... }

  system BILOVICE {
    ftp-proxy SPECIAL-IN-OUT {
      $FTP-PROXIES.FTP-IN-OUT;    # expand content of FTP-IN-OUT ...
      command-acl SPECIAL-ACL-2 { ... }   # ... and complete it

This excerpt will be expanded as:

  system BILOVICE {
    ftp-proxy SPECIAL-IN-OUT {
      listen-on { ... }
      command-acl SPECIAL-ACL-2 { ... }   # ... and complete it
single-node mode

If the variable with path is applied in the context parental to the context of the node referenced, the node as a whole is expanded from the definition. Example:

  set FTP-PROXIES system {
    ftp-proxy FTP-IN-OUT {
      listen-on { ... }

  system BILOVICE {
    $FTP-PROXIES.FTP-IN-OUT;    # expand unmodified FTP-IN-OUT node

This excerpt will be expanded as:

  system BILOVICE {
    ftp-proxy FTP-IN-OUT {
      listen-on { ... }

The CML Control Commands

There are four groups of the CML control commands:


/help, /show, /info, /man


/goto, /edit, /delete, /undelete, /rename, /cut, /copy, /paste, /hide, /unhide


/load, /save, /verify, /generate, /cfgpath, /rcs


/quit, /dbg

Editing commands operate at one moment with a single configuration node. This point of configuration is called cursor and it is indicated by an arrow symbol ("-->") pointing to particular node when displaying content of the currently modified node. The cursor node is e.g. deleted if /delete command is issued. If the cursor has an invalid value (e.g. when modifying an empty section), such a command will fail. The cursor represents also the exact point, where new nodes will be placed. More precisely: new nodes will be placed after the cursor. When editing or adding a node, this node becomes the cursor. When deleting a node, the cursor moves to the node following the removed one. This is the reason, why sequence of /cut + /paste commands swops the two nodes, similarly like the sequence of "xp" or "ddp" commands in the vi editor.

The configuration files are kept not only in the plain form, however, the RCS system (see rcs(1)) is used for keeping track of configuration changes. The /load command checkes whether plain and RCS versions of configuration files differ; if you change the configuration file in an external editor, you will be prompted for authorizing the changes. The /save command stores file to the plain form and then does the check-in operation to save it to the RCS form. When creating a new RCS file or a new RCS file version, user is prompted by rcs program to add some comment. The comment is closed by entering a line with the dot ('.') only.

/cfgpath directory

Set the configuration root path used as reference point for relative paths in

The directory must be absolute and must exist.

/copy [ { + | n | +n | * } ]

Copy nodes to the clipboard. The clipboard content can be inserted back to the configuration by the /paste command.

By default, only the single node under cursor is copied. This usage of the command is allowed for any node type. All other possibilities (with parameters) allow to store more nodes from the same context.

By means of + parameter, the node under cursor can be appended to the current clipboard content (instead of replacing it).

Instead of several subsequent calls of appending copy, a group of nodes (starting by the current one) can be stored into the clipboard by using the number of nodes as a parameter.

Similarly, all subnodes at current level can be placed to the clipboard by using the asterisk as a parameter (if the above constrains are fulfilled).


Move the cursor node to the clipboard. The cursor will then point to the next node. The clipboard content can be then put back to the configuration by the /paste command.

All the parameter variants of the /copy are allowed for this command, too.

/dbg level [ { con | log [filename] } ]

Change amount of displayed messages to the level (see logging(7) for possible values and their meaning).

If you want to change the level only for console or log, you can specify the con or log keyword respectively. In the case of log, you can also change the target file name.


Remove the cursor node. The cursor will then point to the next node. The node can be imediately restored by the /undelete command.

/edit configuration directive ...

Edit the cursor node. The configuration directive must be of the same type as the cursor node. The command will replace the cursor node (in an item case) or will reopen it (in a section case).

This command is used for editing (i.e. changing of the content) of configuration directives. For some kind of directives (repeatable items, comments, for-loops, section variable applications) this is the only possibility of editing. Other directives can be edited simply by typing them anew and the /edit command is only one of the ways how to modify them.

This command cannot be used for replacing of one configuration directive by anoter one (in other words, you cannot change type of the directive, e.g. to comment-out a line, to change an item for other one etc.). This can be done only by deleting the old directive and typing the new one.

Similarly, when using this command, the node name (i.e. repeatable section name, for-loop control variable name) cannot be changed, the /rename command must be used for this purpose, instead.

Using of this command is simplified by help of C3H — you can type /edit, space and press <TAB> — the CML will complete the command line by the content of the cursor node. Similar behavior is implemented for editation of some configuration directives not using the /edit command (e.g. the set directive — see above).


Edit the cursor node by an external editor. The content of all subnodes of the node under cursor are exported to a temporary file, the external editor is called, and the edit result is stored back into the configuration file replacing the original node. The editor can be defined by the environment variable $EDITOR.

In the current version of the CML, this command usage is permitted for structured comments only. The slash characters ('#') on the beginning of comment lines are removed when saving into the file and returned back before reading.


Generate system configuration files. For every system section, a set of files is created under the directory named SYSTEM-name (for more details, see the section called “Generated Output” below).

If the configuration was changed after the last loading/saving operation, or the configuration loaded is not equal to the last version stored in the RCS file, the /save command must be used before issuing the /generate command.

[/goto] number

[/goto] { + | - } [count]

[/goto] { + | - | = } type

[/goto] = name

Move the cursor within the node currently being processed. You can move cursor

  • to the node with given absolute number as shown by the /show command

  • count nodes from current position toward the end ('+') or the beginning ('-') of node currently being processed (default: one)

  • to the next ('+'), the previous ('-') or the first ('=') node with given type (where type can be "FOR", "SET", section or item type name)

  • to the node (repeatable subsection) with given name (you can use C3H to complete the name).

/help [topic]

Show the help (to the given command name).


Hide the cursor node. The cursor node will be marked as hidden and will not be taken into account while working with the configuration, except saving and loading it (e.g. it is possible to have several hidden versions of definition of the same variable). Thus, this feature can be used instead of commenting-out some parts of the configuration.

The node can be enabled by the /hide command later.

/info enum enumeration

Show the enumeration description (meaning, values...).

/info descr [path]

Show configuration directive (item or section) description). The configuration node is given by the CDF path.

Without any parameter, the current node description is shown. Examples:

  /info descr 
  /info descr ftp-proxy.command-acl
  /info descr ^root.system.interface
/info find [pattern]

Find all configuration directives (items and sections) containing pattern as a substring. CDF node paths of found directives (applicable e.g. in the /info descr command) are printed.

/info param

Show internal parameters of the configuration. For the explanation of the parameters, see proper section 6 manual pages.

/load [-r revision] [filename]

Load the configuration from given filename. If the name is omitted, last loaded file name is used. Before loading the file, its content is checked against the one checked-out from the RCS file filename,v (see rcs(1) for the details). The following cases can be recognized:

  • Neither filename nor filename,v exist. User is prompted whether to create (both of) them.

  • File filename exists, but filename,v not. User is prompted whether to create the RCS file.

  • File filename does not exist, while filename,v does. User is prompted whether to recreate the plain file from the current RCS version.

  • Both filename and filename,v exist, but the checked-in version differs from the plain file. User is prompted whether to store the plain file as a new version.

  • Files filename and filename,v are consistent. File is loaded.

In most cases, user can reject recommended actions and can continue to work with the configuration.

The -r option allows user to request loading of a particular revision from RCS file filename,v. This version can be normally browsed in CML and then stored back into both configuration files (plain and RCS). The acceptable forms for revision are major.minor or '0' for the last version stored in RCS.

/man [section] topic

Show given Kernun manual page. The command behaves similarly to the system man(1)) except that it shows only Kernun manual pages. On the other hand, the advantage is in using of C3H support for the section and the topic completion.

/paste [newname]

Paste the clipboard content after the cursor. If the context is not compatible, the command fails. If some unrepeatable nodes were duplicate, the behavior depends on the length of the clipboard: pasting of single member clipboard fails while in the multimember case, all incorrect nodes are pasted as hidden. In the singlemember case, the pasted node can be renamed, if applicable (see the /rename command below).

/quit [!]

Quit the CML tool. This command ends the CML run, using of it is necessary only in the case when configuration has been changed, but is not to be saved (use with the '!' parameter).

/rcs diff [-r rev1 [-r rev2 ] ]

Display differences between particular revisions of the current configuration file.

/rcs lock

Lock the current configuration file.

/rcs log

Display the RCS log for the current configuration file.

/rcs unlock

Unlock the current configuration file.

/rcs remove revision

Remove the particular revision of the current configuration file from the RCS file.

/rename newname

Rename cursor node. If the node has a name (repeatable section, variable definition, for-loop) this command can change the name.

/save [!] [filename]

Save the configuration file to the plain file and store it then into RCS. The filename parameter can be omitted only if some configuration file was loaded (see the /load command above) and the same filename will be used by this command.

Before saving the file, the CML will try to verify the configuration. If this verification fails, configuration will not be saved. This feature can be switched off by using the '!' parameter. However, we do not recommend to use it unless it is absolutely necessary because the configuration may not be loadable more.

If you use C3H in the place of command argument, the CML will offer the name of the last processed file.

/[show] [ { -a | -e | -p | -P } ] [ { path | . } [ filter ] ]

/[show] [ { -a | -e } ] -c

Display the content of the node being currently edited, or the node referred by the variable path or reference path (for the explanation of paths, see above, in the section called “Variable and reference paths”). The last possible choice is showing the clipboard content which is requested by using a special option -c.

When option -a (all) is used, the whole configuration tree is displayed (recursive display) instead of a list of subnodes only.

When option -e (expand) is used, the expanded form of configuration tree is displayed (including variable expansion, for-loop expansion etc.).

When option -p or -P is used, only nodes relevant to current proxy are displayed. The lower-case form show also nodes the relevancy of which is not known.

When the last parameter is used, only nodes with given CDF type are displayed.

The command accepts a bit more complex CML paths than described above in the section called “Variable and reference paths”. So called extended path can contain (besides normal tokens) also indexed tokens so that it can point even to a repeatable item, section variable application etc. This paths are also used by CML when referring to an error during on-line verification. Example:

  CML.BILOVICE.HTTP-PROXY> /show ^system ftp-proxy
    ftp-proxy FTP-PROXY { ... }
    ftp-proxy FTP-VIA-HTTP { ... }
  CML.BILOVICE.HTTP-PROXY> /show ^system.ftp-proxy[2]
    ftp-proxy FTP-VIA-HTTP { ... }

The last deleted node is restored.


Enable the hidden node. The cursor node marked as hidden (by the /hide command sometimes in the past) will be enabled. During this operation, validity of the node occurrence is checked (e.g. unhiding a repeatable section with the name equal to another section will fail).

/verify [ { . | --> } ]

Verify formal correctness of configuration. Without parameters, this command, in fact, does the first phase of the /generate command work (see above) — expands configuration into a temporary file and tries to read it by the low-level parser.


This command re-creates some files and directories for its purpose, so if you want to use the configuration (e.g. by the apply in the kat tool), you must use the /generate as the last command.

With parameters, only a part of configuration (the node currently being edited, od the node pointed to by the cursor, respectively) is verified.

C3H Support

The Command Completion and Context Help support is one of the basic features of the CML. It helps admin to write correct configuration and even guides him to solve some troubles he can get into. The simple basic rule is: If you don't know what to do now, press <TAB>!

The basic function is quite clear: C3H completes names of the CML commands of all types. In addition, the CML shows possible structure of the configuration node being currently modified.

If the <TAB> is pressed after the first word on the line and the word is set or type name of a repeatable section, C3H searches for all acceptable names already entered and offers their names to complete. In the case of proxy phase 1 ACL section, the C3H offers system.acl names. Example:

  CML> <TAB>
      * shared-dir <name> { ... }
      * shared-file <name> { ... }
      * system <name> { ... }
  CML> sy<TAB>
  CML> system <TAB>
  <new name>  BILOVICE
  CML> system BILOVICE { <TAB>
        admin ...;
  CML> system BILOVICE { _

If the <TAB> is pressed somewhere in the middle of the line, C3H tries to advise in following cases:

  • If the current value must be a keword.

  • If the current value must be an enumeration member.

  • If the current value must be a global section name.

  • If the current value must be a parent ACL section name.

  • If the current word begins with a dollar ('$') character, all possible variables are offered. If there already is a variable name followed by a dot ('.'), C3H tries to complete variable path (see above, in the section called “Variable and reference paths”).

  • If the current word begins with a single up-arrow ('^') character, all possible continuation of reference path (see above, in the section called “Variable and reference paths”) is offered.

  • If the current word begins with a double quote ('"') character, filename completion is provided.

The C3H helps you also in some special circumstances:

  • If you type the /EDIT command and press the <TAB>, C3H will complete command line by the content of the node being currently under the cursor so that you can simply edit it.

  • The C3H will help you to complete the (extended) CML path when using the /SHOW command.

  • The C3H will help you to complete the CDF context path when defining a section variable.

  • The C3H try to help you to close an errorneous configuration directive and recover from the error state.

Control Sequences

The End-of-file control sequence (^D, Control-D) can be used for quitting the CML. It works silently only if the current configuration was not changed after the last loading/saving operation. Otherwise it rejects the operation and the /quit ! command must be used.

The ^R (Control-R) sequence is used for command history searching. You can type part of some previous command (the part is displayed in the prompt) and C3H searches in the history to the last command containing such a string. This command is then displayed on the command line and you can tune the selection by adding more characters to the pattern, removing some characters by the <Backspace> key or repeating the search by pressing the ^R again. If your selection is completed, press <Enter>, the selected command is placed into command line buffer and you can edit it. The CML tool saves command history at the end of its work and restores it at the beginning.

The ^U (Control-U) sequence is used for clearing the command line.

The CML Prompt

The CML prompts users with its own prompt. On the beginning, the text "CML> " is in the prompt. Whenever user enter some section, item or variable definition, for-loop etc., name of component occurs at the end of the prompt. Example:

  CML> system BILOVICE {
  CML.BILOVICE> routes {
  CML.BILOVICE.routes> set VAR {
  CML.BILOVICE.routes.set[VAR]> #{
  CML.BILOVICE.routes.set[VAR].#> #}
  CML.BILOVICE.routes.set[VAR]> }}}

If the configuration is in not a well defined state, a special appendix to the prompt occurs. The appendices are:


Last operation failed, currently edited configuration directive will be later deleted, it is time to immediately end it (you can try to let the C3H to advise you proper break-thru — press the <TAB> and <Enter> keys).


Grammar parser is awaiting for the opening brace, type "{".


Variable name is expected (in the for-loop or variable setting).


Variable type name (an equal sign or CDF context) is expected.


For-looop iteration list is expected.

If the prompt is too long (the path is too deep), the path displayed in the prompt is stripped from the left.

The CML Semantics

There are several configuration directives having a special meaning in the CML.


The CML adds a special directive version to each saved configuration so that newer versions of the software can indicate potential problems with understanding of an old configuration. This tag cannot be entered by user and is invisible for him/her.

Another hidden directive cml-id keeps the current RCS version of the configuration for easier detection of problems caused by some configuration changes done by the admin.

Also, the origin directive keeps track for the time and host name of configuration creation.

Shared Files and Directories

On the global configuration level, two kinds of sections concerning shared files (across the whole CML) can be defined. Both of them specify files/directories which primarily resides on the computer where the CML is run. During generation process, all the files are copied to the output tree. Sections shared-file and shared-dir are then copied to proxy configuration files, however, paths are changed so that they are valid on the target system. Example:

  shared-file MIME-SAMPLE {
    path "samples/mime-types"; # path relative to the CML cfg file
  system BILOVICE {
    kernun-root "/usr/local/kernun";
    ftp-proxy FTP-PROXY {

On the target system, the MIME sample file will be placed as /usr/local/kernun/etc/shared/mime-types and the configuration file for the ftp-proxy (i.e. /usr/local/kernun/etc/ftp-proxy.cfg) will contain

  shared-file MIME-SAMPLE {
    path "/usr/local/kernun/etc/shared/mime-types";
    ftp-proxy FTP-PROXY {

Level 1 ACL

Kernun proxies use several levels of ACL to control access to their services (see access-control(7)). Typically, the first level of ACL (called session-acl) decides according to the source and destination addresses, transparency, time etc. All these data are common to all proxies. Higher levels of ACL take in the count also some protocol specific information. In the CML, therefore the first level of ACL is picked up from the proxies definition to the system one. This allows the administrator to make general decisions and propagate them to particular proxies. At the proxy level, some protocol specific directives can be appended to all or to concrete ACLs. Higher levels of ACL are left fully to proxy specifications. Examples:

  system BILOVICE {
    acl IN-OUT {
      from [];
      service { FTP-PROXY, HTTP-PROXY }; # target proxies
    acl OUT-IN {
      from { ! []; * };
      service { HTTP-PROXY };            # target proxies
    ftp-proxy FTP-PROXY {
      session-acl * {      # add to all ACLs
        data-port 20;
    http-proxy HTTP-PROXY {
      session-acl OUT-IN { # add only to named ACL
        plug-to www.internal : 80;

Proxy configurations will look like:

  ftp-proxy FTP-PROXY {
    session-acl IN-OUT {
      from [];          # inherited from BILOVICE.IN-OUT
      data-port 20;              # added by FTP-PROXY.*
    # session-acl OUT-IN is not generated
  http-proxy HTTP-PROXY {
    session-acl IN-OUT {
      from [];          # inherited from BILOVICE.IN-OUT
      # nothing more added
    session-acl OUT-IN {
      from { ! []; * }; # inherited from BILOVICE.OUT-IN
      plug-to www.internal : 80; # added by HTTP-PROXY.OUT-IN

Generated Output

Command /generate (see above the section called “CML Commands”) creates in the configuration directory (i.e. directory where the currently loaded the CML file resides, or the current working directory) a tree of configuration files with root named SYSTEM-system-name. This tree is then copied into the filesystem root onto target machine by the kat(8) apply command. Within this tree, following files are generated:


sources: system.hostname, system.domain, system.interface(.alias), system.routes.default, system.routes.static, system.cluster.interface(.alias), system.rc-conf


sources: system.sysctl


sources: system.packet-filter,

/etc/passwd and other

source: system.user and original /etc/passwd




source: system.admin (for root alias), original /etc/aliases


sources: system.domain, system.resolver, system.use-resolver


source: system.hosts-table


source: system.crontab


source: system.ntp


for each ssh-server section NAME


for each proxy section NAME


for each shared-file and shared-dir section NAME

KERNUN_ROOT/etc/postfix.NAME/ and

for each smtp-forwarder section NAME with agent (Postfix) and for local-mailer (if used).

KERNUN_ROOT/etc/namedb.NAME/ directory

for each nameserver section NAME.


source: system.rotate-log and /etc/newsyslog.conf

The KERNUN_ROOT denotes the value of the kernun-root configuration directive of the particular system section (typically /usr/local/kernun).



The file name where log messages will be redirected. If not set, system logging is used.

See Also


access-control(7), configuration(7), kernun(7), logging(7), kat(8)


man(1), rcs(1), vi(1), editline(3)


The current version of the CML cannot process whole systems, level 1 ACLs and whole proxies within for-loops or section variables.


This man page is a part of Kernun Firewall.
Copyright © 2000–2023 Trusted Network Solutions, a. s.
All rights reserved.