From b449b119a5fe7d9dc675c4694da3480be4a3f938 Mon Sep 17 00:00:00 2001 From: Suvendhu Hansa Date: Thu, 28 Jul 2022 16:10:07 +0000 Subject: [PATCH] Added support of ManageableDevice & GatewayInfo objects --- dmtree/tr181/device.c | 2 + dmtree/tr181/gatewayinfo.c | 122 ++++++++++++ dmtree/tr181/gatewayinfo.h | 20 ++ dmtree/tr181/hosts.c | 2 +- dmtree/tr181/managementserver.c | 181 ++++++++++++++++++ dmtree/tr181/managementserver.h | 1 + dmtree/vendor/iopsys/tr181/x_iopsys_eu_igmp.c | 24 ++- gitlab-ci/memory-test.sh | 3 +- test/files/tmp/dhcp.leases | 2 +- test/files/tmp/interface_wan.data | 4 +- test/files/var/dhcp.client.options | 2 +- 11 files changed, 357 insertions(+), 6 deletions(-) create mode 100644 dmtree/tr181/gatewayinfo.c create mode 100644 dmtree/tr181/gatewayinfo.h diff --git a/dmtree/tr181/device.c b/dmtree/tr181/device.c index 40af9463..bb756b27 100644 --- a/dmtree/tr181/device.c +++ b/dmtree/tr181/device.c @@ -41,6 +41,7 @@ #include "security.h" #include "ieee1905.h" #include "routeradvertisement.h" +#include "gatewayinfo.h" #ifdef BBF_TR104 #include "servicesvoiceservice.h" #endif @@ -122,6 +123,7 @@ DMOBJ tDeviceObj[] = { #ifdef BBF_TR104 {"Services", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tServicesObj, NULL, NULL, BBFDM_BOTH, NULL, "2.0"}, #endif +{"GatewayInfo", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tGatewayInfoParams, NULL, BBFDM_CWMP, NULL, "2.0"}, {0} }; diff --git a/dmtree/tr181/gatewayinfo.c b/dmtree/tr181/gatewayinfo.c new file mode 100644 index 00000000..b344d082 --- /dev/null +++ b/dmtree/tr181/gatewayinfo.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2022 iopsys Software Solutions AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * Author: Suvendhu Hansa + */ + +#include "gatewayinfo.h" +#include "dmbbfcommon.h" + +enum gateway_param { + E_OUI, + E_SERIAL, + E_CLASS +}; + +static void get_gateway_params(int param, char *dst, int size) +{ + char *interface = NULL, *vivso = NULL, search[3] = {0}; + json_object *res = NULL; + + if (dst == NULL) + return; + + switch (param) { + case E_OUI: + if (2 != snprintf(search, sizeof(search), "4=")) + return; + + break; + case E_SERIAL: + if (2 != snprintf(search, sizeof(search), "5=")) + return; + + break; + case E_CLASS: + if (2 != snprintf(search, sizeof(search), "6=")) + return; + + break; + default: + return; + } + + + dmuci_get_option_value_string("cwmp", "cpe", "default_wan_interface", &interface); + if (DM_STRLEN(interface) == 0) + return; + + dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res); + if (!res) + return; + + vivso = dmjson_get_value(res, 2, "data", "vivsoinf"); + int len = DM_STRLEN(vivso); + if (len == 0) + return; + + char value[len + 1]; + memset(value, 0, sizeof(value)); + snprintf(value, len+1, "%s", vivso); + + char *temp = strtok(value, ","); + while (temp) { + if (DM_STRNCMP(temp, search, 2) != 0) { + temp = strtok(NULL, ","); + continue; + } + + temp = temp + 2; + snprintf(dst, size, "%s", temp); + return; + } + + return; +} + +static int get_manufacturer_oui(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char oui[7] = {0}; + + get_gateway_params(E_OUI, oui, sizeof(oui)); + *value = dmstrdup(oui); + + return 0; +} + +static int get_product_class(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char class[65] = {0}; + + get_gateway_params(E_CLASS, class, sizeof(class)); + *value = dmstrdup(class); + + return 0; +} + +static int get_serial_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char serial[65] = {0}; + + get_gateway_params(E_SERIAL, serial, sizeof(serial)); + *value = dmstrdup(serial); + + return 0; +} + +/********************************************************************************************************************************** +* OBJ & PARAM DEFINITION +***********************************************************************************************************************************/ +/* *** Device.GatewayInfo. *** */ +DMLEAF tGatewayInfoParams[] = { +/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ +{"ManufacturerOUI", &DMREAD, DMT_STRING, get_manufacturer_oui, NULL, BBFDM_CWMP, "2.0"}, +{"ProductClass", &DMREAD, DMT_STRING, get_product_class, NULL, BBFDM_CWMP, "2.0"}, +{"SerialNumber", &DMREAD, DMT_STRING, get_serial_number, NULL, BBFDM_CWMP, "2.0"}, +{0} +}; + diff --git a/dmtree/tr181/gatewayinfo.h b/dmtree/tr181/gatewayinfo.h new file mode 100644 index 00000000..cb27dc9f --- /dev/null +++ b/dmtree/tr181/gatewayinfo.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2022 iopsys Software Solutions AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * Author Suvendhu Hansa + * + */ + +#ifndef __GATEWAYINFO_H +#define __GATEWAYINFO_H + +#include "libbbf_api/dmcommon.h" + +extern DMLEAF tGatewayInfoParams[]; + +#endif + diff --git a/dmtree/tr181/hosts.c b/dmtree/tr181/hosts.c index 2f2a702f..1822a03b 100644 --- a/dmtree/tr181/hosts.c +++ b/dmtree/tr181/hosts.c @@ -64,7 +64,7 @@ static int browseHostsHostIPv6AddressInst(struct dmctx *dmctx, DMNODE *parent_no **************************************************************/ static int get_linker_host(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker) { - *linker = dmjson_get_value((json_object *)data, 1, "ipaddr"); + *linker = dmjson_get_value((json_object *)data, 1, "macaddr"); return 0; } diff --git a/dmtree/tr181/managementserver.c b/dmtree/tr181/managementserver.c index e85db0a0..91573f73 100644 --- a/dmtree/tr181/managementserver.c +++ b/dmtree/tr181/managementserver.c @@ -16,6 +16,143 @@ char *CWMP_EVENTS[] = {"0 BOOTSTRAP", "1 BOOT", "2 PERIODIC", "3 SCHEDULED", "5 KICKED", "6 CONNECTION REQUEST", "7 TRANSFER COMPLETE", "8 DIAGNOSTICS COMPLETE", "9 REQUEST DOWNLOAD", "10 AUTONOMOUS TRANSFER COMPLETE", "11 DU STATE CHANGE COMPLETE", "M Reboot", "M ScheduleInform", "M Download", "M ScheduleDownload", "M Upload", "M ChangeDUState", "14 HEARTBEAT"}; +enum suboption_125 { + OPT_OUI, + OPT_SERIAL, + OPT_CLASS +}; + +struct manageable_device_args { + char mac[18]; + char oui[7]; + char serial[65]; + char class[65]; + char host[1025]; +}; + +static void get_option125_suboption(char *data, int option, char *dst, int dst_len) +{ + int data_len = 0, len = 0; + char *pos = NULL; + + data_len = DM_STRLEN(data); + + if (data_len == 0) + return; + + switch (option) { + case OPT_OUI: + pos = strstr(data, "oui_len"); + if (pos == NULL) + return; + + sscanf(pos, "oui_len=%d", &len); + pos = strstr(data, "device_oui="); + if (pos == NULL) + return; + + pos = pos + 11; + if (pos >= (data + data_len)) + return; + + if (len >= dst_len) + len = dst_len; + else + len = len + 1; + + snprintf(dst, len, "%s", pos); + break; + case OPT_SERIAL: + pos = strstr(data, "serial_len"); + if (pos == NULL) + return; + + sscanf(pos, "serial_len=%d", &len); + pos = strstr(data, "device_serial="); + if (pos == NULL) + return; + + pos = pos + 14; + if (pos >= (data + data_len)) + return; + + if (len >= dst_len) + len = dst_len; + else + len = len + 1; + + snprintf(dst, len, "%s", pos); + break; + case OPT_CLASS: + pos = strstr(data, "class_len"); + if (pos == NULL) + return; + + sscanf(pos, "class_len=%d", &len); + pos = strstr(data, "device_class="); + if (pos == NULL) + return; + + pos = pos + 13; + if (pos >= (data + data_len)) + return; + + if (len >= dst_len) + len = dst_len; + else + len = len + 1; + + snprintf(dst, len, "%s", pos); + break; + default: + return; + } +} + +static int browseManageableDevice(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + FILE *f = fopen(DHCP_CLIENT_OPTIONS_FILE, "r"); + if (f == NULL) + return 0; + + struct manageable_device_args device; + char line[2048]; + char *inst = NULL; + int id = 0; + + while (fgets(line, sizeof(line), f) != NULL) { + remove_new_line(line); + + memset(&device, 0, sizeof(device)); + + sscanf(line, "%17s", device.mac); + + if (DM_STRLEN(device.mac) < 17) + continue; + + char *linker = NULL; + adm_entry_get_linker_param(dmctx, "Device.Hosts.Host.", device.mac, &linker); + if (DM_STRLEN(linker) == 0) + continue; + + strncpy(device.host, linker, 1024); + get_option125_suboption(line, OPT_OUI, device.oui, sizeof(device.oui)); + get_option125_suboption(line, OPT_SERIAL, device.serial, sizeof(device.serial)); + get_option125_suboption(line, OPT_CLASS, device.class, sizeof(device.class)); + + if (DM_STRCMP(device.oui, "-") == 0 || DM_STRCMP(device.serial, "-") == 0) + continue; + + inst = handle_instance_without_section(dmctx, parent_node, ++id); + + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&device, inst) == DM_STOP) + break; + } + fclose(f); + return 0; + +} + /*#Device.ManagementServer.URL!UCI:cwmp/acs,acs/url*/ static int get_management_server_url(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { @@ -608,6 +745,13 @@ static int get_nat_detected(char *refparam, struct dmctx *ctx, void *data, char return 0; } +static int get_manageable_device_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + int cnt = get_number_of_entries(ctx, data, instance, browseManageableDevice); + dmasprintf(value, "%d", cnt); + return 0; +} + static int get_heart_beat_policy_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { *value = dmuci_get_option_value_fallback_def("cwmp", "acs", "heartbeat_enable", "0"); @@ -827,6 +971,34 @@ static int get_inform_parameter_number_of_entries(char *refparam, struct dmctx * return 0; } +static int get_manageable_device_oui(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct manageable_device_args *device = (struct manageable_device_args *)data; + *value = dmstrdup(device->oui); + return 0; +} + +static int get_manageable_device_serial(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct manageable_device_args *device = (struct manageable_device_args *)data; + *value = dmstrdup(device->serial); + return 0; +} + +static int get_manageable_device_class(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct manageable_device_args *device = (struct manageable_device_args *)data; + *value = (DM_STRCMP(device->class, "-") != 0) ? dmstrdup(device->class) : ""; + return 0; +} + +static int get_manageable_device_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct manageable_device_args *device = (struct manageable_device_args *)data; + *value = dmstrdup(device->host); + return 0; +} + /********************************************************************************************************************************** * OBJ & PARAM DEFINITION ***********************************************************************************************************************************/ @@ -834,6 +1006,7 @@ DMOBJ tManagementServerObj[] = { /* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/ {"HeartbeatPolicy", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tHeartbeatPolicyParams, NULL, BBFDM_CWMP, NULL, "2.12"}, {"InformParameter", &DMWRITE, add_inform_parameter, delete_inform_parameter, NULL, browseInformParameterInst, NULL, NULL, NULL, tInformParameterParams, NULL, BBFDM_CWMP, NULL, "2.8"}, +{"ManageableDevice", &DMREAD, NULL, NULL, NULL, browseManageableDevice, NULL, NULL, NULL, tManageableDeviceParams, NULL, BBFDM_CWMP, NULL, "2.12"}, {0} }; @@ -869,6 +1042,7 @@ DMLEAF tManagementServerParams[] = { {"UDPConnectionRequestAddress", &DMREAD, DMT_STRING, get_upd_cr_address, NULL, BBFDM_CWMP, "2.0"}, {"NATDetected", &DMREAD, DMT_BOOL, get_nat_detected, NULL, BBFDM_CWMP, "2.0"}, {"InformParameterNumberOfEntries", &DMREAD, DMT_UNINT, get_inform_parameter_number_of_entries, NULL, BBFDM_CWMP, "2.0"}, +{"ManageableDeviceNumberOfEntries", &DMREAD, DMT_UNINT, get_manageable_device_number_of_entries, NULL, BBFDM_CWMP, "2.0"}, {0} }; @@ -887,3 +1061,10 @@ DMLEAF tInformParameterParams[] = { {0} }; +DMLEAF tManageableDeviceParams[] = { +{"ManufacturerOUI", &DMREAD, DMT_STRING, get_manageable_device_oui, NULL, BBFDM_CWMP, "2.0"}, +{"SerialNumber", &DMREAD, DMT_STRING, get_manageable_device_serial, NULL, BBFDM_CWMP, "2.0"}, +{"ProductClass", &DMREAD, DMT_STRING, get_manageable_device_class, NULL, BBFDM_CWMP, "2.0"}, +{"Host", &DMREAD, DMT_STRING, get_manageable_device_host, NULL, BBFDM_CWMP, "2.0"}, +{0} +}; diff --git a/dmtree/tr181/managementserver.h b/dmtree/tr181/managementserver.h index 2dba042d..3f34ce2b 100644 --- a/dmtree/tr181/managementserver.h +++ b/dmtree/tr181/managementserver.h @@ -17,5 +17,6 @@ extern DMLEAF tManagementServerParams[]; extern DMLEAF tHeartbeatPolicyParams[]; extern DMLEAF tInformParameterParams[]; +extern DMLEAF tManageableDeviceParams[]; extern DMOBJ tManagementServerObj[]; #endif diff --git a/dmtree/vendor/iopsys/tr181/x_iopsys_eu_igmp.c b/dmtree/vendor/iopsys/tr181/x_iopsys_eu_igmp.c index 802029d1..492fca98 100644 --- a/dmtree/vendor/iopsys/tr181/x_iopsys_eu_igmp.c +++ b/dmtree/vendor/iopsys/tr181/x_iopsys_eu_igmp.c @@ -31,6 +31,27 @@ static void get_mcast_iface_key(char *p_ifname, char *key, size_t key_size) } } +static char *get_host_linker(char *ipaddr) +{ + json_object *res = NULL, *host_obj = NULL, *arrobj = NULL; + char *macaddr = ""; + int i = 0; + + dmubus_call("topology", "hosts", UBUS_ARGS{0}, 0, &res); + if (res == NULL) + return ""; + + dmjson_foreach_obj_in_array(res, arrobj, host_obj, i, 1, "hosts") { + char *ip_addr = dmjson_get_value(host_obj, 1, "ipaddr"); + if (DM_STRCMP(ip_addr, ipaddr) == 0) { + macaddr = dmjson_get_value(host_obj, 1, "macaddr"); + break; + } + } + + return macaddr; +} + static void sync_mcast_dmmap_iface_sec(struct uci_list *proxy_iface, char *s_mode, struct uci_section *s, char *dmmap_package, char *dmmap_sec, struct list_head *dup_list, char *up_iface) @@ -1356,7 +1377,8 @@ static int get_igmp_cgrp_adev_iface(char *refparam, struct dmctx *ctx, void *dat static int get_igmp_cgrp_adev_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { char *ipaddr = dmjson_get_value((json_object *)data, 1, "ipaddr"); - adm_entry_get_linker_param(ctx, "Device.Hosts.Host.", ipaddr, value); + char *linker = get_host_linker(ipaddr); + adm_entry_get_linker_param(ctx, "Device.Hosts.Host.", linker, value); return 0; } diff --git a/gitlab-ci/memory-test.sh b/gitlab-ci/memory-test.sh index 3724cd8d..fa83f3aa 100755 --- a/gitlab-ci/memory-test.sh +++ b/gitlab-ci/memory-test.sh @@ -41,7 +41,7 @@ function run_valgrind_verbose() function run_valgrind_redirect() { - echo "Running # bbf_dm $@ #" > output-report-device-get.txt + echo "Running # bbf_dm $@ #" >> output-report-device-get.txt exec_cmd_verbose valgrind -q --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes ./test/bbf_test/bbf_dm $@ | tee -a output-report-device-get.txt } @@ -67,6 +67,7 @@ run_valgrind -u get Device. run_valgrind -c get Device. run_valgrind_redirect -u get Device. +run_valgrind_redirect -c get Device. supervisorctl stop all supervisorctl status diff --git a/test/files/tmp/dhcp.leases b/test/files/tmp/dhcp.leases index a4ccaae9..b81c9a36 100644 --- a/test/files/tmp/dhcp.leases +++ b/test/files/tmp/dhcp.leases @@ -1 +1 @@ -1632358669 24:18:1d:e2:f7:dd 192.168.1.187 Galaxy-S8 01:24:18:1d:e2:f7:dd +1658935161 24:18:1d:e2:f7:dd 192.168.1.141 iopsysWrt-44D43771AFF0 * \ No newline at end of file diff --git a/test/files/tmp/interface_wan.data b/test/files/tmp/interface_wan.data index 3dccbfc6..87c6f456 100644 --- a/test/files/tmp/interface_wan.data +++ b/test/files/tmp/interface_wan.data @@ -72,6 +72,8 @@ "data": { "hostname": "iopsysWrt-44D43771AFF0", "leasetime": 86400, - "ntpserver": "200.23.51.102" + "ntpserver": "200.23.51.102", + "vendorspecinf": "http://iopsys_genieacs:7547", + "vivsoinf": "4=44D437,5=Y.0721140006,6=EAGLE" } } diff --git a/test/files/var/dhcp.client.options b/test/files/var/dhcp.client.options index 5902968d..7e8ed642 100644 --- a/test/files/var/dhcp.client.options +++ b/test/files/var/dhcp.client.options @@ -1 +1 @@ -24:18:1d:e2:f7:dd vcid=android-dhcp-9 clid=01:24:18:1d:e2:f7:dd ucid=- +24:18:1d:e2:f7:dd vcid=eagle clid=01:24:18:1d:e2:f7:dd ucid=- oui_len=6 device_oui=44D437 serial_len=12 device_serial=Y.0721140030 class_len=5 device_class=EAGLE \ No newline at end of file