Ambroz Bizjak 432f2ba511 NCD: Fix evdev event code names with newer headers.
Most of the event codes may be defined in another header file not directly in linux/input.h.
Also remove _MAX and _CNT codes.
2016-08-27 17:09:48 +02:00
..
examples ncd: Remove sphero example. 2015-01-24 16:48:29 +01:00
extra ncd: Store the NCDStingIndex pointer in NCDValMem. 2015-05-09 00:01:49 +02:00
modules Fix a typo in getargs.c 2015-12-02 15:42:30 +08:00
tests ncd: modules: arithmetic: Don't fail immediately on arithmetic errors, expose their occurrence. 2015-01-22 23:04:30 +01:00
CMakeLists.txt NCD: Fix evdev event code names with newer headers. 2016-08-27 17:09:48 +02:00
emncd.c ncd: move parsing of the program out of NCDInterpreter 2012-12-03 23:33:04 +00:00
emncd.html port NCD to Emscripten 2012-10-23 01:07:14 +00:00
include_linux_input.c compile with PathScale compiler 2012-08-01 20:38:27 +00:00
make_name_indices.h remove misc/split_string.h 2012-10-09 00:48:43 +00:00
module_common.h ncd: Refactor the function call infrastructure. 2014-11-11 00:33:40 +01:00
ncd.c ncd: Add --signal-exit-code option. 2014-11-09 14:14:24 +01:00
ncd.h BSignal: Also catch SIGHUP. 2016-04-24 10:01:05 +02:00
NCDAst.c Implement Do-Interrupt. 2014-12-20 19:37:46 +01:00
NCDAst.h Implement Do-Interrupt. 2014-12-20 19:37:46 +01:00
NCDBuildProgram.c Fix some variable shadowing (no bugs). 2014-11-12 21:52:49 +01:00
NCDBuildProgram.h ncd: implement NCDBuildProgram and make ncd.c utilize it. This finishes the initial implementation of the include system. 2012-12-04 18:25:43 +00:00
NCDConfigParser_parse.y ncd: Permit functions with have zero arguments. 2015-01-22 22:35:51 +01:00
NCDConfigParser.c Implement Do-Interrupt. 2014-12-20 19:37:46 +01:00
NCDConfigParser.h ncd: refactor parsing and implement if clauses 2012-05-29 14:51:27 +00:00
NCDConfigTokenizer.c Implement Do-Interrupt. 2014-12-20 19:37:46 +01:00
NCDConfigTokenizer.h Implement Do-Interrupt. 2014-12-20 19:37:46 +01:00
NCDEvaluator_call_vec.h structure/Vector: Split into header and implementation. 2014-11-08 20:31:51 +01:00
NCDEvaluator_var_vec.h structure/Vector: Split into header and implementation. 2014-11-08 20:31:51 +01:00
NCDEvaluator.c ncd: Store the NCDStingIndex pointer in NCDValMem. 2015-05-09 00:01:49 +02:00
NCDEvaluator.h structure/Vector: Split into header and implementation. 2014-11-08 20:31:51 +01:00
NCDInterpProcess.c ncd: NCDStringIndex: Refactor using MemRef. 2014-12-02 23:54:45 +01:00
NCDInterpProcess.h ncd: Refactoring to support upcoming function calls. 2014-10-30 01:17:59 +01:00
NCDInterpProg_hash.h ncd: NCDInterpProg: lookup processes by string ids 2012-10-18 13:33:32 +00:00
NCDInterpProg.c ncd: Refactoring to support upcoming function calls. 2014-10-30 01:17:59 +01:00
NCDInterpProg.h ncd: Refactoring to support upcoming function calls. 2014-10-30 01:17:59 +01:00
NCDInterpreter.c ncd: NCDStringIndex: Refactor using MemRef. 2014-12-02 23:54:45 +01:00
NCDInterpreter.h ncd: Refactor the function call infrastructure. 2014-11-11 00:33:40 +01:00
NCDMethodIndex_hash.h ncd: speed up module lookup when initializing statements. For non-method statements, cache the module pointer in NCDInterpBlock. For 2012-08-06 13:40:58 +00:00
NCDMethodIndex.c ncd: NCDModule: allow separating static module information from generated at runtime by the interpreter. Fix other stuff to work with 2012-12-09 18:21:37 +00:00
NCDMethodIndex.h ncd: NCDModule: allow separating static module information from generated at runtime by the interpreter. Fix other stuff to work with 2012-12-09 18:21:37 +00:00
NCDModule.c ncd: Refactoring using NCDModuleRef. 2014-12-21 11:17:04 +01:00
NCDModule.h ncd: Refactoring using NCDModuleRef. 2014-12-21 11:17:04 +01:00
NCDModuleIndex_fhash.h ncd: Implement registration of functions by modules. 2014-11-08 20:31:52 +01:00
NCDModuleIndex_func_vec.h ncd: Implement registration of functions by modules. 2014-11-08 20:31:52 +01:00
NCDModuleIndex_mhash.h ncd: NCDModule: allow separating static module information from generated at runtime by the interpreter. Fix other stuff to work with 2012-12-09 18:21:37 +00:00
NCDModuleIndex.c misc/substring.h: Refactor with MemRef. 2014-12-02 20:41:45 +01:00
NCDModuleIndex.h ncd: Implement registration of functions by modules. 2014-11-08 20:31:52 +01:00
NCDObject.c ncd: Implement object reference infrastructure and objref module. 2014-11-21 22:58:58 +01:00
NCDObject.h ncd: Implement object reference infrastructure and objref module. 2014-11-21 22:58:58 +01:00
NCDStringIndex_hash.h ncd: NCDStringIndex: support null bytes in strings 2012-11-18 17:21:11 +00:00
NCDStringIndex.c ncd: NCDStringIndex: Refactor using MemRef. 2014-12-02 23:54:45 +01:00
NCDStringIndex.h ncd: NCDStringIndex: Refactor using MemRef. 2014-12-02 23:54:45 +01:00
NCDSugar.c Implement Do-Interrupt. 2014-12-20 19:37:46 +01:00
NCDSugar.h add some missing file headers 2012-05-31 00:04:06 +00:00
NCDVal_maptree.h ncd: NCDVal: Renaming internal static functions. 2015-05-09 18:49:51 +02:00
NCDVal_types.h ncd: Store the NCDStingIndex pointer in NCDValMem. 2015-05-09 00:01:49 +02:00
NCDVal.c ncd: NCDVal: Renaming internal static functions. 2015-05-09 18:49:51 +02:00
NCDVal.h ncd: Store the NCDStingIndex pointer in NCDValMem. 2015-05-09 00:01:49 +02:00
NCDValCons.c ncd: NCDValCons, NCDValParser: report depth limit errors properly 2012-11-20 14:48:50 +00:00
NCDValCons.h ncd: NCDValCons, NCDValParser: report depth limit errors properly 2012-11-20 14:48:50 +00:00
NCDValGenerator.c Replace cstring with MemRef. 2014-11-25 21:18:48 +01:00
NCDValGenerator.h ncd: rename NCDValue{Generator,Parser} to NCDVal{Generator,Parser} 2012-10-05 01:45:22 +00:00
NCDValParser_parse.y ncd: rename NCDValue{Generator,Parser} to NCDVal{Generator,Parser} 2012-10-05 01:45:22 +00:00
NCDValParser.c Refactoring using MemRef. 2014-11-26 20:07:35 +01:00
NCDValParser.h Refactoring using MemRef. 2014-11-26 20:07:35 +01:00
parse_linux_input.sh NCD: Fix evdev event code names with newer headers. 2016-08-27 17:09:48 +02:00
README ncd: update README 2011-09-04 13:51:25 +00:00
static_strings.h ncd: modules: call: Implement inline_code calls. 2014-11-16 18:50:53 +01:00

