bbfdm/dmoperate.c
2020-12-21 20:47:04 +01:00

1249 lines
42 KiB
C

/*
* dmoperate.c: Operate handler for uspd
*
* Copyright (C) 2019 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: Vivek Dutta <vivek.dutta@iopsys.eu>
* Author: Yashvardhan <y.yashvardhan@iopsys.eu>
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#include "dmoperate.h"
#define GLOB_EXPR "[=><]+"
static uint8_t wifi_neighbor_count = 0;
struct op_cmd *dynamic_operate = NULL;
static void bbf_init(struct dmctx *dm_ctx, char *path)
{
unsigned int instance = INSTANCE_MODE_NUMBER;
if (match(path, "[[]+")) {
if (!match(path, GLOB_EXPR))
instance = INSTANCE_MODE_ALIAS;
}
dm_ctx_init_sub(dm_ctx, instance);
}
static void bbf_cleanup(struct dmctx *dm_ctx)
{
dm_ctx_clean_sub(dm_ctx);
}
static bool bbf_get(int operation, char *path, struct dmctx *dm_ctx)
{
int fault = 0;
switch(operation) {
case CMD_GET_NAME:
fault = dm_entry_param_method(dm_ctx, CMD_GET_NAME, path, "true", NULL);
break;
case CMD_GET_VALUE:
fault = dm_entry_param_method(dm_ctx, CMD_GET_VALUE, path, NULL, NULL);
break;
default:
return false;
}
if (dm_ctx->list_fault_param.next != &dm_ctx->list_fault_param) {
return false;
}
if (fault) {
return false;
}
return true;
}
static bool bbf_set_value(char *path, char *value)
{
int fault = 0, res;
struct dmctx dm_ctx = {0};
struct dmctx *p_dmctx = &dm_ctx;
bbf_init(&dm_ctx, path);
fault = dm_entry_param_method(&dm_ctx, CMD_SET_VALUE, path, value, NULL);
if (!fault) {
fault = dm_entry_apply(&dm_ctx, CMD_SET_VALUE, "", NULL);
}
if (p_dmctx->list_fault_param.next != &p_dmctx->list_fault_param) {
res = FAIL;
}
if (fault)
res = FAIL;
else
res = SUCCESS;
bbf_cleanup(&dm_ctx);
return res;
}
static char *bbf_get_value_by_id(char *id)
{
struct dmctx dm_ctx = {0};
struct dm_parameter *n;
char *value = NULL;
bbf_init(&dm_ctx, id);
if (bbf_get(CMD_GET_VALUE, id, &dm_ctx)) {
list_for_each_entry(n, &dm_ctx.list_parameter, list) {
value = dmstrdup(n->data);
break;
}
}
bbf_cleanup(&dm_ctx);
return value;
}
static char *get_param_val_from_op_cmd(char *op_cmd, const char *param)
{
char *val = NULL;
char node[256] = {'\0'};
// Trim action from operation command
// For eg: trim Reset from Device.IP.Interface.*.Reset
char *ret = strrchr(op_cmd, '.');
strncpy(node, op_cmd, ret - op_cmd +1);
// Append param name to the trimmed path
strcat(node, param);
// Get parameter value
val = bbf_get_value_by_id(node);
return val;
}
static opr_ret_t reboot_device(struct dmctx *dmctx, char *path, json_object *input)
{
if (0 == dmubus_call_set(SYSTEM_UBUS_PATH, "reboot", UBUS_ARGS{}, 0))
return SUCCESS;
else
return FAIL;
}
static opr_ret_t factory_reset(struct dmctx *dmctx, char *path, json_object *input)
{
if (0 == dmcmd_no_wait("/sbin/defaultreset", 0))
return SUCCESS;
else
return FAIL;
}
static opr_ret_t network_interface_reset(struct dmctx *dmctx, char *path, json_object *input)
{
char cmd[NAME_MAX] = NETWORK_INTERFACE_UBUS_PATH;
bool status = false;
snprintf(cmd + strlen(cmd), NAME_MAX - strlen(cmd), "%s", ".");
char *zone = NULL;
zone = get_param_val_from_op_cmd(path, "Name");
if (zone) {
strcat(cmd, zone);
dmfree(zone);
} else {
return FAIL;
}
if (0 == dmubus_call_set(cmd, "down", UBUS_ARGS{}, 0))
status = true;
if (0 == dmubus_call_set(cmd, "up", UBUS_ARGS{}, 0))
status &= true;
if (status)
return SUCCESS;
else
return FAIL;
}
static opr_ret_t wireless_reset(struct dmctx *dmctx, char *path, json_object *input)
{
if (0 == dmcmd_no_wait("/sbin/wifi", 2, "reload", "&"))
return SUCCESS;
else
return FAIL;
}
struct wifi_security_params reset_params[] = {
{"", "ModeEnabled", ""},
{"", "PreSharedKey", ""},
{"", "KeyPassphrase", ""}
};
static opr_ret_t ap_security_reset(struct dmctx *dmctx, char *path, json_object *input)
{
char *wpakey = NULL;
char node[255] = {'\0'};
int i, len = 0;
char *ret = strrchr(path, '.');
strncpy(node, path, ret - path +1);
len = ARRAY_SIZE(reset_params);
for (i = 0; i < len; i++) {
strncpy(reset_params[i].node, node, 255);
strcat(reset_params[i].node, reset_params[i].param);
}
const char *mode_enabled = "WPA2-Personal";
// Default mode - WPA2-Personal
strncpy(reset_params[0].value, mode_enabled, 255);
// Get Default wpakey
db_get_value_string("hw", "board", "wpa_key", &wpakey);
// PreSharedKey and KeyPassphrase are kept same
strncpy(reset_params[1].value, wpakey, 255);
strncpy(reset_params[2].value, wpakey, 255);
for (i = 0; i < len; i++) {
bbf_set_value(reset_params[i].node, reset_params[i].value);
}
return SUCCESS;
}
static opr_ret_t dhcp_client_renew(struct dmctx *dmctx, char *path, json_object *input)
{
if (SUCCESS == bbf_set_value(path, "true"))
return SUCCESS;
else
return FAIL;
}
static opr_ret_t vendor_conf_backup(struct dmctx *dmctx, char *path, json_object *input)
{
struct file_server fserver = {0};
char *vcf_name = NULL;
vcf_name = get_param_val_from_op_cmd(path, "Name");
if (!vcf_name)
return FAIL;
fserver.url = dmjson_get_value(input, 1, "URL");
if (fserver.url[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
fserver.user = dmjson_get_value(input, 1, "Username");
fserver.pass = dmjson_get_value(input, 1, "Password");
dmcmd("/bin/sh", 7, ICWMP_SCRIPT, "upload", fserver.url, VCF_FILE_TYPE, fserver.user, fserver.pass, vcf_name);
dmfree(vcf_name);
return SUCCESS;
}
static opr_ret_t vendor_conf_restore(struct dmctx *dmctx, char *path, json_object *input)
{
struct file_server fserver = {0};
char *file_size = NULL;
fserver.url = dmjson_get_value(input, 1, "URL");
if (fserver.url[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
fserver.user = dmjson_get_value(input, 1, "Username");
fserver.pass = dmjson_get_value(input, 1, "Password");
file_size = dmjson_get_value(input, 1, "FileSize");
dmcmd("/bin/sh", 7, ICWMP_SCRIPT, "download", fserver.url, file_size, VCF_FILE_TYPE, fserver.user, fserver.pass);
if (0 == dmcmd_no_wait("/bin/sh", 4, ICWMP_SCRIPT, "apply", "download", VCF_FILE_TYPE))
return SUCCESS;
else
return FAIL;
}
static void fill_wireless_scan_results(struct dmctx *dmctx, char *radio)
{
json_object *res = NULL, *obj = NULL;
struct neighboring_wiFi_diagnostic neighboring = {0};
char object[32], *ssid, *bssid, *channel, *frequency, *signal_stregth, *noise;
snprintf(object, sizeof(object), "wifi.radio.%s", radio);
dmubus_call_set(object, "scan", UBUS_ARGS{}, 0);
sleep(2); // Wait for results to get populated in scanresults
dmubus_call(object, "scanresults", UBUS_ARGS{}, 0, &res);
if (!res)
return;
if (!json_object_object_get_ex(res,"accesspoints", &obj))
return;
uint8_t len = json_object_array_length(obj);
for (uint8_t j = 0; j < len; j++ ) {
wifi_neighbor_count++;
json_object *array_obj = json_object_array_get_idx(obj, j);
neighboring.ssid = dmjson_get_value(array_obj, 1, "ssid");
neighboring.bssid = dmjson_get_value(array_obj, 1, "bssid");
neighboring.channel = dmjson_get_value(array_obj, 1, "channel");
neighboring.frequency = dmjson_get_value(array_obj, 1, "band");
neighboring.signal_strength = dmjson_get_value(array_obj, 1, "rssi");
neighboring.noise = dmjson_get_value(array_obj, 1, "noise");
dmasprintf(&ssid, "Result.%d.SSID", wifi_neighbor_count);
dmasprintf(&bssid, "Result.%d.BSSID", wifi_neighbor_count);
dmasprintf(&channel, "Result.%d.Channel", wifi_neighbor_count);
dmasprintf(&frequency, "Result.%d.OperatingFrequencyBand", wifi_neighbor_count);
dmasprintf(&signal_stregth, "Result.%d.SignalStrength", wifi_neighbor_count);
dmasprintf(&noise, "Result.%d.Noise", wifi_neighbor_count);
add_list_parameter(dmctx, ssid, neighboring.ssid, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, bssid, neighboring.bssid, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, channel, neighboring.channel, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, frequency, neighboring.frequency, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, signal_stregth, neighboring.signal_strength, DMT_TYPE[DMT_INT], NULL);
add_list_parameter(dmctx, noise, neighboring.noise, DMT_TYPE[DMT_INT], NULL);
}
}
static opr_ret_t fetch_neighboring_wifi_diagnostic(struct dmctx *dmctx, char *path, json_object *input)
{
json_object *res = NULL, *radios = NULL, *arrobj = NULL;
int j = 0;
dmubus_call("wifi", "status", UBUS_ARGS{}, 0, &res);
if (res) {
dmjson_foreach_obj_in_array(res, arrobj, radios, j, 1, "radios") {
fill_wireless_scan_results(dmctx, dmjson_get_value(radios, 1, "name"));
}
}
wifi_neighbor_count = 0;
return SUCCESS;
}
static opr_ret_t ip_diagnostics_ipping(struct dmctx *dmctx, char *path, json_object *input)
{
struct ipping_diagnostics ipping = {0};
init_diagnostics_operation("ipping", IPPING_PATH);
ipping.host = dmjson_get_value(input, 1, "Host");
if (ipping.host[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
ipping.interface = dmjson_get_value(input, 1, "Interface");
ipping.proto = dmjson_get_value(input, 1, "ProtocolVersion");
ipping.nbofrepetition = dmjson_get_value(input, 1, "NumberOfRepetitions");
ipping.timeout = dmjson_get_value(input, 1, "Timeout");
ipping.datablocksize = dmjson_get_value(input, 1, "DataBlockSize");
ipping.dscp = dmjson_get_value(input, 1, "DSCP");
set_diagnostics_option("ipping", "Host", ipping.host);
set_diagnostics_interface_option(dmctx, "ipping", ipping.interface);
set_diagnostics_option("ipping", "ProtocolVersion", ipping.proto);
set_diagnostics_option("ipping", "NumberOfRepetitions", ipping.nbofrepetition);
set_diagnostics_option("ipping", "Timeout", ipping.timeout);
set_diagnostics_option("ipping", "DataBlockSize", ipping.datablocksize);
set_diagnostics_option("ipping", "DSCP", ipping.dscp);
// Commit and Free uci_ctx_bbfdm
commit_and_free_uci_ctx_bbfdm(DMMAP_DIAGNOSTIGS);
dmcmd("/bin/sh", 3, IPPING_PATH, "run", "usp");
// Allocate uci_ctx_bbfdm
dmuci_init_bbfdm();
ipping.success_count = get_diagnostics_option("ipping", "SuccessCount");
ipping.failure_count = get_diagnostics_option("ipping", "FailureCount");
ipping.average_response_time = get_diagnostics_option("ipping", "AverageResponseTime");
ipping.minimum_response_time = get_diagnostics_option("ipping", "MinimumResponseTime");
ipping.maximum_response_time = get_diagnostics_option("ipping", "MaximumResponseTime");
ipping.average_response_time_detailed = get_diagnostics_option("ipping", "AverageResponseTimeDetailed");
ipping.minimum_response_time_detailed = get_diagnostics_option("ipping", "MinimumResponseTimeDetailed");
ipping.maximum_response_time_detailed = get_diagnostics_option("ipping", "MaximumResponseTimeDetailed");
add_list_parameter(dmctx, dmstrdup("SuccessCount"), ipping.success_count, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("FailureCount"), ipping.failure_count, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("AverageResponseTime"), ipping.average_response_time, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("MinimumResponseTime"), ipping.minimum_response_time, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("MaximumResponseTime"), ipping.maximum_response_time, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("AverageResponseTimeDetailed"), ipping.average_response_time_detailed, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("MinimumResponseTimeDetailed"), ipping.minimum_response_time_detailed, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("MaximumResponseTimeDetailed"), ipping.maximum_response_time_detailed, DMT_TYPE[DMT_UNINT], NULL);
return SUCCESS;
}
static opr_ret_t ip_diagnostics_traceroute(struct dmctx *dmctx, char *path, json_object *input)
{
struct traceroute_diagnostics traceroute = {0};
struct uci_section *s = NULL;
char *host, *host_address, *errorcode, *rttimes;
int i = 1;
init_diagnostics_operation("traceroute", TRACEROUTE_PATH);
traceroute.host = dmjson_get_value(input, 1, "Host");
if (traceroute.host[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
traceroute.interface = dmjson_get_value(input, 1, "Interface");
traceroute.proto = dmjson_get_value(input, 1, "ProtocolVersion");
traceroute.nboftries = dmjson_get_value(input, 1, "NumberOfTries");
traceroute.timeout = dmjson_get_value(input, 1, "Timeout");
traceroute.datablocksize = dmjson_get_value(input, 1, "DataBlockSize");
traceroute.dscp = dmjson_get_value(input, 1, "DSCP");
traceroute.maxhops = dmjson_get_value(input, 1, "MaxHopCount");
set_diagnostics_option("traceroute", "Host", traceroute.host);
set_diagnostics_interface_option(dmctx, "traceroute", traceroute.interface);
set_diagnostics_option("traceroute", "ProtocolVersion", traceroute.proto);
set_diagnostics_option("traceroute", "NumberOfTries", traceroute.nboftries);
set_diagnostics_option("traceroute", "Timeout", traceroute.timeout);
set_diagnostics_option("traceroute", "DataBlockSize", traceroute.datablocksize);
set_diagnostics_option("traceroute", "DSCP", traceroute.dscp);
set_diagnostics_option("traceroute", "MaxHops", traceroute.maxhops);
// Commit and Free uci_ctx_bbfdm
commit_and_free_uci_ctx_bbfdm(DMMAP_DIAGNOSTIGS);
dmcmd("/bin/sh", 3, TRACEROUTE_PATH, "run", "usp");
// Allocate uci_ctx_bbfdm
dmuci_init_bbfdm();
traceroute.response_time = get_diagnostics_option("traceroute", "ResponseTime");
add_list_parameter(dmctx, dmstrdup("ResponseTime"), traceroute.response_time, DMT_TYPE[DMT_UNINT], NULL);
uci_path_foreach_sections(bbfdm, DMMAP_DIAGNOSTIGS, "RouteHops", s) {
dmasprintf(&host, "RouteHops.%d.Host", i);
dmasprintf(&host_address, "RouteHops.%d.HostAddress", i);
dmasprintf(&errorcode, "RouteHops.%d.ErrorCode", i);
dmasprintf(&rttimes, "RouteHops.%d.RTTimes", i);
dmuci_get_value_by_section_string(s, "host", &traceroute.host_name);
dmuci_get_value_by_section_string(s, "ip", &traceroute.host_address);
dmuci_get_value_by_section_string(s, "time", &traceroute.rttimes);
add_list_parameter(dmctx, host, traceroute.host_name, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, host_address, traceroute.host_address, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, errorcode, "0", DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, rttimes, traceroute.rttimes, DMT_TYPE[DMT_STRING], NULL);
i++;
}
return SUCCESS;
}
static opr_ret_t ip_diagnostics_download(struct dmctx *dmctx, char *path, json_object *input)
{
struct download_diagnostics download = {0};
init_diagnostics_operation("download", DOWNLOAD_DIAGNOSTIC_PATH);
download.download_url = dmjson_get_value(input, 1, "DownloadURL");
if (download.download_url[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
download.interface = dmjson_get_value(input, 1, "Interface");
download.dscp = dmjson_get_value(input, 1, "DSCP");
download.ethernet_priority = dmjson_get_value(input, 1, "EthernetPriority");
download.proto = dmjson_get_value(input, 1, "ProtocolVersion");
download.num_of_connections = dmjson_get_value(input, 1, "NumberOfConnections");
download.enable_per_connection_results = dmjson_get_value(input, 1, "EnablePerConnectionResults");
set_diagnostics_option("download", "url", download.download_url);
set_diagnostics_interface_option(dmctx, "download", download.interface);
set_diagnostics_option("download", "DSCP", download.dscp);
set_diagnostics_option("download", "ethernetpriority", download.ethernet_priority);
set_diagnostics_option("download", "ProtocolVersion", download.proto);
set_diagnostics_option("download", "NumberOfConnections", download.num_of_connections);
set_diagnostics_option("download", "EnablePerConnection", download.enable_per_connection_results);
if (start_upload_download_diagnostic(DOWNLOAD_DIAGNOSTIC, "usp") == -1)
return FAIL;
download.romtime = get_diagnostics_option("download", "ROMtime");
download.bomtime = get_diagnostics_option("download", "BOMtime");
download.eomtime = get_diagnostics_option("download", "EOMtime");
download.test_bytes_received = get_diagnostics_option("download", "TestBytesReceived");
download.total_bytes_received = get_diagnostics_option("download", "TotalBytesReceived");
download.total_bytes_sent = get_diagnostics_option("download", "TotalBytesSent");
download.test_bytes_received_under_full_loading = get_diagnostics_option("download", "TestBytesReceived");
download.total_bytes_received_under_full_loading = get_diagnostics_option("download", "TotalBytesReceived");
download.total_bytes_sent_under_full_loading = get_diagnostics_option("download", "TotalBytesSent");
download.period_of_full_loading = get_diagnostics_option("download", "PeriodOfFullLoading");
download.tcp_open_request_time = get_diagnostics_option("download", "TCPOpenRequestTime");
download.tcp_open_response_time = get_diagnostics_option("download", "TCPOpenResponseTime");
add_list_parameter(dmctx, dmstrdup("ROMTime"), download.romtime, DMT_TYPE[DMT_TIME], NULL);
add_list_parameter(dmctx, dmstrdup("BOMTime"), download.bomtime, DMT_TYPE[DMT_TIME], NULL);
add_list_parameter(dmctx, dmstrdup("EOMTime"), download.eomtime, DMT_TYPE[DMT_TIME], NULL);
add_list_parameter(dmctx, dmstrdup("TestBytesReceived"), download.test_bytes_received, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TotalBytesReceived"), download.total_bytes_received, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TotalBytesSent"), download.total_bytes_sent, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TestBytesReceivedUnderFullLoading"), download.test_bytes_received_under_full_loading, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TotalBytesReceivedUnderFullLoading"), download.total_bytes_received_under_full_loading, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TotalBytesSentUnderFullLoading"), download.total_bytes_sent_under_full_loading, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("PeriodOfFullLoading"), download.period_of_full_loading, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TCPOpenRequestTime"), download.tcp_open_request_time, DMT_TYPE[DMT_TIME], NULL);
add_list_parameter(dmctx, dmstrdup("TCPOpenResponseTime"), download.tcp_open_response_time, DMT_TYPE[DMT_TIME], NULL);
return SUCCESS;
}
static opr_ret_t ip_diagnostics_upload(struct dmctx *dmctx, char *path, json_object *input)
{
struct upload_diagnostics upload = {0};
init_diagnostics_operation("upload", UPLOAD_DIAGNOSTIC_PATH);
upload.upload_url = dmjson_get_value(input, 1, "UploadURL");
if (upload.upload_url[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
upload.test_file_length = dmjson_get_value(input, 1, "TestFileLength");
if (upload.test_file_length[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
upload.interface = dmjson_get_value(input, 1, "Interface");
upload.dscp = dmjson_get_value(input, 1, "DSCP");
upload.ethernet_priority = dmjson_get_value(input, 1, "EthernetPriority");
upload.proto = dmjson_get_value(input, 1, "ProtocolVersion");
upload.num_of_connections = dmjson_get_value(input, 1, "NumberOfConnections");
upload.enable_per_connection_results = dmjson_get_value(input, 1, "EnablePerConnectionResults");
set_diagnostics_option("upload", "url", upload.upload_url);
set_diagnostics_option("upload", "TestFileLength", upload.test_file_length);
set_diagnostics_interface_option(dmctx, "upload", upload.interface);
set_diagnostics_option("upload", "DSCP", upload.dscp);
set_diagnostics_option("upload", "ethernetpriority", upload.ethernet_priority);
set_diagnostics_option("upload", "ProtocolVersion", upload.proto);
set_diagnostics_option("upload", "NumberOfConnections", upload.num_of_connections);
set_diagnostics_option("upload", "EnablePerConnection", upload.enable_per_connection_results);
if (start_upload_download_diagnostic(UPLOAD_DIAGNOSTIC, "usp") == -1)
return FAIL;
upload.romtime = get_diagnostics_option("upload", "ROMtime");
upload.bomtime = get_diagnostics_option("upload", "BOMtime");
upload.eomtime = get_diagnostics_option("upload", "EOMtime");
upload.test_bytes_sent = get_diagnostics_option("upload", "TestBytesSent");
upload.total_bytes_received = get_diagnostics_option("upload", "TotalBytesReceived");
upload.total_bytes_sent = get_diagnostics_option("upload", "TotalBytesSent");
upload.test_bytes_sent_under_full_loading = get_diagnostics_option("upload", "TestBytesSent");
upload.total_bytes_received_under_full_loading = get_diagnostics_option("upload", "TotalBytesReceived");
upload.total_bytes_sent_under_full_loading = get_diagnostics_option("upload", "TotalBytesSent");
upload.period_of_full_loading = get_diagnostics_option("upload", "PeriodOfFullLoading");
upload.tcp_open_request_time = get_diagnostics_option("upload", "TCPOpenRequestTime");
upload.tcp_open_response_time = get_diagnostics_option("upload", "TCPOpenResponseTime");
add_list_parameter(dmctx, dmstrdup("ROMTime"), upload.romtime, DMT_TYPE[DMT_TIME], NULL);
add_list_parameter(dmctx, dmstrdup("BOMTime"), upload.bomtime, DMT_TYPE[DMT_TIME], NULL);
add_list_parameter(dmctx, dmstrdup("EOMTime"), upload.eomtime, DMT_TYPE[DMT_TIME], NULL);
add_list_parameter(dmctx, dmstrdup("TestBytesSent"), upload.test_bytes_sent, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TotalBytesReceived"), upload.total_bytes_received, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TotalBytesSent"), upload.total_bytes_sent, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TestBytesSentUnderFullLoading"), upload.test_bytes_sent_under_full_loading, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TotalBytesReceivedUnderFullLoading"), upload.total_bytes_received_under_full_loading, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TotalBytesSentUnderFullLoading"), upload.total_bytes_sent_under_full_loading, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("PeriodOfFullLoading"), upload.period_of_full_loading, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("TCPOpenRequestTime"), upload.tcp_open_request_time, DMT_TYPE[DMT_TIME], NULL);
add_list_parameter(dmctx, dmstrdup("TCPOpenResponseTime"), upload.tcp_open_response_time, DMT_TYPE[DMT_TIME], NULL);
return SUCCESS;
}
static opr_ret_t ip_diagnostics_udpecho(struct dmctx *dmctx, char *path, json_object *input)
{
struct udpecho_diagnostics udpecho = {0};
init_diagnostics_operation("udpechodiag", UDPECHO_PATH);
udpecho.host = dmjson_get_value(input, 1, "Host");
if (udpecho.host[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
udpecho.port = dmjson_get_value(input, 1, "Port");
if (udpecho.port[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
udpecho.interface = dmjson_get_value(input, 1, "Interface");
udpecho.proto = dmjson_get_value(input, 1, "ProtocolVersion");
udpecho.nbofrepetition = dmjson_get_value(input, 1, "NumberOfRepetitions");
udpecho.timeout = dmjson_get_value(input, 1, "Timeout");
udpecho.datablocksize = dmjson_get_value(input, 1, "DataBlockSize");
udpecho.dscp = dmjson_get_value(input, 1, "DSCP");
udpecho.inter_transmission_time = dmjson_get_value(input, 1, "InterTransmissionTime");
set_diagnostics_option("udpechodiag", "Host", udpecho.host);
set_diagnostics_option("udpechodiag", "port", udpecho.port);
set_diagnostics_interface_option(dmctx, "udpechodiag", udpecho.interface);
set_diagnostics_option("udpechodiag", "ProtocolVersion", udpecho.proto);
set_diagnostics_option("udpechodiag", "NumberOfRepetitions", udpecho.nbofrepetition);
set_diagnostics_option("udpechodiag", "Timeout", udpecho.timeout);
set_diagnostics_option("udpechodiag", "DataBlockSize", udpecho.datablocksize);
set_diagnostics_option("udpechodiag", "DSCP", udpecho.dscp);
set_diagnostics_option("udpechodiag", "InterTransmissionTime", udpecho.inter_transmission_time);
// Commit and Free uci_ctx_bbfdm
commit_and_free_uci_ctx_bbfdm(DMMAP_DIAGNOSTIGS);
dmcmd("/bin/sh", 3, UDPECHO_PATH, "run", "usp");
// Allocate uci_ctx_bbfdm
dmuci_init_bbfdm();
udpecho.success_count = get_diagnostics_option("udpechodiag", "SuccessCount");
udpecho.failure_count = get_diagnostics_option("udpechodiag", "FailureCount");
udpecho.average_response_time = get_diagnostics_option("udpechodiag", "AverageResponseTime");
udpecho.minimum_response_time = get_diagnostics_option("udpechodiag", "MinimumResponseTime");
udpecho.maximum_response_time = get_diagnostics_option("udpechodiag", "MaximumResponseTime");
add_list_parameter(dmctx, dmstrdup("SuccessCount"), udpecho.success_count, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("FailureCount"), udpecho.failure_count, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("AverageResponseTime"), udpecho.average_response_time, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("MinimumResponseTime"), udpecho.minimum_response_time, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("MaximumResponseTime"), udpecho.maximum_response_time, DMT_TYPE[DMT_UNINT], NULL);
return SUCCESS;
}
static opr_ret_t ip_diagnostics_serverselection(struct dmctx *dmctx, char *path, json_object *input)
{
struct serverselection_diagnostics serverselection = {0};
init_diagnostics_operation("serverselection", SERVERSELECTION_PATH);
serverselection.hostlist = dmjson_get_value(input, 1, "HostList");
if (serverselection.hostlist[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
serverselection.port = dmjson_get_value(input, 1, "Port");
serverselection.proto = dmjson_get_value(input, 1, "Protocol");
if (strcmp(serverselection.proto, "ICMP")) {
if (serverselection.port[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
}
serverselection.protocol_version = dmjson_get_value(input, 1, "ProtocolVersion");
serverselection.interface = dmjson_get_value(input, 1, "Interface");
serverselection.nbofrepetition = dmjson_get_value(input, 1, "NumberOfRepetitions");
serverselection.timeout = dmjson_get_value(input, 1, "Timeout");
set_diagnostics_option("serverselection", "HostList", serverselection.hostlist);
set_diagnostics_interface_option(dmctx, "serverselection", serverselection.interface);
set_diagnostics_option("serverselection", "ProtocolVersion", serverselection.protocol_version);
set_diagnostics_option("serverselection", "NumberOfRepetitions", serverselection.nbofrepetition);
set_diagnostics_option("serverselection", "port", serverselection.port);
set_diagnostics_option("serverselection", "Protocol", serverselection.proto);
set_diagnostics_option("serverselection", "Timeout", serverselection.timeout);
// Commit and Free uci_ctx_bbfdm
commit_and_free_uci_ctx_bbfdm(DMMAP_DIAGNOSTIGS);
dmcmd("/bin/sh", 3, SERVERSELECTION_PATH, "run", "usp");
// Allocate uci_ctx_bbfdm
dmuci_init_bbfdm();
serverselection.fasthost = get_diagnostics_option("serverselection", "FastestHost");
serverselection.average_response_time = get_diagnostics_option("serverselection", "AverageResponseTime");
serverselection.minimum_response_time = get_diagnostics_option("serverselection", "MinimumResponseTime");
serverselection.maximum_response_time = get_diagnostics_option("serverselection", "MaximumResponseTime");
add_list_parameter(dmctx, dmstrdup("FastestHost"), serverselection.fasthost, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, dmstrdup("AverageResponseTime"), serverselection.average_response_time, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("MinimumResponseTime"), serverselection.minimum_response_time, DMT_TYPE[DMT_UNINT], NULL);
add_list_parameter(dmctx, dmstrdup("MaximumResponseTime"), serverselection.maximum_response_time, DMT_TYPE[DMT_UNINT], NULL);
return SUCCESS;
}
static opr_ret_t ip_diagnostics_nslookup(struct dmctx *dmctx, char *path, json_object *input)
{
struct nslookup_diagnostics nslookup = {0};
struct uci_section *s = NULL;
char *status, *answertype, *hostname, *ipaddress, *dnsserverip, *responsetime;
int i = 1;
init_diagnostics_operation("nslookup", NSLOOKUP_PATH);
nslookup.hostname = dmjson_get_value(input, 1, "HostName");
if (nslookup.hostname[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
nslookup.interface = dmjson_get_value(input, 1, "Interface");
nslookup.dnsserver = dmjson_get_value(input, 1, "DNSServer");
nslookup.timeout = dmjson_get_value(input, 1, "Timeout");
nslookup.nbofrepetition = dmjson_get_value(input, 1, "NumberOfRepetitions");
set_diagnostics_option("nslookup", "HostName", nslookup.hostname);
set_diagnostics_interface_option(dmctx, "nslookup", nslookup.interface);
set_diagnostics_option("nslookup", "DNSServer", nslookup.dnsserver);
set_diagnostics_option("nslookup", "Timeout", nslookup.timeout);
set_diagnostics_option("nslookup", "NumberOfRepetitions", nslookup.nbofrepetition);
// Commit and Free uci_ctx_bbfdm
commit_and_free_uci_ctx_bbfdm(DMMAP_DIAGNOSTIGS);
dmcmd("/bin/sh", 3, NSLOOKUP_PATH, "run", "usp");
// Allocate uci_ctx_bbfdm
dmuci_init_bbfdm();
nslookup.success_count = get_diagnostics_option("nslookup", "SuccessCount");
char *param_success_count = dmstrdup("SuccessCount");
add_list_parameter(dmctx, param_success_count, nslookup.success_count, DMT_TYPE[DMT_UNINT], NULL);
uci_path_foreach_sections(bbfdm, DMMAP_DIAGNOSTIGS, "NSLookupResult", s) {
dmasprintf(&status, "Result.%d.Status", i);
dmasprintf(&answertype, "Result.%d.AnswerType", i);
dmasprintf(&hostname, "Result.%d.HostNameReturned", i);
dmasprintf(&ipaddress, "Result.%d.IPAddresses", i);
dmasprintf(&dnsserverip, "Result.%d.DNSServerIP", i);
dmasprintf(&responsetime, "Result.%d.ResponseTime", i);
dmuci_get_value_by_section_string(s, "Status", &nslookup.status);
dmuci_get_value_by_section_string(s, "AnswerType", &nslookup.answer_type);
dmuci_get_value_by_section_string(s, "HostNameReturned", &nslookup.hostname_returned);
dmuci_get_value_by_section_string(s, "IPAddresses", &nslookup.ip_addresses);
dmuci_get_value_by_section_string(s, "DNSServerIP", &nslookup.dns_server_ip);
dmuci_get_value_by_section_string(s, "ResponseTime", &nslookup.response_time);
add_list_parameter(dmctx, status, nslookup.status, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, answertype, nslookup.answer_type, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, hostname, nslookup.hostname_returned, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, ipaddress, nslookup.ip_addresses, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, dnsserverip, nslookup.dns_server_ip, DMT_TYPE[DMT_STRING], NULL);
add_list_parameter(dmctx, responsetime, nslookup.response_time, DMT_TYPE[DMT_UNINT], NULL);
i++;
}
return SUCCESS;
}
static opr_ret_t swmodules_exec_env_reset(struct dmctx *dmctx, char *path, json_object *input)
{
char *exec_env = get_param_val_from_op_cmd(path, "Name");
if (exec_env) {
if (strcmp(exec_env, "OpenWRT_Linux") == 0) {
if (0 == dmcmd_no_wait("/sbin/defaultreset", 0))
return SUCCESS;
else
return FAIL;
}
} else
return FAIL;
return SUCCESS;
}
static opr_ret_t swmodules_install_du(struct dmctx *dmctx, char *path, json_object *input)
{
json_object *res = NULL;
struct deployment_unit_install du_install = {0};
du_install.url = dmjson_get_value(input, 1, "URL");
if (du_install.url[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
du_install.uuid = dmjson_get_value(input, 1, "UUID");
du_install.username = dmjson_get_value(input, 1, "Username");
du_install.password = dmjson_get_value(input, 1, "Password");
du_install.environment = dmjson_get_value(input, 1, "ExecutionEnvRef");
char *exec_env = get_param_val_from_op_cmd(du_install.environment ? du_install.environment : "Device.SoftwareModules.ExecEnv.1.", "Name");
if (!exec_env)
return FAIL;
dmubus_call("swmodules", "du_install", UBUS_ARGS{
{"url", du_install.url},
{"uuid", du_install.uuid},
{"username", du_install.username},
{"password", du_install.password},
{"environment", exec_env}},
5,
&res);
if (!res)
return FAIL;
char *status = dmjson_get_value(res, 1, "status");
return (strcmp(status, "true") == 0) ? SUCCESS : FAIL;
}
static opr_ret_t swmodules_update_du(struct dmctx *dmctx, char *path, json_object *input)
{
json_object *res = NULL;
struct deployment_unit_update du_update = {0};
du_update.url = dmjson_get_value(input, 1, "URL");
if (du_update.url[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
du_update.username = dmjson_get_value(input, 1, "Username");
du_update.password = dmjson_get_value(input, 1, "Password");
char *du_uuid = get_param_val_from_op_cmd(path, "UUID");
if (!du_uuid)
return FAIL;
dmubus_call("swmodules", "du_update", UBUS_ARGS{
{"uuid", du_uuid},
{"url", du_update.url},
{"username", du_update.username},
{"password", du_update.password}},
4,
&res);
if (!res)
return FAIL;
char *status = dmjson_get_value(res, 1, "status");
return (strcmp(status, "true") == 0) ? SUCCESS : FAIL;
}
static opr_ret_t swmodules_uninstall_du(struct dmctx *dmctx, char *path, json_object *input)
{
json_object *res = NULL;
char exec_env_path[64] = {0};
char *du_name = get_param_val_from_op_cmd(path, "Name");
if (!du_name)
return FAIL;
char *exec_env = get_param_val_from_op_cmd(path, "ExecutionEnvRef");
if (!exec_env)
return FAIL;
snprintf(exec_env_path, sizeof(exec_env_path), "%s.", exec_env);
char *env = get_param_val_from_op_cmd(exec_env_path, "Name");
if (!env)
return FAIL;
dmubus_call("swmodules", "du_uninstall", UBUS_ARGS{
{"name", du_name},
{"environment", env}},
2,
&res);
if (!res)
return FAIL;
char *status = dmjson_get_value(res, 1, "status");
return (strcmp(status, "true") == 0) ? SUCCESS : FAIL;
}
static opr_ret_t firmware_image_download(struct dmctx *dmctx, char *path, json_object *input)
{
return SUCCESS;
}
static opr_ret_t firmware_image_activate(struct dmctx *dmctx, char *path, json_object *input)
{
return SUCCESS;
}
static int get_index_of_available_dynamic_operate(struct op_cmd *operate)
{
int idx = 0;
for (; (operate && operate->name); operate++) {
idx++;
}
return idx;
}
int add_dynamic_operate(char *path, operation operate, char *type)
{
if (dynamic_operate == NULL) {
dynamic_operate = calloc(2, sizeof(struct op_cmd));
dynamic_operate[0].name = path;
dynamic_operate[0].opt = operate;
dynamic_operate[0].type = type;
} else {
int idx = get_index_of_available_dynamic_operate(dynamic_operate);
struct op_cmd *new_dynamic_operate = realloc(dynamic_operate, (idx + 2) * sizeof(struct op_cmd));
if (new_dynamic_operate == NULL)
FREE(dynamic_operate);
else
dynamic_operate = new_dynamic_operate;
memset(dynamic_operate + (idx + 1), 0, sizeof(struct op_cmd));
dynamic_operate[idx].name = path;
dynamic_operate[idx].opt = operate;
dynamic_operate[idx].type = type;
}
return 0;
}
static const struct op_cmd operate_helper[] = {
{
"Device.Reboot", reboot_device, "sync"
},
{
"Device.FactoryReset", factory_reset, "sync"
},
{
"Device.IP.Interface.*.Reset", network_interface_reset, "sync"
},
{
"Device.PPP.Interface.*.Reset", network_interface_reset, "sync"
},
{
"Device.WiFi.Reset", wireless_reset, "sync"
},
{
"Device.WiFi.AccessPoint.*.Security.Reset", ap_security_reset, "sync"
},
{
"Device.DHCPv4.Client.*.Renew", dhcp_client_renew, "sync"
},
{
"Device.DHCPv6.Client.*.Renew", dhcp_client_renew, "sync"
},
{
"Device.DeviceInfo.VendorConfigFile.*.Backup", vendor_conf_backup, "async",
{
.in = (const char *[]) {
"URL",
"Username",
"Password",
NULL
}
}
},
{
"Device.DeviceInfo.VendorConfigFile.*.Restore", vendor_conf_restore, "async",
{
.in = (const char *[]) {
"URL",
"Username",
"Password",
"FileSize",
"TargetFileName",
"CheckSumAlgorithm",
"CheckSum",
NULL
}
}
},
{
"Device.DeviceInfo.FirmwareImage.*.Download", firmware_image_download, "async",
{
.in = (const char *[]) {
"URL",
"AutoActivate",
"Username",
"Password",
"FileSize",
"CheckSumAlgorithm",
"CheckSum",
NULL
}
}
},
{
"Device.DeviceInfo.FirmwareImage.*.Activate", firmware_image_activate, "async"
},
{
"Device.WiFi.NeighboringWiFiDiagnostic", fetch_neighboring_wifi_diagnostic, "async",
{
.out = (const char *[]) {
"Status",
NULL
}
}
},
{
"Device.IP.Diagnostics.IPPing", ip_diagnostics_ipping, "async",
{
.in = (const char *[]) {
"Interface",
"ProtocolVersion",
"Host",
"NumberOfRepetitions",
"Timeout",
"DataBlockSize",
"DSCP",
NULL
},
.out = (const char *[]) {
"Status",
"IPAddressUsed",
"SuccessCount",
"FailureCount",
"AverageResponseTime",
"MinimumResponseTime",
"MaximumResponseTime",
"AverageResponseTimeDetailed",
"MinimumResponseTimeDetailed",
"MaximumResponseTimeDetailed",
NULL
}
}
},
{
"Device.IP.Diagnostics.TraceRoute", ip_diagnostics_traceroute, "async",
{
.in = (const char *[]) {
"Interface",
"ProtocolVersion",
"Host",
"NumberOfTries",
"Timeout",
"DataBlockSize",
"DSCP",
"MaxHopCount",
NULL
},
.out = (const char *[]) {
"Status",
"IPAddressUsed",
"ResponseTime",
NULL
}
}
},
{
"Device.IP.Diagnostics.DownloadDiagnostics", ip_diagnostics_download, "async",
{
.in = (const char *[]) {
"Interface",
"DownloadURL",
"DSCP",
"EthernetPriority",
"TimeBasedTestDuration",
"TimeBasedTestMeasurementInterval",
"TimeBasedTestMeasurementOffset",
"ProtocolVersion",
"NumberOfConnections",
"EnablePerConnectionResults",
NULL
},
.out = (const char *[]) {
"Status",
"IPAddressUsed",
"ROMTime",
"BOMTime",
"EOMTime",
"TestBytesReceived",
"TotalBytesReceived",
"TotalBytesSent",
"TestBytesReceivedUnderFullLoading",
"TotalBytesReceivedUnderFullLoading",
"TotalBytesSentUnderFullLoading",
"PeriodOfFullLoading",
"TCPOpenRequestTime",
"TCPOpenResponseTime",
NULL
}
}
},
{
"Device.IP.Diagnostics.UploadDiagnostics", ip_diagnostics_upload, "async",
{
.in = (const char *[]) {
"Interface",
"UploadURL",
"DSCP",
"EthernetPriority",
"TestFileLength",
"TimeBasedTestDuration",
"TimeBasedTestMeasurementInterval",
"TimeBasedTestMeasurementOffset",
"ProtocolVersion",
"NumberOfConnections",
"EnablePerConnectionResults",
NULL
},
.out = (const char *[]) {
"Status",
"IPAddressUsed",
"ROMTime",
"BOMTime",
"EOMTime",
"TestBytesSent",
"TotalBytesReceived",
"TotalBytesSent",
"TestBytesSentUnderFullLoading",
"TotalBytesReceivedUnderFullLoading",
"TotalBytesSentUnderFullLoading",
"PeriodOfFullLoading",
"TCPOpenRequestTime",
"TCPOpenResponseTime",
NULL
}
}
},
{
"Device.IP.Diagnostics.UDPEchoDiagnostics", ip_diagnostics_udpecho, "async",
{
.in = (const char *[]) {
"Interface",
"Host",
"Port",
"NumberOfRepetitions",
"Timeout",
"DataBlockSize",
"DSCP",
"InterTransmissionTime",
"ProtocolVersion",
"EnableIndividualPacketResults",
NULL
},
.out = (const char *[]) {
"Status",
"IPAddressUsed",
"SuccessCount",
"FailureCount",
"AverageResponseTime",
"MinimumResponseTime",
"MaximumResponseTime",
NULL
}
}
},
{
"Device.IP.Diagnostics.ServerSelectionDiagnostics", ip_diagnostics_serverselection, "async",
{
.in = (const char *[]) {
"Interface",
"ProtocolVersion",
"Protocol",
"HostList",
"NumberOfRepetitions",
"Timeout",
NULL
},
.out = (const char *[]) {
"Status",
"FastestHost",
"MinimumResponseTime",
"AverageResponseTime",
"MaximumResponseTime",
"IPAddressUsed",
NULL
}
}
},
{
"Device.DNS.Diagnostics.NSLookupDiagnostics", ip_diagnostics_nslookup, "async",
{
.in = (const char *[]) {
"HostName",
"Interface",
"DNSServer",
"Timeout",
"NumberOfRepetitions",
NULL
},
.out = (const char *[]) {
"Status",
"AnswerType",
"HostNameReturned",
"IPAddresses",
"DNSServerIP",
"ResponseTime",
NULL
}
}
},
{
"Device.SoftwareModules.ExecEnv.*.Reset", swmodules_exec_env_reset, "sync"
},
{
"Device.SoftwareModules.InstallDU", swmodules_install_du, "async",
{
.in = (const char *[]) {
"URL",
"UUID",
"Username",
"Password",
"ExecutionEnvRef",
NULL
}
}
},
{
"Device.SoftwareModules.DeploymentUnit.*.Update", swmodules_update_du, "async",
{
.in = (const char *[]) {
"URL",
"Username",
"Password",
NULL
}
}
},
{
"Device.SoftwareModules.DeploymentUnit.*.Uninstall", swmodules_uninstall_du, "async"
}
};
void operate_list_cmds(struct dmctx *dmctx)
{
char *param, *type;
const operation_args *args;
const size_t n = ARRAY_SIZE(operate_helper);
size_t i;
struct op_cmd *save_pointer = NULL;
if (dynamic_operate) save_pointer = dynamic_operate;
for(i = 0; i < n; i++) {
param = dmstrdup(operate_helper[i].name);
type = (char *)operate_helper[i].type;
args = &operate_helper[i].args;
add_list_parameter(dmctx, param, (char *)args, type, NULL);
}
for (; (dynamic_operate && dynamic_operate->name); dynamic_operate++) {
param = dmstrdup(dynamic_operate->name);
type = (char *)dynamic_operate->type;
args = &dynamic_operate->args;
add_list_parameter(dmctx, param, (char *)args, type, NULL);
}
if (save_pointer)dynamic_operate = save_pointer;
}
static opr_ret_t do_operate(struct dmctx *dmctx, char *path, operation func, const char *input)
{
json_object *j_input;
opr_ret_t rc;
if (input)
j_input = json_tokener_parse(input);
else
j_input = NULL;
rc = func(dmctx, path, j_input);
json_object_put(j_input);
return rc;
}
opr_ret_t operate_on_node(struct dmctx *dmctx, char *path, char *input)
{
struct op_cmd *save_pointer = NULL;
const struct op_cmd *op;
const size_t n = ARRAY_SIZE(operate_helper);
size_t i;
if (dynamic_operate)
save_pointer = dynamic_operate;
for (i = 0; i < n; i++) {
op = &operate_helper[i];
if (match(path, op->name))
return do_operate(dmctx, path, op->opt, input);
}
for (; (dynamic_operate && dynamic_operate->name); dynamic_operate++) {
if (match(path, dynamic_operate->name)) {
opr_ret_t res = do_operate(dmctx, path, dynamic_operate->opt, input);
if (save_pointer) dynamic_operate = save_pointer;
return res;
}
}
if (save_pointer)
dynamic_operate = save_pointer;
return CMD_NOT_FOUND;
}