# This is a configuration file for the configuration
# generator: it is used by
# conf2struct(http://www.rutschle.net/tech/conf2struct/README.html)
# to generate the config file and command line parser in
# sslh-conf.c

header: "sslh-conf.h";
parser: "sslh-conf.c";

printer: true;

conffile_option: ("F", "config");

# List of includes to define runtime types
# (bug in libconfig? if swallows the brackets if they start
# the string)
includes: (
           "probe.h",
           " <sys/types.h>",
           " <sys/socket.h>",
           " <netdb.h>"
          );

config: {
         name : "sslhcfg",
         type: "list",
         items: (
            { name: "verbose-config"; type: "int"; default: 0; 
                description: "Print configuration at startup" },
            { name: "verbose-config-error"; type: "int"; default: 3; 
                description: "Print configuration errors" },
            { name: "verbose-connections"; type: "int"; default: 3; 
                description: "Trace established incoming address to forward address" },
            { name: "verbose-connections-try"; type: "int"; default: 0; 
                description: "Connection errors" },
            { name: "verbose-connections-error"; type: "int"; default: 3; 
                description: "Connection attempts towards targets" },
            { name: "verbose-fd"; type: "int"; default: 0; 
                description: "File descriptor activity, open/close/whatnot" },
            { name: "verbose-packets"; type: "int"; default: 0; 
                description: "Hexdump packets on which probing is done" },

            { name: "verbose-probe-info"; type: "int"; default: 0; 
                description: "Trace the probe process" },
            { name: "verbose-probe-error"; type: "int"; default: 3; 
                description: "Failures and problems during probing" },

            { name: "verbose-system-error"; type: "int"; default: 3; 
                description: "System call failures" },
            { name: "verbose-int-error"; type: "int"; default: 3; 
                description: "Internal errors that should never happen" },

            { name: "version"; type: "bool"; default: false;
              short: "V";
              description: "Print version information and exit"; },
            { name: "foreground"; type: "bool"; default: false;
              short: "f";
              description: "Run in foreground instead of as a daemon"; },
            { name: "inetd"; type: "bool"; default: false;
              short: "i";
              description: "Run in inetd mode: use stdin/stdout instead of network listen"; },
            { name: "numeric"; type: "bool"; default: false;
              short: "n";
              description: "Print IP addresses and ports as numbers"; },
            { name: "transparent"; type: "bool"; default: false;
              description: "Set up as a transparent proxy"; },
            { name: "timeout"; type: "int"; default: 5; 
              short: "t";
              description: "Set up timeout before connecting to default target"; },
            { name: "udp_max_connections"; type: "int"; default: 1024;
              description: "Number of concurrent UDP connections"; },
            { name: "user"; type: "string"; optional: true; 
              short: "u";
              description: "Username to change to after set-up"; },
            { name: "pidfile"; type: "string"; optional: true; 
              short: "P"; argdesc: "<file>";
              description: "Path to file to store PID of current instance"; },
            { name: "chroot"; type: "string"; optional: true;
              short: "C"; argdesc: "<path>";
              description: "Root to change to after set-up"; },
            { name: "syslog_facility"; type: "string"; default: "auth"; 
              description: "Facility to syslog to"; },
            { name: "logfile"; type: "string"; optional: true;
              description: "Log messages to a file" },

            { name: "on-timeout"; type: "string"; default: "ssh"; 
              description: "Target to connect to when timing out"; },

            { name: "prefix"; type: "string"; default: ""; description: "Reserved for testing" }, # For echosrv only, not sslh

            { name: "listen", 
                no_cl_accessors: true;  # disable generation of individual cl options for each group element (we create a specific --listen option further below)
                type: "list", 
                items: (
                    { name: "host"; type: "string"; var: true; },
                    { name: "port"; type: "string"; var: true; },
                    { name: "is_udp"; type: "bool"; default: false },
                    { name: "keepalive"; type: "bool"; default: false; }
                )
            },

            { name: "protocols",
                no_cl_accessors: true;
                type: "list",
                items: (
                    { name: "name"; type: "string"; },
                    { name: "host"; type: "string"; var: true; },
                    { name: "port"; type: "string"; var: true; },
                    { name: "service"; type: "string"; optional: true; },
                    { name: "is_udp"; type: "bool"; default: false },
                    { name: "udp_timeout"; type: "int"; default: 60 },
                    { name: "fork"; type: "bool"; default: false },
                    { name: "tfo_ok"; type: "bool"; default: false;
                        description: "Set to true if this protocol supports TCP FAST OPEN" },
                    { name: "transparent"; type: "bool"; default: false;
                        description: "Set to proxy this protocol transparently" },
                    { name: "resolve_on_forward"; type: "bool"; default: false;
                        description: "Set to true if server address should be resolved on (every) newly incoming connection (again)" },
                    { name: "log_level"; type: "int"; default: 1 },
                    { name: "keepalive"; type: "bool"; default: false },
                    { name: "sni_hostnames",
                        type: "array", 
                        element_type: "string"
                    },
                    { name: "alpn_protocols",
                    type: "array",
                    element_type: "string" 
                    },
                    { name: "regex_patterns",
                    type: "array",
                    element_type: "string"
                    },
                    { name: "minlength"; type: "int"; optional: true },

                    # Runtime data
                    { name: "probe"; type: "runtime"; c_type: "T_PROBE*" },
                    { name: "saddr"; type: "runtime"; c_type: "struct addrinfo*" },
                    { name: "data"; type: "runtime"; c_type: "void*" },
                    { name: "timeouts"; type: "runtime"; c_type: "dl_list" }
                )
            }
        )
}