# This file contains some examples of using NCD, the Network Configuration Daemon.
#
# A short introduction to NCD follows.
#
# NCD is a general-purpose system configuration system, operated with a unique programming language.
# The configuration consists of one or more so-called processes that can be considered executing in
# parallel. Further, each process consists of one or more statements, representing the individual
# actions. Statements are implemented as modules built into NCD.
#
# Inside a process, statements can be considered "executed" one after another. That is, when NCD
# starts up, it initializes the first statement, putting it in the DOWN state. When the statement
# reports having transitioned into the UP state, it initializes the next statement in the DOWN state,
# and so on.
#
# However, execution can go in the other direction too. A statement in the UP state can, at any time,
# report having transitioned into the DOWN state. At this point, any statements after that one will
# automatically be de-initialized. The de-initiazation is done from the bottom up. First the last
# initialized statement after the problematic statement is requested to terminate and enters the
# DYING state. After it terminates, its preceding statement enters the DYING state, and so on, until
# all statements following the problematic statement have been de-initiazed.
#
# The backward-execution is the key feature of NCD, and is particularly well suited for programming
# system configurations. Read on to see why.
#
# Statements in NCD can be divided into two categories:
#   - Statements that configure something. These statements transition into the UP state "immediately".
#     On de-initialization, such statements perform the reverse operation of what they did when initialized.
#     Imaginary example: a statement that turn a light on intialization, and turns if off on de-initialization.
#   - Statements that wait for something. These statements may remain in the DOWN state indefinitely.
#     They enter the UP state when the waited-for condition is satisfied, and also go back into the DOWN
#     state when it is no longer satisfied.
#     Imaginary example: a statement that is UP when a switch is turned on, and DOWN when it is turned off.
#
# Using the two example statements, we can constuct a process that controls the light based on the switch:
# (these are not really implemented in NCD :)
#
#  process light {
#      wait_switch();
#      turn_light();
#  }
#
# When the switch is turned on, wait_switch() will transition to UP, initializing turn_light(), turning the
# light on. When the switch is turned off, wait_switch() will transition to DOWN, causing the de-initialization
# of turn_light(), turning the light off.
# We can add another turn_light() at the end to make the switch control two lights.
#
# A more complex example: We have a christmas three with lights on it. There are multiple "regular" lights,
# controlled with switches, and a special "top" light. The regular lights take a long time to turn on, and
# each takes a different, unpredictable time. We want the top light to be turned on if and only if all the regular
# lights are completely on.
#
# This problem can easily be solved using dependencies. NCD has built-in support for dependencies, provided
# in the form of provide() and depend() statements. A depend() statement is DOWN when its corresponding
# provide() statement is not initialized, and UP when it is. When a provide() is requested to de-initialize, it
# transitions the depend() statements back into the DOWN state, and, before actually dying, waits for any
# statements following them to de-initialize.
#
# The christmas three problem can then be programmed as follows:
#
# process light1 {
#     wait_switch1();
#     turn_light1();
#     provide("L1");
# }
#
# process light2 {
#     wait_switch2();
#     turn_light2();
#     provide("L2");
# }
#
# process top_light {
#     depend("L1");
#     depend("L2");
#     turn_top_light();
# }
#
# Follow some real examples of network configuration using NCD.
# For a list of implemented statements and their descriptions, take a look at the BadVPN source code, in
# the ncd/modules/ folder.
#

