summaryrefslogtreecommitdiffstats
path: root/src/feature.c
blob: 0edf9433aca96dde80c26e03e5c6062220048664 (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* Copyright (C) 2019 Open Information Security Foundation
 *
 * You can copy, redistribute or modify this Program under the terms of
 * the GNU General Public License version 2 as published by the Free
 * Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * version 2 along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

/**
 * \file
 *
 * \author Jeff Lucovsky <jeff@lucovsky.org>
 *
 * Implements feature tracking
 */

#include "suricata-common.h"
#include "feature.h"
#include "threads.h"

#include "util-debug.h"
#include "util-hashlist.h"

typedef struct FeatureEntryType {
	const char *feature;
} FeatureEntryType;

static SCMutex feature_table_mutex = SCMUTEX_INITIALIZER;
static HashListTable *feature_hash_table;

static uint32_t FeatureHashFunc(HashListTable *ht, void *data,
                                uint16_t datalen)
{
    FeatureEntryType *f = (FeatureEntryType *)data;
    uint32_t hash = 0;
    int len = strlen(f->feature);

    for (int i = 0; i < len; i++)
        hash += u8_tolower((unsigned char)f->feature[i]);

    return (hash % ht->array_size);
}

static char FeatureHashCompareFunc(void *data1, uint16_t datalen1,
                                   void *data2, uint16_t datalen2)
{
    FeatureEntryType *f1 = (FeatureEntryType *)data1;
    FeatureEntryType *f2 = (FeatureEntryType *)data2;
    int len1 = 0;
    int len2 = 0;

    if (f1 == NULL || f2 == NULL)
        return 0;

    if (f1->feature == NULL || f2->feature == NULL)
        return 0;

    len1 = strlen(f1->feature);
    len2 = strlen(f2->feature);

    return (len1 == len2 && memcmp(f1->feature, f2->feature, len1) == 0);
}

static void FeatureHashFreeFunc(void *data)
{
    FeatureEntryType *f = data;
    if (f->feature) {
        SCFree((void *)f->feature);
    }
    SCFree(data);
}

static void FeatureInit(void) {
    feature_hash_table = HashListTableInit(256, FeatureHashFunc,
                                           FeatureHashCompareFunc,
                                           FeatureHashFreeFunc);

    if (!feature_hash_table) {
        FatalError("Unable to allocate feature hash table.");
    }
}

static void FeatureAddEntry(const char *feature_name)
{
    int rc;

    FeatureEntryType *feature = SCCalloc(1, sizeof(*feature));
    if (!feature) {
        FatalError("Unable to allocate feature entry memory.");
    }

    feature->feature = SCStrdup(feature_name);
    if (feature->feature) {
        rc = HashListTableAdd(feature_hash_table, feature, sizeof(*feature));
        if (rc == 0)
            return;
    }

    FeatureHashFreeFunc(feature);
}

void ProvidesFeature(const char *feature_name)
{
    FeatureEntryType f = { feature_name };

    SCMutexLock(&feature_table_mutex);

    FeatureEntryType *feature = HashListTableLookup(feature_hash_table, &f, sizeof(f));

    if (!feature) {
        FeatureAddEntry(feature_name);
    }

    SCMutexUnlock(&feature_table_mutex);
}

bool RequiresFeature(const char *feature_name)
{
    FeatureEntryType f = { feature_name };

    SCMutexLock(&feature_table_mutex);
    FeatureEntryType *feature = HashListTableLookup(feature_hash_table, &f, sizeof(f));
    SCMutexUnlock(&feature_table_mutex);
    return feature != NULL;
}

void FeatureTrackingRelease(void)
{
    if (feature_hash_table != NULL) {
        HashListTableFree(feature_hash_table);
        feature_hash_table = NULL;
    }
}

void FeatureDump(void)
{
    HashListTableBucket *hb = HashListTableGetListHead(feature_hash_table);
    for (; hb != NULL; hb = HashListTableGetListNext(hb)) {
        FeatureEntryType *f = HashListTableGetListData(hb);
        printf("provided feature name: %s\n", f->feature);
    }
}
void FeatureTrackingRegister(void)
{
    FeatureInit();
}