From 65fd08a0d6173dcdeac8dd59a5df3c0d1abc0698 Mon Sep 17 00:00:00 2001 From: Suvendhu Hansa Date: Thu, 2 Jun 2022 08:27:07 +0000 Subject: [PATCH] JSON plugin: Add support for uci list --- dmdynamicjson.c | 80 ++++- gitlab-ci/tools-test.sh | 4 + libbbf_api/dmcommon.c | 25 ++ libbbf_api/dmcommon.h | 1 + test/files/etc/bbfdm/json/urlfilter.json | 385 +++++++++++++++++++++++ test/files/etc/config/urlfilter | 34 ++ tools/generate_dm_excel.py | 6 +- 7 files changed, 521 insertions(+), 14 deletions(-) create mode 100644 test/files/etc/bbfdm/json/urlfilter.json create mode 100644 test/files/etc/config/urlfilter diff --git a/dmdynamicjson.c b/dmdynamicjson.c index fc6617e5..4e795ebe 100644 --- a/dmdynamicjson.c +++ b/dmdynamicjson.c @@ -619,6 +619,8 @@ static char *uci_get_value(json_object *mapping_obj, int json_version, char *ref struct json_object *section_name = NULL; struct json_object *option = NULL; struct json_object *option_name = NULL; + struct json_object *list = NULL; + struct json_object *list_name = NULL; struct json_object *path = NULL; char *value = ""; @@ -629,11 +631,20 @@ static char *uci_get_value(json_object *mapping_obj, int json_version, char *ref json_object_object_get_ex(section, "name", §ion_name); json_object_object_get_ex(obj, "option", &option); json_object_object_get_ex(option, "name", &option_name); + json_object_object_get_ex(obj, "list", &list); + json_object_object_get_ex(list, "name", &list_name); json_object_object_get_ex(obj, "path", &path); - if (file && type && option_name && strstr(refparam, "NumberOfEntries")) { + char *opt_temp = NULL; + if (list_name) { + opt_temp = json_object_get_string(list_name); + } else if (option_name) { + opt_temp = json_object_get_string(option_name); + } - if (strcmp(json_object_get_string(option_name), "@Count") != 0 && json_version == JSON_VERSION_1) + if (file && type && opt_temp && strstr(refparam, "NumberOfEntries")) { + + if (strcmp(opt_temp, "@Count") != 0 && json_version == JSON_VERSION_1) goto end; struct uci_section *s = NULL; @@ -646,16 +657,28 @@ static char *uci_get_value(json_object *mapping_obj, int json_version, char *ref goto end; } - if (data && file && type && option_name) { - if (strcmp(json_object_get_string(option_name), "@Name") == 0) { + if (data && file && type && opt_temp) { + if (strcmp(opt_temp, "@Name") == 0) { dmasprintf(&value, "%s", section_name((struct uci_section *)data)); } else { char uci_type[32] = {0}; snprintf(uci_type, sizeof(uci_type), "@%s[%ld]", json_object_get_string(type), instance ? DM_STRTOL(instance)-1 : 0); - value = dmuci_get_value_by_path(json_object_get_string(path), json_object_get_string(file), uci_type, json_object_get_string(option_name)); + if (option) { + value = dmuci_get_value_by_path(json_object_get_string(path), json_object_get_string(file), uci_type, opt_temp); + } else { + struct uci_list *list_val; + dmuci_get_option_value_list(json_object_get_string(file), uci_type, opt_temp, &list_val); + value = dmuci_list_to_string(list_val, ","); + } + } + } else if (file && section_name && opt_temp) { + if (option) { + value = dmuci_get_value_by_path(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), opt_temp); + } else { + struct uci_list *list_val; + dmuci_get_option_value_list(json_object_get_string(file), json_object_get_string(section_name), opt_temp, &list_val); + value = dmuci_list_to_string(list_val, ","); } - } else if (file && section_name && option_name) { - value = dmuci_get_value_by_path(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), json_object_get_string(option_name)); } if (strstr(refparam, "Alias") && value[0] == '\0') @@ -1205,6 +1228,8 @@ static void uci_set_value(json_object *mapping_obj, int json_version, char *refp struct json_object *section_name = NULL; struct json_object *option = NULL; struct json_object *option_name = NULL; + struct json_object *list = NULL; + struct json_object *list_name = NULL; struct json_object *path = NULL; json_object_object_get_ex(mapping_obj, "uci", &uci_obj); @@ -1214,15 +1239,48 @@ static void uci_set_value(json_object *mapping_obj, int json_version, char *refp json_object_object_get_ex(section, "name", §ion_name); json_object_object_get_ex(uci_obj, "option", &option); json_object_object_get_ex(option, "name", &option_name); + json_object_object_get_ex(uci_obj, "list", &list); + json_object_object_get_ex(list, "name", &list_name); json_object_object_get_ex(uci_obj, "path", &path); - if (data && file && type && option_name) { + char *opt_temp = NULL; + if (list_name) { + opt_temp = json_object_get_string(list_name); + } else if (option_name) { + opt_temp = json_object_get_string(option_name); + } + + if (data && file && type && opt_temp) { char uci_type[32] = {0}; snprintf(uci_type, sizeof(uci_type), "@%s[%ld]", json_object_get_string(type), instance ? DM_STRTOL(instance)-1 : 0); - dmuci_set_value_by_path(json_object_get_string(path), json_object_get_string(file), uci_type, json_object_get_string(option_name), value); - } else if (file && section_name && option_name) { - dmuci_set_value_by_path(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), json_object_get_string(option_name), value); + if (option) { + dmuci_set_value_by_path(json_object_get_string(path), json_object_get_string(file), uci_type, opt_temp, value); + } else { + if (value != NULL) { + dmuci_delete(json_object_get_string(file), uci_type, opt_temp, NULL); + char *p = strtok(value, ","); + while (p) { + strip_lead_trail_whitespace(p); + dmuci_add_list_value(json_object_get_string(file), uci_type, opt_temp, p); + p = strtok(NULL, ","); + } + } + } + } else if (file && section_name && opt_temp) { + if (option) { + dmuci_set_value_by_path(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), opt_temp, value); + } else { + if (value != NULL) { + dmuci_delete(json_object_get_string(file), json_object_get_string(section_name), opt_temp, NULL); + char *p = strtok(value, ","); + while (p) { + strip_lead_trail_whitespace(p); + dmuci_add_list_value(json_object_get_string(file), json_object_get_string(section_name), opt_temp, p); + p = strtok(NULL, ","); + } + } + } } } diff --git a/gitlab-ci/tools-test.sh b/gitlab-ci/tools-test.sh index c2bc0c51..a03e51c5 100755 --- a/gitlab-ci/tools-test.sh +++ b/gitlab-ci/tools-test.sh @@ -45,6 +45,10 @@ echo "Validate X_IOPSYS_EU_WiFi JSON Plugin" ./tools/validate_json_plugin.py test/files/etc/bbfdm/json/X_IOPSYS_EU_WiFi.json check_ret $? +echo "Validate X_IOPSYS_EU_URLFilter JSON Plugin" +./tools/validate_json_plugin.py test/files/etc/bbfdm/json/urlfilter.json +check_ret $? + echo "Validate TR-181 JSON Plugin after generating from XML" json_path=$(./tools/convert_dm_xml_to_json.py test/tools/tr-181-2-15-0-cwmp-full.xml test/tools/tr-181-2-15-0-usp-full.xml Device.) ./tools/validate_json_plugin.py $json_path diff --git a/libbbf_api/dmcommon.c b/libbbf_api/dmcommon.c index a7c130ac..87c44f07 100644 --- a/libbbf_api/dmcommon.c +++ b/libbbf_api/dmcommon.c @@ -1718,6 +1718,31 @@ char *replace_str(const char *str, const char *substr, const char *replacement) return value; } +void strip_lead_trail_whitespace(char *str) +{ + if (str == NULL) + return; + + /* First remove leading whitespace */ + const char* first_valid = str; + + while (*first_valid == ' ') { + ++first_valid; + } + + size_t len = strlen(first_valid) + 1; + + memmove(str, first_valid, len); + + /* Now remove trailing whitespace */ + char* end_str = str + strlen(str) - 1; + + while (str < end_str && *end_str == ' ') { + *end_str = '\0'; + --end_str ; + } +} + int check_browse_section(struct uci_section *s, void *data) { struct browse_args *browse_args = (struct browse_args *)data; diff --git a/libbbf_api/dmcommon.h b/libbbf_api/dmcommon.h index 61d87898..544bba52 100644 --- a/libbbf_api/dmcommon.h +++ b/libbbf_api/dmcommon.h @@ -291,4 +291,5 @@ int parse_proc_intf6_line(const char *line, const char *device, char *ipstr, siz char *ioctl_get_ipv4(char *interface_name); char *get_ipv6(char *interface_name); bool validate_blob_message(struct blob_attr *src, struct blob_attr *dst); +void strip_lead_trail_whitespace(char *str); #endif diff --git a/test/files/etc/bbfdm/json/urlfilter.json b/test/files/etc/bbfdm/json/urlfilter.json new file mode 100644 index 00000000..64906bc1 --- /dev/null +++ b/test/files/etc/bbfdm/json/urlfilter.json @@ -0,0 +1,385 @@ +{ + "json_plugin_version": 1, + "Device.X_IOPSYS_EU_URLFilter.": { + "type": "object", + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "access": false, + "array": false, + "Enable": { + "type": "boolean", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "name": "globals" + }, + "option": { + "name": "enable" + } + } + } + ] + }, + "GlobalBlacklist": { + "type": "boolean", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "name": "globals" + }, + "option": { + "name": "global_blacklist" + } + } + } + ] + }, + "BlacklistURL": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "list": { + "datatype": "string" + }, + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "name": "globals" + }, + "list": { + "name": "blacklist_url" + } + } + } + ] + }, + "ProfileNumberOfEntries": { + "type": "unsignedInt", + "read": true, + "write": false, + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "profile" + }, + "option": { + "name": "@Count" + } + } + } + ] + }, + "Device.X_IOPSYS_EU_URLFilter.Profile.{i}.": { + "type": "object", + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "access": true, + "array": true, + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "profile" + }, + "dmmapfile": "dmmap_urlfilter_profile" + } + } + ], + "WhitelistURL": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "list": { + "datatype": "string" + }, + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "profile" + }, + "list": { + "name": "whitelist_url" + } + } + } + ] + }, + "BlacklistURL": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "list": { + "datatype": "string" + }, + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "profile" + }, + "list": { + "name": "blacklist_url" + } + } + } + ] + } + }, + "FilterNumberOfEntries": { + "type": "unsignedInt", + "read": true, + "write": false, + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "filter" + }, + "option": { + "name": "@Count" + } + } + } + ] + }, + "Device.X_IOPSYS_EU_URLFilter.Filter.{i}.": { + "type": "object", + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "access": true, + "array": true, + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "filter" + }, + "dmmapfile": "dmmap_urlfilter_filter" + } + } + ], + "Enable": { + "type": "boolean", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "filter" + }, + "option": { + "name": "enable" + } + } + } + ] + }, + "Profile": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "filter" + }, + "option": { + "name": "profile" + } + } + } + ] + }, + "MacAddress": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "list": { + "datatype": "string" + }, + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "filter" + }, + "list": { + "name": "macaddr" + } + } + } + ] + }, + "Day": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "list": { + "datatype": "string" + }, + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "filter" + }, + "list": { + "name": "day" + } + } + } + ] + }, + "StartTime": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "filter" + }, + "option": { + "name": "start_time" + } + } + } + ] + }, + "Duration": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "filter" + }, + "option": { + "name": "duration" + } + } + } + ] + } + } + } +} + diff --git a/test/files/etc/config/urlfilter b/test/files/etc/config/urlfilter new file mode 100644 index 00000000..26767c5a --- /dev/null +++ b/test/files/etc/config/urlfilter @@ -0,0 +1,34 @@ +config globals 'globals' + option enable '1' + option global_blacklist '1' + list blacklist_url 'abc.com' + list blacklist_url 'def.com' + list blacklist_url 'facebook.com' + list blacklist_url 'instagram.com' + +config profile 'homeoffice' + list whitelist_url 'facebook.com' + list whitelist_url 'instagram.com' + +config profile 'kids' + list blacklist_url 'youtube.com' + list blacklist_url 'game.com' + +config filter 'f1' + option enable '1' + option profile 'kids' + list macaddr '00:11:22:33:44:55' + list macaddr 'AA:BB:CC:33:44:55' + list day 'Monday' + list day 'Tuesday' + list day 'Wednesday' + list day 'Thursday' + list day 'Friday' + option start_time '20:00' + option duration '64800' + +config filter 'f2' + option enable '1' + option profile 'homeoffice' + list macaddr 'CC:DD:EE:33:44:55' + list macaddr 'EE:AA:BB:11:22:33' diff --git a/tools/generate_dm_excel.py b/tools/generate_dm_excel.py index 6af21b52..dee6c65e 100755 --- a/tools/generate_dm_excel.py +++ b/tools/generate_dm_excel.py @@ -141,7 +141,7 @@ def generate_excel_file(output_file): wb.set_colour_RGB(0x30, 153, 153, 153) style_title = xlwt.easyxf( - 'pattern: pattern solid, fore_colour custom_colour_grey;''font: bold 1, color black;''alignment: horizontal center;') + 'pattern: pattern solid, fore_colour custom_colour_grey;' + 'font: bold 1, color black;' + 'alignment: horizontal center;') sheet.write(0, 0, 'OBJ/PARAM/OPERATE', style_title) sheet.write(0, 1, 'Protocols', style_title) sheet.write(0, 2, 'Supported', style_title) @@ -155,12 +155,12 @@ def generate_excel_file(output_file): style_name = xlwt.easyxf( 'pattern: pattern solid, fore_colour custom_colour_yellow') style = xlwt.easyxf( - 'pattern: pattern solid, fore_colour custom_colour_yellow;''alignment: horizontal center;') + 'pattern: pattern solid, fore_colour custom_colour_yellow;' + 'alignment: horizontal center;') elif param[3] == "operate" or param[3] == "event": style_name = xlwt.easyxf( 'pattern: pattern solid, fore_colour custom_colour_green') style = xlwt.easyxf( - 'pattern: pattern solid, fore_colour custom_colour_green;''alignment: horizontal center;') + 'pattern: pattern solid, fore_colour custom_colour_green;' + 'alignment: horizontal center;') else: style_name = None style = xlwt.easyxf('alignment: horizontal center;')