#
# Network card using DHCP.
#

process lan {
    # Make the interface name a variable so we can refer to it.
    # The NCD language has no notion of assigning a variable. Instead variables are
    # provided by statements preceding the statement where they are used.
    # The built-in var() statement can be used to make an alias.
    var("eth0") dev;

    # Wait for the network card to appear, set it up and wait for the cable to be
    # plugged it.
    net.backend.waitdevice(dev);
    net.up(dev);
    net.backend.waitlink(dev);

    # Start DHCP.
    net.ipv4.dhcp(dev) dhcp;
    
    # DHCP has obtained an address.
    # Because net.ipv4.dhcp does no checks of the IP address, as a safety measure, do not proceed
    # if the address is local.
    ip_in_network(dhcp.addr, "127.0.0.0", "8") test_local;
    ifnot(test_local);

    # Assign the obtained address to the interface.
    net.ipv4.addr(dev, dhcp.addr, dhcp.prefix);

    # Add a default route.
    # <dest> <dest_prefix> <gateway/"none"> <metric> <device>
    net.ipv4.route("0.0.0.0", "0", dhcp.gateway, "20", dev);

    # Add DNS servers, as provided by DHCP.
    # "20" is the priority of the servers. When applying DNS servers, NCD collects the servers
    # from all active net.dns() statements, sorts them by priority ascending (stable), and writes
    # them to /etc/resolv.conf, overwriting anything that was previously there.
    net.dns(dhcp.dns_servers, "20");
}