# Command line for list settings: additional options that
# can set up several settings at once. Each option will
# create a new group setting entry if required (with
# defaults set up)
# This only works with string targets
# This may not be the right abstraction at all and way too
# sslh-centric
cl_groups: (
    { name: "listen"; pattern: "(.+):(\w+)"; description: "Listen on host:port";
      short: "p"; argdesc: "<host:port>";
        list: "listen";
        # no override, this just adds to the list (and thus can be specified several times)
        targets: (
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" }
        );
    },
    { name: "ssh"; pattern: "(.+):(\w+)";  description: "Set up ssh target";
        list: "protocols"; # List name that we're defining with this command line option
        override: "name";  # Field in the group to override.  If not found in list, add an item
                           # (it's mandatory to have that field as one of the targets
                           # below)
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "ssh" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "fork"; value: 1 },
        { path: "log_level"; value: 1 },
        { path: "tfo_ok"; value: 1 }
        );
    },
    { name: "tls"; pattern: "(.+):(\w+)"; description: "Set up TLS/SSL target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "tls" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 },
        { path: "tfo_ok"; value: 1 }
        );
    },
    { name: "openvpn"; pattern: "(.+):(\w+)"; description: "Set up OpenVPN target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "openvpn" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 },
        { path: "tfo_ok"; value: 1 }
        );
    },
    { name: "tinc"; pattern: "(.+):(\w+)"; description: "Set up tinc target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "tinc" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 },
        { path: "tfo_ok"; value: 1 }
        );
    },
    { name: "wireguard"; pattern: "(.+):(\w+)"; description: "Set up WireGuard target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "wireguard" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 },
        { path: "tfo_ok"; value: 1 }
        );
    },
    { name: "xmpp"; pattern: "(.+):(\w+)"; description: "Set up XMPP target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "xmpp" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 }
        );
    },
    { name: "http"; pattern: "(.+):(\w+)"; description: "Set up HTTP (plain) target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "http" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 }
        );
    },
    { name: "adb"; pattern: "(.+):(\w+)"; description: "Set up ADB (Android Debug) target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "adb" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 }
        );
    },
    { name: "socks5"; pattern: "(.+):(\w+)"; description: "Set up socks5 target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "socks5" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 }
        );
    },
    { name: "syslog"; pattern: "(.+):(\w+)"; description: "Set up syslog target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "syslog" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 }
        );
    },
    { name: "msrdp"; pattern: "(.+):(\w+)"; description: "Set up msrdp target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "msrdp" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 }
        );
    },
    { name: "anyprot"; pattern: "(.+):(\w+)"; description: "Set up default target";
        list: "protocols";
        override: "name";
        argdesc: "<host:port>";
        targets: (
        { path: "name"; value: "anyprot" },
        { path: "host"; value: "$1" },
        { path: "port"; value: "$2" },
        { path: "log_level"; value: 1 }
        );
    }
)