1/*
2Copyright (C) 2020 Derry <destan19@126.com>
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"), to deal
6in the Software without restriction, including without limitation the rights
7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20THE SOFTWARE.
21*/
22#include <stdio.h>
23#include <string.h>
24#include <stdlib.h>
25#include "appfilter_config.h"
26#include <uci.h>
27
28app_name_info_t app_name_table[MAX_SUPPORT_APP_NUM];
29int g_app_count = 0;
30int g_cur_class_num = 0;
31char CLASS_NAME_TABLE[MAX_APP_TYPE][MAX_CLASS_NAME_LEN];
32
33const char *config_path = "./config";
34static struct uci_context *uci_ctx = NULL;
35static struct uci_package *uci_appfilter;
36
37
38int uci_get_int_value(struct uci_context *ctx, char *key)
39{
40    struct uci_element *e;
41    struct uci_ptr ptr;
42    int ret = -1;
43    int dummy;
44    char *parameters ;
45    char param_tmp[128] = {0};
46    strcpy(param_tmp, key);
47    if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
48        return ret;
49    }
50
51    if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
52        ctx->err = UCI_ERR_NOTFOUND;
53        goto done;
54    }
55
56    e = ptr.last;
57    switch(e->type) {
58        case UCI_TYPE_SECTION:
59            ret = -1;
60			goto done;
61        case UCI_TYPE_OPTION:
62            ret = atoi(ptr.o->v.string);
63			goto done;
64        default:
65            break;
66    }
67done:
68
69	if (ptr.p)
70		uci_unload(ctx, ptr.p);
71    return ret;
72}
73
74
75int uci_get_value(struct uci_context *ctx, char *key, char *output, int out_len)
76{
77    struct uci_element *e;
78    struct uci_ptr ptr;
79    int ret = UCI_OK;
80    int dummy;
81    char *parameters ;
82    char param_tmp[128] = {0};
83    strcpy(param_tmp, key);
84    if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
85        ret = 1;
86        return ret;
87    }
88
89    if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
90        ctx->err = UCI_ERR_NOTFOUND;
91        ret = 1;
92        goto done;
93    }
94
95    e = ptr.last;
96    switch(e->type) {
97        case UCI_TYPE_SECTION:
98            snprintf(output, out_len, "%s", ptr.s->type);
99            break;
100        case UCI_TYPE_OPTION:
101            snprintf(output, out_len, "%s", ptr.o->v.string);
102			break;
103        default:
104			ret = 1;
105            break;
106    }
107done:
108	if (ptr.p)
109		uci_unload(ctx, ptr.p);
110    return ret;
111}
112
113//
114static struct uci_package *
115config_init_package(const char *config)
116{
117    struct uci_context *ctx = uci_ctx;
118    struct uci_package *p = NULL;
119
120    if (!ctx)
121    {
122        ctx = uci_alloc_context();
123        uci_ctx = ctx;
124        ctx->flags &= ~UCI_FLAG_STRICT;
125        //if (config_path)
126        //	uci_set_confdir(ctx, config_path);
127    }
128    else
129    {
130        p = uci_lookup_package(ctx, config);
131        if (p)
132            uci_unload(ctx, p);
133    }
134
135    if (uci_load(ctx, config, &p))
136        return NULL;
137
138    return p;
139}
140char *get_app_name_by_id(int id)
141{
142    int i;
143    for (i = 0; i < g_app_count; i++)
144    {
145        if (id == app_name_table[i].id)
146            return app_name_table[i].name;
147    }
148    return "";
149}
150
151void init_app_name_table(void)
152{
153    int count = 0;
154    char line_buf[2048] = {0};
155
156    FILE *fp = fopen("/tmp/feature.cfg", "r");
157    if (!fp)
158    {
159        printf("open file failed\n");
160        return;
161    }
162
163    while (fgets(line_buf, sizeof(line_buf), fp))
164    {
165        if (strstr(line_buf, "#"))
166            continue;
167        if (strlen(line_buf) < 10)
168            continue;
169        if (!strstr(line_buf, ":"))
170            continue;
171        char *pos1 = strstr(line_buf, ":");
172        char app_info_buf[128] = {0};
173        int app_id;
174        char app_name[64] = {0};
175        memset(app_name, 0x0, sizeof(app_name));
176        strncpy(app_info_buf, line_buf, pos1 - line_buf);
177        sscanf(app_info_buf, "%d %s", &app_id, app_name);
178        app_name_table[g_app_count].id = app_id;
179        strcpy(app_name_table[g_app_count].name, app_name);
180        g_app_count++;
181    }
182    fclose(fp);
183}
184
185void init_app_class_name_table(void)
186{
187    char line_buf[2048] = {0};
188    int class_id;
189    char class_name[64] = {0};
190    FILE *fp = fopen("/tmp/app_class.txt", "r");
191    if (!fp)
192    {
193        printf("open file failed\n");
194        return;
195    }
196    while (fgets(line_buf, sizeof(line_buf), fp))
197    {
198        sscanf(line_buf, "%d %*s %s", &class_id, class_name);
199        strcpy(CLASS_NAME_TABLE[class_id - 1], class_name);
200        g_cur_class_num++;
201    }
202    fclose(fp);
203}
204//00:00 9:1
205int check_time_valid(char *t)
206{
207    if (!t)
208        return 0;
209    if (strlen(t) < 3 || strlen(t) > 5 || (!strstr(t, ":")))
210        return 0;
211    else
212        return 1;
213}
214
215void dump_af_time(af_ctl_time_t *t)
216{
217    int i;
218    printf("---------dump af time-------------\n");
219    printf("%d:%d ---->%d:%d\n", t->start.hour, t->start.min,
220           t->end.hour, t->end.min);
221    for (i = 0; i < 7; i++)
222    {
223        printf("%d ", t->days[i]);
224    }
225    printf("\n");
226}
227
228af_ctl_time_t *load_appfilter_ctl_time_config(void)
229{
230    char start_time_str[64] = {0};
231    char end_time_str[64] = {0};
232    char start_time_str2[64] = {0};
233    char end_time_str2[64] = {0};
234    char days_str[64] = {0};
235    int value = 0;
236    int ret = 0;
237    af_ctl_time_t *t = NULL;
238    struct uci_context *ctx = uci_alloc_context();
239    if (!ctx)
240        return NULL;
241
242    memset(start_time_str, 0x0, sizeof(start_time_str));
243    memset(end_time_str, 0x0, sizeof(end_time_str));
244    memset(start_time_str2, 0x0, sizeof(start_time_str2));
245    memset(end_time_str2, 0x0, sizeof(end_time_str2));
246
247    uci_get_value(ctx, "appfilter.time.start_time", start_time_str, sizeof(start_time_str));
248    uci_get_value(ctx, "appfilter.time.end_time", end_time_str, sizeof(end_time_str));
249    uci_get_value(ctx, "appfilter.time.start_time2", start_time_str2, sizeof(start_time_str2));
250    uci_get_value(ctx, "appfilter.time.end_time2", end_time_str2, sizeof(end_time_str2));
251    uci_get_value(ctx, "appfilter.time.days", days_str, sizeof(days_str));
252
253
254    t = malloc(sizeof(af_ctl_time_t));
255
256    value = uci_get_int_value(ctx, "appfilter.time.time_mode");
257    if (value < 0)
258        t->time_mode = 0;
259    else
260        t->time_mode = value;
261    if (check_time_valid(start_time_str) && check_time_valid(end_time_str)){
262        sscanf(start_time_str, "%d:%d", &t->start.hour, &t->start.min);
263        sscanf(end_time_str, "%d:%d", &t->end.hour, &t->end.min);
264    }
265    if (check_time_valid(start_time_str2) && check_time_valid(end_time_str2)){
266        sscanf(start_time_str2, "%d:%d", &t->start2.hour, &t->start2.min);
267        sscanf(end_time_str2, "%d:%d", &t->end2.hour, &t->end2.min);
268    }
269
270    char *p = strtok(days_str, " ");
271    if (!p)
272        goto EXIT;
273    do
274    {
275        int day = atoi(p);
276        if (day >= 0 && day <= 6)
277            t->days[day] = 1;
278        else
279            ret = 0;
280    } while (p = strtok(NULL, " "));
281EXIT:
282	uci_free_context(ctx);
283    return t;
284}
285
286
287
288int config_get_appfilter_enable(void)
289{
290    int enable = 0;
291    struct uci_context *ctx = uci_alloc_context();
292    if (!ctx)
293        return NULL;
294	enable = uci_get_int_value(ctx, "appfilter.global.enable");
295    if (enable < 0)
296        enable = 0;
297
298	uci_free_context(ctx);
299    return enable;
300}
301
302int config_get_lan_ip(char *lan_ip, int len)
303{
304    int ret = 0;
305    struct uci_context *ctx = uci_alloc_context();
306    if (!ctx)
307        return -1;
308    ret = uci_get_value(ctx, "network.lan.ipaddr", lan_ip, len);
309    uci_free_context(ctx);
310    return ret;
311}
312
313int config_get_lan_mask(char *lan_mask, int len)
314{
315    int ret = 0;
316    struct uci_context *ctx = uci_alloc_context();
317    if (!ctx)
318        return -1;
319    ret = uci_get_value(ctx, "network.lan.netmask", lan_mask, len);
320    uci_free_context(ctx);
321    return ret;
322}
323
324
325int appfilter_config_alloc(void)
326{
327    char *err;
328    uci_appfilter = config_init_package("appfilter");
329    if (!uci_appfilter)
330    {
331        uci_get_errorstr(uci_ctx, &err, NULL);
332        printf("Failed to load appfilter config (%s)\n", err);
333        free(err);
334        return -1;
335    }
336
337    return 0;
338}
339
340int appfilter_config_free(void)
341{
342    if (uci_appfilter)
343    {
344        uci_unload(uci_ctx, uci_appfilter);
345        uci_appfilter = NULL;
346    }
347    if (uci_ctx)
348    {
349        uci_free_context(uci_ctx);
350        uci_ctx = NULL;
351    }
352}
353