#
# Network card with static configuration.
#

process lan2 {
    # Make the interface name a variable so we can refer to it.
    var("eth1") dev;

    # Wait for the network card to appear, set it up and wait for the cable to be
    # plugged it.
    net.backend.waitdevice(dev);
    net.up(dev);
    net.backend.waitlink(dev);

    # Assign an IP address.
    # "24" is prefix length, i.e. subnet mask 255.255.255.0
    net.ipv4.addr(dev, "192.168.62.3", "24");

    # Add a default route.
    net.ipv4.route("0.0.0.0", "0", "192.168.62.3", "20", dev);

    # Build a list of DNS servers.
    # The NCD language does not support "expressions" - statement arguments must be
    # constant strings or variables referring to preceding statements.
    # A list can be constructed using the built-in list() statement.
    list("192.168.62.5", "192.168.62.6") dns_servers;

    # Add the DNS servers.
    net.dns(dns_servers, "20");
}

#
# Wireless network interface using wpa_supplicant.
#

process WLAN {
    # Set device.
    var("wlan0") dev;

    # Wait for device and rfkill switch.
    net.backend.waitdevice(dev);
    net.backend.rfkill("wlan", dev);

    # Start wpa_supplicant on this interface, using configuration in /etc/wpa_supplicant/all.conf .
    list() args;
    net.backend.wpa_supplicant(dev, "/etc/wpa_supplicant/all.conf", "/usr/sbin/wpa_supplicant", args) sup;

    # wpa_supplicant tells us what network we connected to. Look below for how this can be used to
    # have different configurations, "BadVPN, but configured differently based on what network we're in".
    println("connected to wireless network: bssid=", sup.bssid, " ssid=", sup.ssid);

    # Wireless connection successful, here comes network config (DHCP/static/whatever) ...
}

#
# A BadVPN VPN interface for access to the virtual network (only).
#

process lan {
    ... (something like above) ...

    # Alias our IP address for easy access from the "vpn" process (or, for a static address, alias
    # it before assigning it, and assign it using the alias).
    var(dhcp.addr) ipaddr;

    # Allow VPN to start at this point.
    # (and require it to stop before deconfiguring the interface if e.g. the cable is plugged out)
    provide("LAN");
}

process vpn {
    # Need the local interface to be working in order start VPN.
    depend("LAN") landep;

    # Choose the name of the network interface.
    var("tap3") dev;

    # Construct command line arguments for badvpn-client. Adapt according to your setup.
    # "--tapdev" will be provided automatically.

    # Alias the port number that the VPN process will bind to.
    var("6000") port;

    # Construct dynamic parts of command line options.
    # The VPN client program needs to know some IP addresses in order to tell other peers where to connect to.
    # Obtain this informations from variables in the "lan" process through the depend() statement.

    # Construct the local address (addr + port).
    concat(landep.ipaddr, ":", port) local_addr_arg;

    # Construct the Internet address (assuming we are behind a NAT).
    # Need to know the NAT's external address here. But we could queried it somehow.
    # That is if we have preconfigured the NAT router to forward ports. But we could implement a statement
    # that obtains the mappings dynamically with UPnP!
    concat("1.2.3.4", ":", port) internet_addr_arg;

    # Finally construct the complete arguments, using the above address arguments.
    list(
        "--logger", "syslog", "--syslog-ident", "badvpn",
        "--server-addr", "badvpn.example.com:7000",
        "--ssl", "--nssdb", "sql:/home/badvpn/nssdb", "--client-cert-name", "peer-someone",
        "--transport-mode", "udp", "--encryption-mode", "blowfish", "--hash-mode", "md5", "--otp", "blowfish", "3000", "2000",
        "--scope", "mylan", "--scope", "internet",
        "--bind-addr", "0.0.0.0:6000", "--num-ports", "20",
                "--ext-addr", local_addr_arg, "mylan",
                "--ext-addr", internet_addr_arg, "internet"
    ) args;

    # Start the BadVPN backend.
    # "badvpn" is the user account which the VPN client will run as.
    # If you use SSL, the NSS database must be accessible to this user.
    net.backend.badvpn(dev, "badvpn", "/usr/bin/badvpn-client-26", args);

    # Assign an IP address to the VPN interface.
    # (we could easily use DHCP here!)
    net.ipv4.addr(dev, "10.0.0.1", "24");
}

