summaryrefslogtreecommitdiff
path: root/plugins/telnet/telnet_config.c
blob: d154f887b028c3f261c1d89689c993a4e551926f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "hybbx/telnet.h"
#include "hybbx/util.h"

#include <stdlib.h>
#include <string.h>

static unsigned int parse_port(const char *value)
{
    char *end;
    unsigned long port;

    if (value == NULL || value[0] == '\0') {
        return HYBBX_TELNET_DEFAULT_PORT;
    }

    port = strtoul(value, &end, 10);
    if (end == value || *end != '\0' || port == 0 || port > 65535u) {
        return HYBBX_TELNET_DEFAULT_PORT;
    }

    return (unsigned int)port;
}

static const char *find_kv(const char *config, const char *key,
                           char *scratch, size_t scratch_len)
{
    const char *cursor = config;
    size_t key_len = strlen(key);

    if (config == NULL || key == NULL) {
        return NULL;
    }

    while (*cursor != '\0') {
        const char *sep = strchr(cursor, ';');
        const char *end = sep != NULL ? sep : cursor + strlen(cursor);
        const char *eq = strchr(cursor, '=');

        if (eq != NULL && eq < end && (size_t)(eq - cursor) == key_len &&
            strncmp(cursor, key, key_len) == 0) {
            const char *value = eq + 1;
            size_t value_len = (size_t)(end - value);

            if (scratch != NULL && scratch_len > 0) {
                if (value_len >= scratch_len) {
                    value_len = scratch_len - 1;
                }
                memcpy(scratch, value, value_len);
                scratch[value_len] = '\0';
                return scratch;
            }

            return value;
        }

        if (sep == NULL) {
            break;
        }
        cursor = sep + 1;
    }

    return NULL;
}

void hybbx_telnet_config_defaults(hybbx_telnet_config_t *config)
{
    if (config == NULL) {
        return;
    }

    memset(config, 0, sizeof(*config));
    hybbx_strlcpy(config->bind_v4, HYBBX_TELNET_DEFAULT_BIND_V4,
                  sizeof(config->bind_v4));
    hybbx_strlcpy(config->bind_v6, HYBBX_TELNET_DEFAULT_BIND_V6,
                  sizeof(config->bind_v6));
    config->port = HYBBX_TELNET_DEFAULT_PORT;
    config->ipv4 = 1;
    config->ipv6 = 1;
}

hybbx_result_t hybbx_telnet_config_parse(const char *config,
                                         hybbx_telnet_config_t *out)
{
    char scratch[HYBBX_TELNET_BIND_V6_MAX];
    const char *value;

    if (out == NULL) {
        return HYBBX_ERR_INVALID;
    }

    hybbx_telnet_config_defaults(out);

    if (config == NULL || config[0] == '\0') {
        return HYBBX_OK;
    }

    value = find_kv(config, "port", scratch, sizeof(scratch));
    out->port = parse_port(value);

    value = find_kv(config, "bind", scratch, sizeof(scratch));
    if (value != NULL && value[0] != '\0') {
        if (strchr(value, ':') != NULL) {
            hybbx_strlcpy(out->bind_v6, value, sizeof(out->bind_v6));
        } else {
            hybbx_strlcpy(out->bind_v4, value, sizeof(out->bind_v4));
        }
    }

    value = find_kv(config, "bind6", scratch, sizeof(scratch));
    if (value != NULL && value[0] != '\0') {
        hybbx_strlcpy(out->bind_v6, value, sizeof(out->bind_v6));
    }

    value = find_kv(config, "ipv4", scratch, sizeof(scratch));
    if (value != NULL) {
        out->ipv4 = hybbx_parse_bool(value, 1);
    }

    value = find_kv(config, "ipv6", scratch, sizeof(scratch));
    if (value != NULL) {
        out->ipv6 = hybbx_parse_bool(value, 1);
    }

    return HYBBX_OK;
}
git clone -b <branch> https://cgit.mode42.com/<repo>.git
git clone -b <branch> git://cgit.mode42.com/<repo>.git

info@mode42.com