示例#1
0
文件: main.c 项目: nabto/unabto
static bool test_parse_args(const char * progname, int argc, char* argv[], nabto_main_setup* nms)
{
    const char *x1[] = { "help", 0 };
    const char *x2[] = { "version", 0 };
    const char *x3[] = { "config", 0 };
    const char *x4[] = { "size", 0 };
    const char *x5[] = { "deviceName", 0 };
    const char *x6[] = { "use_encryption", 0 };
    const char *x7[] = { "encryption_key", 0 };
    const char *x8[] = { "localport", 0 };
    const char *x11[] = { "nice_exit", 0};

    const struct { int k; int f; const char *s; const char*const* l; } opts[] = {
        { 'h', GOPT_NOARG,   "h?", x1 },
        { 'V', GOPT_NOARG,   "V",  x2 },
        { 'C', GOPT_NOARG,   "C",  x3 },
        { 'S', GOPT_NOARG,   "S",  x4 },
        { 'd', GOPT_ARG,     "d",  x5 },
        { 's', GOPT_NOARG,   "s",  x6 },
        { 'k', GOPT_ARG,     "k",  x7 },
        { 'p', GOPT_ARG,     "p",  x8 },
        { 'x', GOPT_NOARG,   "x",  x11 },
        { 0,0,0,0 }
    };

    void *options = gopt_sort(&argc, (const char**)argv, opts);

    if (gopt(options, 'h')) {
        printf("Usage: %s [options]\n", progname);
        printf("   -h  Print this help.\n");
        printf("   -V  Print release version.\n");
        printf("   -C  Print configuration (unabto_config.h).\n");
        printf("   -S  Print size (in bytes) of structures (memory usage).\n");
        exit(0);
    }
    
    if (gopt(options, 'V')) {
        printf("%s: %d.%d\n", progname, RELEASE_MAJOR, RELEASE_MINOR);
        exit(0);
    }
    
    if (gopt(options, 'C')) {
        unabto_printf_unabto_config(stdout, progname);
        exit(0);
    }
    
    if (gopt(options, 'S')) {
        unabto_printf_memory_sizes(stdout, progname);
        exit(0);
    }

    if (!gopt_arg(options, 'd', &nms->id)) {
        NABTO_LOG_FATAL(("Specify a serverId with -d"));
    }
    
    if (gopt(options, 's')) {
        const char* preSharedKey;
        if ( gopt_arg( options, 'k', &preSharedKey)) {
            if (!unabto_read_psk_from_hex(preSharedKey, nms->presharedKey, 16)) {
                NABTO_LOG_FATAL(("Cannot read presharedkey");
            }
        }
#if NABTO_ENABLE_CONNECTIONS
        nms->cryptoSuite = CRYPT_W_AES_CBC_HMAC_SHA256;
#endif
    }
bool check_args(int argc, char* argv[], nabto_main_setup *nms)
{
    const char *address;
    const char *basestationAddress;
    const char *preSharedKey;
    const char *localPortStr;
    const char *bufferSizeStr;
    const char *idParam;
    const char *interfaceParam;
    const char *htmlddurloverride;
    uint32_t addr;
    const char *progname;
#ifdef WIN32
    char modulename[MAX_PATH];
#endif

    
    const char x0s[] = "h?";     const char* x0l[] = { "help", "HELP", 0 };
    const char x1s[] = "a";      const char* x1l[] = { "localAddress", 0 };
    const char x2s[] = "d";      const char* x2l[] = { "deviceName", 0 };
    const char x3s[] = "l";      const char* x3l[] = { "log", 0 };
    const char x4s[] = "A";      const char* x4l[] = { "controllerAddress", 0 };
    const char x5s[] = "p";      const char* x5l[] = { "localport", 0 };
    const char x6s[] = "b";      const char* x6l[] = { "buffersize", 0 };
    const char x7s[] = "k";      const char* x7l[] = { "presharedkey", 0 };
    const char x8s[] = "s";      const char* x8l[] = { "securedevice", 0 };
    const char x9s[] = "n";      const char* x9l[] = { "datanullencrypted", 0 };
    const char x10s[] = "i";     const char* x10l[] = { "interface", 0 };
    const char x11s[] = "U";     const char* x11l[] = { "htmlddurloverride", 0 };
    const char x12s[] = "V";     const char* x12l[] = { "version", 0 };
    const char x13s[] = "C";     const char* x13l[] = { "config", 0 };
    const char x14s[] = "S";     const char* x14l[] = { "size", 0 };

    const struct { int k; int f; const char *s; const char*const* l; } opts[] = {
        { 'h', 0,           x0s, x0l },
        { 'a', GOPT_ARG,    x1s, x1l },
        { 'd', GOPT_ARG,    x2s, x2l },
        { 'l', GOPT_REPEAT, x3s, x3l },
        { 'A', GOPT_ARG,    x4s, x4l },
        { 'p', GOPT_ARG,    x5s, x5l },
        { 'b', GOPT_ARG,    x6s, x6l },
        { 'k', GOPT_ARG,    x7s, x7l },
        { 's', 0,           x8s, x8l },
        { 'n', 0,           x9s, x9l },
        { 'i', GOPT_ARG,    x10s, x10l },
        { 'U', GOPT_ARG,    x11s, x11l },
        { 'V', GOPT_NOARG,  x12s, x12l },
        { 'C', GOPT_NOARG,  x13s, x13l },
        { 'S', GOPT_NOARG,  x14s, x14l },
        { 0,0,0,0 }
    };

    void *options = gopt_sort( & argc, (const char**)argv, opts);

#ifdef WIN32
    modulename[0] = 0;
    GetModuleFileNameA(NULL, modulename, sizeof(modulename));
    progname = strrchr(modulename, '\\');
    if (!progname)
        progname = modulename;
    else
        progname++;
#else
    progname = strrchr(argv[0], '/');
    if (!progname)
        progname = argv[0];
    else
        progname++;
#endif

    if( gopt( options, 'h')) {
        help("Help", progname);
        return false;
    }
    
    if (gopt(options, 'V')) {
        fprintf(stdout, "%d.%d\n", RELEASE_MAJOR, RELEASE_MINOR);
        return false;
    }

    if( gopt( options, 'C')) {
        unabto_printf_unabto_config(stdout, progname);
        return false;
    }
    
    if (gopt(options, 'S')) {
        unabto_printf_memory_sizes(stdout, progname);
        return false;
    }

    if( gopt_arg( options, 'a', & address ) ){
        addr = inet_addr(address);
        if (addr == INADDR_NONE) {
            help("Illegal local address", progname);
            gopt_free(options);
            return false;
        }
		nms->ipAddress = htonl(addr);
    } 

    if( gopt_arg( options, 'd', &idParam ) ){
        nms->id = strdup(idParam);
    } else {
        help("You must specify an id for your uNabto device", progname);
        gopt_free(options);
        return false;
    }

    if( gopt_arg( options, 'p', &localPortStr) ){
		nms->localPort = atoi(localPortStr);
    }

    if( gopt_arg( options, 'b', &bufferSizeStr) ){
        nms->bufsize = (size_t)atoi(bufferSizeStr);
    }

    if( gopt_arg( options, 'A', & basestationAddress ) ){
        addr = inet_addr(basestationAddress);
        if (addr == INADDR_NONE) {
            help("Illegal basestation address", progname);
            gopt_free(options);
            return false;
        }
        nms->controllerArg.addr = htonl(addr);
    }

    if ( gopt_arg( options, 'k', &preSharedKey)) {
        size_t i;
        size_t pskLen = strlen(preSharedKey);
        // read the pre shared key as a hexadecimal string.
        for (i = 0; i < pskLen/2 && i < 16; i++) {
            sscanf_s(preSharedKey+(2*i), "%02hhx", &nms->presharedKey[i]);
        }
    }

    if (gopt(options, 's')) {
        nms->secureAttach= true;
        nms->secureData = true;
#if NABTO_ENABLE_CONNECTIONS
        nms->cryptoSuite = CRYPT_W_AES_CBC_HMAC_SHA256;
#endif
    }
    if (gopt(options, 'n')) {
        nms->secureData = false;
    }

    if (gopt_arg(options, 'i', &interfaceParam)) {
        nms->interfaceName = strdup(interfaceParam);
    }

    if (gopt_arg(options, 'U', &htmlddurloverride)) {
        nms->url = strdup(htmlddurloverride);
    }

    gopt_free(options);
    
    return true;
}
示例#3
0
文件: main.c 项目: nabto/unabto
static bool tunnel_parse_args(int argc, char* argv[], nabto_main_setup* nms) {

    const char *tunnel_port_str;

    const char x1s[] = "h";      const char* x1l[] = { "help", 0 };
    const char x2s[] = "V";      const char* x2l[] = { "version", 0 };
    const char x3s[] = "C";      const char* x3l[] = { "config", 0 };
    const char x4s[] = "S";      const char* x4l[] = { "size", 0 };
    const char x9s[] = "d";      const char* x9l[] = { "device_name", 0 };
    const char x10s[] = "H";     const char* x10l[] = { "tunnel_default_host", 0 }; // only used together with the tunnel.
    const char x11s[] = "P";     const char* x11l[] = { "tunnel_default_port", 0 };
    const char x12s[] = "s";     const char* x12l[] = { "use_encryption", 0 };
    const char x13s[] = "k";     const char* x13l[] = { "encryption_key", 0 };
    const char x14s[] = "p";     const char* x14l[] = { "localport", 0 };
    const char x15s[] = "a";     const char* x15l[] = { "check_acl", 0 };
    const char x16s[] = "";      const char* x16l[] = { "allow_port", 0};
    const char x17s[] = "";      const char* x17l[] = { "allow_host", 0};
    const char x18s[] = "x";     const char* x18l[] = { "nice_exit", 0};
    const char x19s[] = "";      const char* x19l[] = { "allow_all_ports", 0};
    const char x21s[] = "l";     const char* x21l[] = { "nabtolog", 0 };
    const char x22s[] = "A";     const char* x22l[] = { "controller", 0 };
    const char x23s[] = "";      const char* x23l[] = { "disable_tcp_fb", 0 };
    const char x24s[] = "";      const char* x24l[] = { "controller_port", 0 };
#if NABTO_ENABLE_EPOLL
    const char x25s[] = "";      const char* x25l[] = { "select_based", 0 };
#endif

    const char x26s[] = "";      const char* x26l[] = { "tunnels", 0 };
    const char x27s[] = "";      const char* x27l[] = { "stream_window_size",0 };
    const char x28s[] = "";      const char* x28l[] = { "connections", 0 };
    const char x29s[] = "";      const char* x29l[] = { "disable_extended_rendezvous_multiple_sockets", 0 };
// uart options
    const char x30s[] = "";      const char* x30l[] = { "uart_device", 0 }; 

    const struct { int k; int f; const char *s; const char*const* l; } opts[] = {
        { 'h', GOPT_NOARG,   x1s, x1l },
        { 'V', GOPT_NOARG,   x2s, x2l },
        { 'C', GOPT_NOARG,   x3s, x3l },
        { 'S', GOPT_NOARG,   x4s, x4l },
        { 'd', GOPT_ARG,     x9s, x9l },
        { 'H', GOPT_ARG,     x10s, x10l },
        { 'P', GOPT_ARG,     x11s, x11l },
        { 's', GOPT_NOARG,   x12s, x12l },
        { 'k', GOPT_ARG,     x13s, x13l },
        { 'p', GOPT_ARG,     x14s, x14l },
        { 'a', GOPT_NOARG,   x15s, x15l },
        { ALLOW_PORT_OPTION, GOPT_REPEAT|GOPT_ARG, x16s, x16l },
        { ALLOW_HOST_OPTION, GOPT_REPEAT|GOPT_ARG, x17s, x17l },
        { 'x', GOPT_NOARG, x18s, x18l },
        { ALLOW_ALL_PORTS_OPTION, GOPT_NOARG, x19s, x19l },
        { 'l', GOPT_REPEAT|GOPT_ARG,  x21s, x21l },
        { 'A', GOPT_ARG, x22s, x22l },
        { DISABLE_TCP_FALLBACK_OPTION, GOPT_NOARG, x23s, x23l },
        { CONTROLLER_PORT_OPTION, GOPT_ARG, x24s, x24l },
#if NABTO_ENABLE_EPOLL
        { SELECT_BASED_OPTION, GOPT_NOARG, x25s, x25l },
#endif
#if NABTO_ENABLE_DYNAMIC_MEMORY
        { TUNNELS_OPTION, GOPT_ARG, x26s, x26l },
        { STREAM_WINDOW_SIZE_OPTION, GOPT_ARG, x27s, x27l },
        { CONNECTIONS_SIZE_OPTION, GOPT_ARG, x28s, x28l },
#endif
#if NABTO_ENABLE_EXTENDED_RENDEZVOUS_MULTIPLE_SOCKETS
        { DISABLE_EXTENDED_RENDEZVOUS_MULTIPLE_SOCKETS, GOPT_NOARG, x29s, x29l },
#endif
        { UART_DEVICE_OPTION, GOPT_ARG, x30s, x30l },
        { 0,0,0,0 }
    };

    void *options = gopt_sort( & argc, (const char**)argv, opts);

    const char * h;
    int p;
    const char* localPortStr;
    const char* optionString;
    const char* basestationAddress;
    const char* controllerPort;
    const char* tunnelsOption;
    const char* streamWindowSizeOption;
    const char* connectionsOption;
    const char* uartDevice = 0;
    uint32_t addr;


    if (gopt(options, 'h')) {
        printf("Usage: unabto_tunnel [options] -d devicename\n");
        printf("  -h, --help                  Print this help.\n");
        printf("  -V, --version               Print version.\n");
        printf("  -C, --config                Print configuration (unabto_config.h).\n");
        printf("  -S, --size                  Print size (in bytes) of memory usage.\n");
        printf("  -l, --nabtolog              Speficy log level such as *.trace.\n");
        printf("  -d, --device_name           Specify name of this device.\n");
        printf("  -H, --tunnel_default_host   Set default host name for tunnel (%s).\n", UNABTO_TUNNEL_TCP_DEFAULT_HOST);
        printf("  -P, --tunnel_default_port   Set default port for tunnel (%u).\n", UNABTO_TUNNEL_TCP_DEFAULT_PORT);
        printf("  -s, --use_encryption        Encrypt communication.\n");
        printf("  -k, --encryption_key        Specify encryption key.\n");
        printf("  -p, --localport             Specify port for local connections.\n");
        printf("  -A, --controller            Specify controller address\n");
        printf("      --controller_port       sets the controller port number.\n");
        printf("  -a, --check_acl             Perform ACL check when establishing connection.\n");
        printf("      --allow_all_ports       Allow connections to all port numbers.\n");
        printf("      --allow_port            Ports that are allowed. Requires -a.\n");
        printf("      --allow_host            Hostnames that are allowed. Requires -a.\n");
        printf("      --uart_device           Sets the uart device\n");
        printf("  -x, --nice_exit             Close the tunnels nicely when pressing Ctrl+C.\n");
#if NABTO_ENABLE_TCP_FALLBACK
        printf("      --disable_tcp_fb        Disable tcp fallback.\n");
#endif
#if NABTO_ENABLE_EPOLL
        printf("      --select_based          Use select instead of epoll.\n");
#endif
#if NABTO_ENABLE_DYNAMIC_MEMORY
        printf("      --tunnels               Specify how many concurrent tcp streams should be possible.\n");
        printf("      --stream_window_size    Specify the stream window size, the larger the value the more memory the aplication will use, but higher throughput will be possible.\n");
        printf("      --connections           Specify the maximum number of allowed concurrent connections.\n");
#endif
#if NABTO_ENABLE_EXTENDED_RENDEZVOUS_MULTIPLE_SOCKETS
        printf("      --disable_extended_rendezvous_multiple_sockets     Disable multiple sockets in extended rendezvous.\n");
#endif
        exit(0);
    }

    if (gopt(options, 'V')) {
        printf("%d.%d\n", RELEASE_MAJOR, RELEASE_MINOR);
        exit(0);
    }

    if (gopt(options, 'C')) {
        unabto_printf_unabto_config(stdout, "unabto_tunnel");
        exit(0);
    }

    if (gopt(options, 'S')) {
        unabto_printf_memory_sizes(stdout, "unabto_tunnel");
        exit(0);
    }
    
    { 
        size_t optionsLength = gopt(options, 'l');
        int i;
        if (optionsLength > 0) {
            for (i = 0; i < optionsLength; i++) {
                optionString = gopt_arg_i(options, 'l', i);
                if (!unabto_log_system_enable_stdout_pattern(optionString)) {
                    NABTO_LOG_FATAL(("Logstring %s is not a valid logsetting", optionString));
                }
            }
        } else {
            unabto_log_system_enable_stdout_pattern("*.info");
        }
        
    } 
    

    if (!gopt_arg( options, 'd', &nms->id)) {
        NABTO_LOG_FATAL(("Specify a serverId with -d. Try -h for help."));
    }

    if(gopt_arg(options, 'H', &h)) {
        unabto_tunnel_tcp_set_default_host(h);
    }

    if (gopt_arg(options, 'P', &tunnel_port_str)) {
        if(1 != sscanf(tunnel_port_str, "%d", &p)) {
            NABTO_LOG_TRACE(("Reading of port parameter failed."));
        } else {
            unabto_tunnel_tcp_set_default_port(p);
        }
    }
     
    if( gopt_arg( options, 'p', &localPortStr) ){
        int localPort = atoi(localPortStr);
        nms->localPort = localPort;
    }


    if (gopt(options, 's')) {
        const char* preSharedKey;
        uint8_t key[16];
        memset(key, 0, 16);
        if ( gopt_arg( options, 'k', &preSharedKey)) {
            size_t i;
            size_t pskLen = strlen(preSharedKey);
            // read the pre shared key as a hexadecimal string.
            for (i = 0; i < pskLen/2 && i < 16; i++) {
                sscanf(preSharedKey+(2*i), "%02hhx", &key[i]);
            }
        }
        memcpy(nms->presharedKey,key,16);
        nms->cryptoSuite = CRYPT_W_AES_CBC_HMAC_SHA256;
        nms->secureAttach = true;
        nms->secureData = true;
    }

    if (gopt(options, 'a')) {
        check_acl = true;
    }

    if( gopt_arg( options, 'A', & basestationAddress ) ){
        addr = inet_addr(basestationAddress);
        if (addr == INADDR_NONE) {
            NABTO_LOG_FATAL(("Invalid basestation address"));
        }
        nms->controllerArg.addr = htonl(addr);
    }

    if (gopt(options, 'x')) {
        nice_exit = true;
    }
    
    ports_length = gopt(options, ALLOW_PORT_OPTION);
    if (ports_length > 0) {
        size_t i;
        ports = (uint16_t*) malloc(ports_length*sizeof(uint16_t));
        memset(ports,0,ports_length*sizeof(uint16_t));
        for (i = 0; i < ports_length; i++) {
            const char* opt = gopt_arg_i(options, ALLOW_PORT_OPTION, i);
            ports[i] = atoi(opt);
        }
    }
    
    hosts_length = gopt(options, ALLOW_HOST_OPTION);
    if (hosts_length > 0) {
        size_t i;
        hosts = (char**) malloc(hosts_length*sizeof(char*));
        for (i = 0; i < hosts_length; i++) {
            const char* opt = gopt_arg_i(options, ALLOW_HOST_OPTION, i);
            hosts[i] = strdup(opt);
        }
    }

    if (gopt(options, ALLOW_ALL_PORTS_OPTION)) {
        allow_all_ports = true;
    }

    if(gopt_arg(options, UART_DEVICE_OPTION, &uartDevice)) {
        uart_tunnel_set_default_device(uartDevice);
    } else {
        NABTO_LOG_TRACE(("Missing uart device option."));
        uartDevice = 0;
    }
    
#if NABTO_ENABLE_TCP_FALLBACK
    if (gopt(options, DISABLE_TCP_FALLBACK_OPTION)) {
        nms->enableTcpFallback = false;
    }
#endif

    if (gopt_arg(options, CONTROLLER_PORT_OPTION, &controllerPort)) {
        nms->controllerArg.port = atoi(controllerPort);
    }

#if NABTO_ENABLE_EPOLL
    if (gopt(options, SELECT_BASED_OPTION)) {
        useSelectBased = true;
    }
#endif

#if NABTO_ENABLE_DYNAMIC_MEMORY
    if (gopt_arg(options, TUNNELS_OPTION, &tunnelsOption)) {
        nms->streamMaxStreams = atoi(tunnelsOption);
    }

    if (gopt_arg(options, STREAM_WINDOW_SIZE_OPTION, &streamWindowSizeOption)) {
        uint16_t windowSize = atoi(streamWindowSizeOption);
        nms->streamReceiveWindowSize = windowSize;
        nms->streamSendWindowSize = windowSize;
    }

    if (gopt_arg(options, CONNECTIONS_SIZE_OPTION, &connectionsOption)) {
        nms->connectionsSize = atoi(connectionsOption);
    }
#endif

#if NABTO_ENABLE_EXTENDED_RENDEZVOUS_MULTIPLE_SOCKETS
    if (gopt(options, DISABLE_EXTENDED_RENDEZVOUS_MULTIPLE_SOCKETS)) {
        nms->enableExtendedRendezvousMultipleSockets = false;
    }
#endif

    return true;
}
static bool tunnel_parse_args(int argc, char* argv[], nabto_main_setup* nms) {

    const char *tunnel_port_str;

    const char x1s[] = "h";      const char* x1l[] = { "help", 0 };
    const char x2s[] = "V";      const char* x2l[] = { "version", 0 };
    const char x3s[] = "C";      const char* x3l[] = { "config", 0 };
    const char x4s[] = "S";      const char* x4l[] = { "size", 0 };
    const char x9s[] = "d";      const char* x9l[] = { "deviceName", 0 };
    const char x10s[] = "H";     const char* x10l[] = { "tunnel_default_host", 0 }; // only used together with the tunnel.
    const char x11s[] = "P";     const char* x11l[] = { "tunnel_default_port", 0 };
    const char x12s[] = "s";     const char* x12l[] = { "use_encryption", 0 };
    const char x13s[] = "k";     const char* x13l[] = { "encryption_key", 0 };
    const char x14s[] = "p";     const char* x14l[] = { "localport", 0 };
    const char x15s[] = "a";     const char* x15l[] = { "check_acl", 0 };
    const char x16s[] = "";      const char* x16l[] = { "allow_port", 0};
    const char x17s[] = "";      const char* x17l[] = { "allow_host", 0};
    const char x18s[] = "x";     const char* x18l[] = { "nice_exit", 0};
    const char x19s[] = "";      const char* x19l[] = { "allow_all_ports", 0};
    const char x20s[] = "";      const char* x20l[] = { "test_webserver", 0};
    const char x21s[] = "l";     const char* x21l[] = { "nabtolog", 0 };
    const char x22s[] = "A";     const char* x22l[] = { "controller", 0 };
    const char x23s[] = "";      const char* x23l[] = { "disable-tcp-fb", 0 };
    const char x24s[] = "";      const char* x24l[] = { "controller-port", 0 };

    const struct { int k; int f; const char *s; const char*const* l; } opts[] = {
        { 'h', GOPT_NOARG,   x1s, x1l },
        { 'V', GOPT_NOARG,   x2s, x2l },
        { 'C', GOPT_NOARG,   x3s, x3l },
        { 'S', GOPT_NOARG,   x4s, x4l },
        { 'd', GOPT_ARG,     x9s, x9l },
        { 'H', GOPT_ARG,     x10s, x10l },
        { 'P', GOPT_ARG,     x11s, x11l },
        { 's', GOPT_NOARG,   x12s, x12l },
        { 'k', GOPT_ARG,     x13s, x13l },
        { 'p', GOPT_ARG,     x14s, x14l },
        { 'a', GOPT_NOARG,   x15s, x15l },
        { ALLOW_PORT_OPTION, GOPT_REPEAT|GOPT_ARG, x16s, x16l },
        { ALLOW_HOST_OPTION, GOPT_REPEAT|GOPT_ARG, x17s, x17l },
        { 'x', GOPT_NOARG, x18s, x18l },
        { ALLOW_ALL_PORTS_OPTION, GOPT_NOARG, x19s, x19l },
        { TEST_WEBSERVER_OPTION, GOPT_ARG, x20s, x20l },
        { 'l', GOPT_REPEAT|GOPT_ARG,  x21s, x21l },
        { 'A', GOPT_ARG, x22s, x22l },
        { DISABLE_TCP_FALLBACK_OPTION, GOPT_NOARG, x23s, x23l },
        { CONTROLLER_PORT_OPTION, GOPT_ARG, x24s, x24l },
        { 0,0,0,0 }
    };

    void *options = gopt_sort( & argc, (const char**)argv, opts);

    const char * h;
    int p;
    const char* localPortStr;
    const char* optionString;
    const char* basestationAddress;
    const char* controllerPort;
    uint32_t addr;


    if (gopt(options, 'h')) {
        printf("Usage: unabto_tunnel [options] -d devicename\n");
        printf("  -h, --help                  Print this help.\n");
        printf("  -V, --version               Print version.\n");
        printf("  -C, --config                Print configuration (unabto_config.h).\n");
        printf("  -S, --size                  Print size (in bytes) of memory usage.\n");
        printf("  -l, --nabtolog              Speficy log level such as *.trace");
        printf("  -d, --deviceName            Specify name of this device.\n");
        printf("  -H, --tunnel_default_host   Set default host name for tunnel (%s).\n", DEFAULT_HOST);
        printf("  -P, --tunnel_default_port   Set default port for tunnel (%u).\n", DEFAULT_PORT);
        printf("  -s, --use_encryption        Encrypt communication (use CRYPTO).\n");
        printf("  -k, --encryption_key        Specify encryption key.\n");
        printf("  -p, --localport             Specify port for local connections.\n");
        printf("  -A, --controller            Specify controller address\n");
        printf("      --controller-port       sets the controller port number");
        printf("  -a, --check_acl             Perform ACL check when establishing connection.\n");
        printf("      --allow_all_ports       Allow connections to all port numbers.\n");
        printf("      --allow_port            Ports that are allowed. Requires -a.\n");
        printf("      --allow_host            Hostnames that are allowed. Requires -a.\n");
        printf("  -x, --nice_exit             Close the tunnels nicely when pressing Ctrl+C.\n");
#if USE_TEST_WEBSERVER
        printf("      --test_webserver        Specify port of test webserver and enable it\n");
#endif
        printf("      --disable-tcp-fb        disable tcp fallback");
        exit(0);
    }

    if (gopt(options, 'V')) {
        printf("%d.%d\n", RELEASE_MAJOR, RELEASE_MINOR);
        exit(0);
    }

    if (gopt(options, 'C')) {
        unabto_printf_unabto_config(stdout, "unabto_tunnel");
        exit(0);
    }

    if (gopt(options, 'S')) {
        unabto_printf_memory_sizes(stdout, "unabto_tunnel");
        exit(0);
    }
    
    { 
        size_t optionsLength = gopt(options, 'l');
        int i;
        if (optionsLength > 0) {
            for (i = 0; i < optionsLength; i++) {
                optionString = gopt_arg_i(options, 'l', i);
                if (!unabto_log_system_enable_stdout_pattern(optionString)) {
                    NABTO_LOG_FATAL(("Logstring %s is not a valid logsetting", optionString));
                }
            }
        } else {
            unabto_log_system_enable_stdout_pattern("*.info");
        }
        
    } 
    

    if (!gopt_arg( options, 'd', &nms->id)) {
        NABTO_LOG_FATAL(("Specify a serverId with -d. Try -h for help."));
    }

    if(gopt_arg(options, 'H', &h)) {
        tunnel_set_default_host(h);
    }

    if (gopt_arg(options, 'P', &tunnel_port_str)) {
        if(1 != sscanf(tunnel_port_str, "%d", &p)) {
            NABTO_LOG_FATAL(("Reading of port parameter failed."));
        } else {
            tunnel_set_default_port(p);
        }
    }
     
    if( gopt_arg( options, 'p', &localPortStr) ){
        int localPort = atoi(localPortStr);
        nms->localPort = localPort;
    }


    if (gopt(options, 's')) {
        const char* preSharedKey;
        uint8_t key[16];
        memset(key, 0, 16);
        if ( gopt_arg( options, 'k', &preSharedKey)) {
            size_t i;
            size_t pskLen = strlen(preSharedKey);
            // read the pre shared key as a hexadecimal string.
            for (i = 0; i < pskLen/2 && i < 16; i++) {
                sscanf(preSharedKey+(2*i), "%02hhx", &key[i]);
            }
        }
        memcpy(nms->presharedKey,key,16);
        nms->cryptoSuite = CRYPT_W_AES_CBC_HMAC_SHA256;
        nms->secureAttach = true;
        nms->secureData = true;
    }

    if (gopt(options, 'a')) {
        check_acl = true;
    }

    if( gopt_arg( options, 'A', & basestationAddress ) ){
        addr = inet_addr(basestationAddress);
        if (addr == INADDR_NONE) {
            NABTO_LOG_FATAL(("Invalid basestation address"));
        }
        nms->controllerArg.addr = htonl(addr);
    }

    if (gopt(options, 'x')) {
        nice_exit = true;
    }

    ports_length = gopt(options, ALLOW_PORT_OPTION);
    if (ports_length > 0) {
        size_t i;
        ports = (uint16_t*) malloc(ports_length*sizeof(uint16_t));
        memset(ports,0,ports_length*sizeof(uint16_t));
        for (i = 0; i < ports_length; i++) {
            const char* opt = gopt_arg_i(options, ALLOW_PORT_OPTION, i);
            ports[i] = atoi(opt);
        }
    }
    
    hosts_length = gopt(options, ALLOW_HOST_OPTION);
    if (hosts_length > 0) {
        size_t i;
        hosts = (char**) malloc(hosts_length*sizeof(char*));
        for (i = 0; i < hosts_length; i++) {
            const char* opt = gopt_arg_i(options, ALLOW_HOST_OPTION, i);
            hosts[i] = strdup(opt);
        }
    }

    if (gopt(options, ALLOW_ALL_PORTS_OPTION)) {
        allow_all_ports = true;
    }

#if USE_TEST_WEBSERVER
    if (gopt_arg(options, TEST_WEBSERVER_OPTION, &testWebserverPortStr)) {
        testWebserver = true;
    }
#endif

#if NABTO_ENABLE_TCP_FALLBACK
    if (gopt(options, DISABLE_TCP_FALLBACK_OPTION)) {
        nms->enableTcpFallback = false;
    }
#endif

    if (gopt_arg(options, CONTROLLER_PORT_OPTION, &controllerPort)) {
        nms->controllerArg.port = atoi(controllerPort);
    }

    return true;
}