#
# BadVPN, but configured differently based on what network we're in.
# The network is identified based on the IP address we were assigned by DHCP.
# The different configuration provide specific arguents to badvpn-client.
#

process lan {
    ... (interface config stuff using DHCP, see above) ...
    ... (the 'ipaddr' variable holds the local IP address) ...

    # Match the address to various known networks.
    ip_in_network(ipaddr, "192.168.4.0", "24") is_lan1;
    ip_in_network(ipaddr, "192.168.7.0", "24") is_lan2;

    # Allow VPN to start at this point.
    provide("LAN");
}

process vpn {
    ...

    # Construct common arguments here ...
    list( ... ) common_args;

    # Choose appropriate configuration by waking up the configuration processes
    # and waiting for one to complete.
    provide("VPN_CONF_START");
    depend("VPN_CONF_END") config;

    # Concatenate common and configuration-specific arguments.
    concatlist(common_args, config.args) args;

    ...
}

process vpn_config_lan1 {
    depend("VPN_CONF_START") dep;

    # Proceed only if we're in lan1.
    if(dep.landep.is_lan1);

    list(
        ...
    ) args;

    provide("VPN_CONF_END");
}

process vpn_config_lan2 {
    depend("VPN_CONF_START") dep;

    # Proceed only if we're in lan2.
    if(dep.landep.is_lan2);

    list(
        ...
    ) args;

    provide("VPN_CONF_END");
}

process vpn_config_inet {
    depend("VPN_CONF_START") dep;

    # Proceed only if we're not in any known network.
    ifnot(dep.landep.is_lan1);
    ifnot(dep.landep.is_lan2);

    list(
        ...
    ) args;

    provide("VPN_CONF_END");
}

#
# Two wired network interfaces (eth0, eth1), both of which may be used for Internet access.
# When both are working, give priority to eth1 (e.g. if eth0 is up, but later eth1 also comes
# up, the configuration will be changed to use eth1 for Internet access).
#

process eth0 {
    # Set device.
    var("eth0") dev;

    # Wait for device.
    net.backend.waitdevice(dev);
    net.up(dev);
    net.backend.waitlink(dev);

    # DHCP configuration.
    net.ipv4.dhcp(dev) dhcp;
    ip_in_network(dhcp.addr, "127.0.0.0", "8") test_local;
    ifnot(test_local);
    var(dhcp.addr) addr;
    var(dhcp.prefix) addr_prefix;
    var(dhcp.gateway) gateway;
    var(dhcp.dns_servers) dns_servers;

    # Assign IP address.
    net.ipv4.addr(dev, addr, addr_prefix);

    # Go on configuring the network.
    multiprovide("NET-eth0");
}

process eth1 {
    # Set device.
    var("eth1") dev;

    # Wait for device.
    net.backend.waitdevice(dev);
    net.up(dev);
    net.backend.waitlink(dev);

    # Static configuration.
    var("192.168.111.116") addr;
    var("24") addr_prefix;
    var("192.168.111.1") gateway;
    list("192.168.111.14", "193.2.1.66") dns_servers;

    # Assign IP address.
    net.ipv4.addr(dev, addr, addr_prefix);

    # Go on configuring the network.
    multiprovide("NET-eth1");
}

process NETCONF {
    # Wait for some network connection. Prefer eth1 by putting it in front of eth0.
    list("NET-eth1", "NET-eth0") pnames;
    multidepend(pnames) ifdep;

    # Alias device values.
    var(ifdep.dev) dev;
    var(ifdep.addr) addr;
    var(ifdep.addr_prefix) addr_prefix;
    var(ifdep.gateway) gateway;
    var(ifdep.dns_servers) dns_servers;

    # Add default route.
    net.ipv4.route("0.0.0.0", "0", gateway, "20", dev);

    # Configure DNS servers.
    net.dns(dns_servers, "20");
}