From bbd746e13252cc69337bca02b14b94f6a9378069 Mon Sep 17 00:00:00 2001 From: Suvendhu Hansa Date: Thu, 6 Oct 2022 08:42:53 +0000 Subject: [PATCH] Added support of ManageableDevice & GatewayInfo --- 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..be3ba37e 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 89ff7836..7215a1b4 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 8f288ec6..22f2c811 100644 --- a/dmtree/tr181/managementserver.c +++ b/dmtree/tr181/managementserver.c @@ -14,6 +14,143 @@ #include "managementserver.h" #include "dmbbfcommon.h" +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) { @@ -606,6 +743,12 @@ 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) { @@ -671,12 +814,41 @@ static int set_heart_beat_policy_initiation_time(char *refparam, struct dmctx *c 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 ***********************************************************************************************************************************/ 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"}, +{"ManageableDevice", &DMREAD, NULL, NULL, NULL, browseManageableDevice, NULL, NULL, NULL, tManageableDeviceParams, NULL, BBFDM_CWMP, NULL, "2.12"}, {0} }; @@ -711,6 +883,7 @@ DMLEAF tManagementServerParams[] = { {"EnableCWMP", &DMWRITE, DMT_BOOL, get_management_server_enable_cwmp, set_management_server_enable_cwmp, BBFDM_CWMP, "2.12"}, {"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"}, +{"ManageableDeviceNumberOfEntries", &DMREAD, DMT_UNINT, get_manageable_device_number_of_entries, NULL, BBFDM_CWMP, "2.0"}, {0} }; @@ -720,3 +893,11 @@ DMLEAF tHeartbeatPolicyParams[] = { {"InitiationTime", &DMWRITE, DMT_TIME, get_heart_beat_policy_initiation_time, set_heart_beat_policy_initiation_time, BBFDM_CWMP, "2.12"}, {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 4dc9c6fe..9eb45d87 100644 --- a/dmtree/tr181/managementserver.h +++ b/dmtree/tr181/managementserver.h @@ -16,5 +16,6 @@ extern DMLEAF tManagementServerParams[]; extern DMLEAF tHeartbeatPolicyParams[]; +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..55d98904 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 * 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..ff72ed83 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