mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
bbfdmd: Add support for cli command
This commit is contained in:
parent
96b305926f
commit
8d00536689
18 changed files with 957 additions and 249 deletions
109
bbfdmd/README.md
109
bbfdmd/README.md
|
|
@ -41,6 +41,115 @@ When a ubus method is called it first fills `usp_data_t` structure with the nece
|
|||
|
||||
In short, it covers/supports all methods introduced in `TR-069` and `TR-369` by using the `bbf_entry_method` API from `libbbfdm-api` with the differents methods and the existing data-model available with `libbbfdm`.
|
||||
|
||||
## BBFDMD Command Line Arguments
|
||||
|
||||
`bbfdmd` supports two modes, a daemon mode (seen above) and a command (or CLI) mode, which supports interactively querying the data model and setting values in the configuration via the data model.
|
||||
|
||||
Actually, the CLI mode is an utility to simplify the interaction with data model that gives to customer the visibility to expose any kind of data model (which can be a `DotSo` plugin, `JSON` plugin, `UBUS` command or `UNIX` socket) with a specific format (`CLI` or `JSON`).
|
||||
|
||||
The CLI mode is specified with the `-c` option and can be run using `cwmp` or `usp` protocol.
|
||||
|
||||
All of the above configurations should be done by json file which can be located anywhere, just don't forget to pass the path with `-I` option.
|
||||
|
||||
```console
|
||||
root@iopsys:~# bbfdmd -I /tmp/test.json -c help
|
||||
Valid commands:
|
||||
help
|
||||
get [path-expr]
|
||||
set [path-expr] [value]
|
||||
add [object]
|
||||
del [path-expr]
|
||||
instances [path-expr]
|
||||
schema [path-expr]
|
||||
|
||||
```
|
||||
|
||||
Below is an example of json file:
|
||||
|
||||
```json
|
||||
{
|
||||
"client": {
|
||||
"config": {
|
||||
"proto": "usp", // usp, cwmp
|
||||
"instance_mode": 0 // 0:number, 1:alias
|
||||
},
|
||||
"input": {
|
||||
"type": "UBUS", // JSON, UBUS, DotSO, UNIX
|
||||
"name": "bbfdm"
|
||||
},
|
||||
"output": {
|
||||
"type": "CLI" // CLI, JSON
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> NOTE: If `-I` option is not passed when starting `bbfdmd`, so configuration options will be loaded from the default [INPUT.JSON](../../json/input.json) located in '/etc/bbfdm/input.json'.
|
||||
|
||||
* To see a list of arguments supported by `bbfdmd` use:
|
||||
|
||||
```console
|
||||
root@iopsys:~# bbfdmd -h
|
||||
Usage: bbfdmd [options]
|
||||
|
||||
options:
|
||||
-s <socket path> ubus socket
|
||||
-I <json path> json input configuration
|
||||
-c <command input> Run cli command
|
||||
-h Displays this help
|
||||
|
||||
```
|
||||
|
||||
* To see a list of commands supported by `bbfdmd` in CLI mode use:
|
||||
|
||||
```console
|
||||
root@iopsys:~# bbfdmd -c help
|
||||
Valid commands:
|
||||
help
|
||||
get [path-expr]
|
||||
set [path-expr] [value]
|
||||
add [object]
|
||||
del [path-expr]
|
||||
instances [path-expr]
|
||||
schema [path-expr]
|
||||
|
||||
```
|
||||
|
||||
* To see the currently implemented data model use:
|
||||
|
||||
```console
|
||||
$ bbfdmd -c schema Device.
|
||||
```
|
||||
|
||||
* To query the value of a parameter use:
|
||||
|
||||
```console
|
||||
root@iopsys:~# bbfdmd -c get Device.Time.
|
||||
Device.Time.Enable => 0
|
||||
Device.Time.Status => Disabled
|
||||
Device.Time.NTPServer1 => ntp1.sth.netnod.se
|
||||
Device.Time.NTPServer2 => ntp1.gbg.netnod.se
|
||||
Device.Time.NTPServer3 =>
|
||||
Device.Time.NTPServer4 =>
|
||||
Device.Time.NTPServer5 =>
|
||||
Device.Time.CurrentLocalTime => 2023-04-22T13:45:01+00:00
|
||||
Device.Time.LocalTimeZone => CET-1CEST,M3.5.0,M10.5.0/3
|
||||
root@iopsys:~# bbfdmd -c get Device.WiFi.SSID.1.SSID
|
||||
Device.WiFi.SSID.1.SSID => test-5g
|
||||
```
|
||||
|
||||
> Note: The "parameter" may contain wildcard intance and partial paths.
|
||||
|
||||
|
||||
* To set the value of a data model parameter use:
|
||||
|
||||
```console
|
||||
$ bbfdmd -c set "parameter" "value"
|
||||
```
|
||||
|
||||
> Note: The CLI mode also supports adding and deleting instances of data model objects and supported instances.
|
||||
|
||||
|
||||
## Important topics
|
||||
* [UBUS methods](../docs/guide/bbfdm_ubus_methods.md)
|
||||
* [UBUS Errors](../docs/guide/bbfdm_ubus_errors.md)
|
||||
|
|
|
|||
|
|
@ -12,5 +12,6 @@ ENDIF()
|
|||
|
||||
FILE(GLOB BBF_SOURCES *.c)
|
||||
ADD_EXECUTABLE(bbfdmd ${BBF_SOURCES})
|
||||
TARGET_LINK_LIBRARIES(bbfdmd uci ubus ubox blobmsg_json bbfdm-api bbfdm)
|
||||
TARGET_LINK_LIBRARIES(bbfdmd ubus ubox blobmsg_json bbfdm-api bbfdm)
|
||||
INSTALL(TARGETS bbfdmd DESTINATION usr/sbin)
|
||||
INSTALL(FILES ../../json/input.json DESTINATION etc/bbfdm)
|
||||
|
|
|
|||
|
|
@ -39,12 +39,16 @@
|
|||
#include "events.h"
|
||||
#include "pretty_print.h"
|
||||
#include "get_helper.h"
|
||||
#include "cli.h"
|
||||
#include "libbbfdm-api/dmentry.h"
|
||||
#include "libbbfdm-api/dmjson.h"
|
||||
|
||||
#define USP_SUBPROCESS_DEPTH (2)
|
||||
#define BBF_SCHEMA_UPDATE_TIMEOUT (60 * 1000)
|
||||
#define BBF_INSTANCES_UPDATE_TIMEOUT (25 * 1000)
|
||||
|
||||
#define DEFAULT_JSON_INPUT "/etc/bbfdm/input.json"
|
||||
|
||||
// Global variables
|
||||
static unsigned int g_refresh_time = BBF_INSTANCES_UPDATE_TIMEOUT;
|
||||
static int g_subprocess_level = USP_SUBPROCESS_DEPTH;
|
||||
|
|
@ -69,8 +73,10 @@ static void usage(char *prog)
|
|||
fprintf(stderr, "Usage: %s [options]\n", prog);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "options:\n");
|
||||
fprintf(stderr, " -s <socket path> ubus socket\n");
|
||||
fprintf(stderr, " -t <timeout> Transaction timeout in sec\n");
|
||||
fprintf(stderr, " -s <socket path> ubus socket\n");
|
||||
fprintf(stderr, " -I <json path> json input configuration\n");
|
||||
fprintf(stderr, " -c <command input> Run cli command\n");
|
||||
fprintf(stderr, " -h Displays this help\n");
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
|
|
@ -101,37 +107,6 @@ static bool is_subprocess_required(const char *path)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int get_proto_type(struct blob_attr *proto)
|
||||
{
|
||||
int type = BBFDM_BOTH;
|
||||
|
||||
if (proto) {
|
||||
const char *val = blobmsg_get_string(proto);
|
||||
|
||||
if (is_str_eq("cwmp", val))
|
||||
type = BBFDM_CWMP;
|
||||
else if (is_str_eq("usp", val))
|
||||
type = BBFDM_USP;
|
||||
else
|
||||
type = BBFDM_BOTH;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static int get_instance_mode(struct blob_attr *ins)
|
||||
{
|
||||
int instance_mode = INSTANCE_MODE_NUMBER;
|
||||
|
||||
if (ins)
|
||||
instance_mode = blobmsg_get_u32(ins);
|
||||
|
||||
if (instance_mode > INSTANCE_MODE_ALIAS)
|
||||
instance_mode = INSTANCE_MODE_NUMBER;
|
||||
|
||||
return instance_mode;
|
||||
}
|
||||
|
||||
static void fill_optional_data(usp_data_t *data, struct blob_attr *msg)
|
||||
{
|
||||
struct blob_attr *attr;
|
||||
|
|
@ -141,11 +116,16 @@ static void fill_optional_data(usp_data_t *data, struct blob_attr *msg)
|
|||
return;
|
||||
|
||||
blobmsg_for_each_attr(attr, msg, rem) {
|
||||
if (is_str_eq(blobmsg_name(attr), "proto"))
|
||||
data->bbf_ctx.dm_type = get_proto_type(attr);
|
||||
|
||||
if (is_str_eq(blobmsg_name(attr), "instance_mode"))
|
||||
data->bbf_ctx.instance_mode = get_instance_mode(attr);
|
||||
if (is_str_eq(blobmsg_name(attr), "proto")) {
|
||||
const char *val = blobmsg_get_string(attr);
|
||||
data->bbf_ctx.dm_type = get_proto_type(val);
|
||||
}
|
||||
|
||||
if (is_str_eq(blobmsg_name(attr), "instance_mode")) {
|
||||
int instance_mode = blobmsg_get_u32(attr);
|
||||
data->bbf_ctx.instance_mode = get_instance_mode(instance_mode);
|
||||
}
|
||||
|
||||
if (is_str_eq(blobmsg_name(attr), "transaction_id"))
|
||||
data->trans_id = blobmsg_get_u32(attr);
|
||||
|
|
@ -1185,82 +1165,69 @@ static void periodic_instance_updater(struct uloop_timeout *t)
|
|||
fork_instance_checker(u);
|
||||
}
|
||||
|
||||
static int usp_get_config(void)
|
||||
static int bbfdm_load_config(const char *json_path)
|
||||
{
|
||||
struct uci_context *ctx = NULL;
|
||||
struct uci_package *pkg = NULL;
|
||||
struct uci_element *e = NULL;
|
||||
json_object *json_obj = NULL;
|
||||
char *opt_val = NULL;
|
||||
|
||||
ctx = uci_alloc_context();
|
||||
if (!ctx)
|
||||
if (!json_path || !strlen(json_path))
|
||||
return -1;
|
||||
|
||||
if (uci_load(ctx, "bbfdm", &pkg)) {
|
||||
uci_free_context(ctx);
|
||||
json_obj = json_object_from_file(json_path);
|
||||
if (!json_obj)
|
||||
return -1;
|
||||
|
||||
opt_val = dmjson_get_value(json_obj, 3, "daemon", "config", "loglevel");
|
||||
if (opt_val && strlen(opt_val)) {
|
||||
uint8_t log_level = (uint8_t) strtoul(opt_val, NULL, 10);
|
||||
set_debug_level(log_level);
|
||||
}
|
||||
|
||||
uci_foreach_element(&pkg->sections, e) {
|
||||
|
||||
struct uci_section *s = uci_to_section(e);
|
||||
if (s == NULL || s->type == NULL)
|
||||
continue;
|
||||
|
||||
if (strcmp(s->type, "bbfdmd") == 0) {
|
||||
struct uci_option *opn = NULL;
|
||||
|
||||
opn = uci_lookup_option(ctx, s, "loglevel");
|
||||
if (opn) {
|
||||
uint8_t log_level = (uint8_t) strtoul(opn->v.string, NULL, 10);
|
||||
set_debug_level(log_level);
|
||||
}
|
||||
|
||||
opn = uci_lookup_option(ctx, s, "subprocess_level");
|
||||
if (opn) {
|
||||
g_subprocess_level = (unsigned int) strtoul(opn->v.string, NULL, 10);
|
||||
}
|
||||
|
||||
opn = uci_lookup_option(ctx, s, "refresh_time");
|
||||
if (opn) {
|
||||
unsigned int refresh_time = (unsigned int) strtoul(opn->v.string, NULL, 10);
|
||||
g_refresh_time = refresh_time * 1000;
|
||||
}
|
||||
}
|
||||
opt_val = dmjson_get_value(json_obj, 3, "daemon", "config", "refresh_time");
|
||||
if (opt_val && strlen(opt_val)) {
|
||||
unsigned int refresh_time = (unsigned int) strtoul(opt_val, NULL, 10);
|
||||
g_refresh_time = refresh_time * 1000;
|
||||
}
|
||||
|
||||
uci_unload(ctx, pkg);
|
||||
uci_free_context(ctx);
|
||||
opt_val = dmjson_get_value(json_obj, 3, "daemon", "config", "transaction_timeout");
|
||||
if (opt_val && strlen(opt_val)) {
|
||||
int trans_timeout = (int) strtol(opt_val, NULL, 10);
|
||||
configure_transaction_timeout(trans_timeout);
|
||||
}
|
||||
|
||||
opt_val = dmjson_get_value(json_obj, 3, "daemon", "config", "subprocess_level");
|
||||
if (opt_val && strlen(opt_val)) {
|
||||
g_subprocess_level = (unsigned int) strtoul(opt_val, NULL, 10);
|
||||
}
|
||||
|
||||
json_object_put(json_obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usp_init(struct usp_context *u)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = usp_get_config();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
INFO("Registering ubus objects....");
|
||||
ret = ubus_add_object(&u->ubus_ctx, &bbf_object);
|
||||
|
||||
return ret;
|
||||
return ubus_add_object(&u->ubus_ctx, &bbf_object);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct usp_context usp_ctx;
|
||||
const char *input_json = DEFAULT_JSON_INPUT;
|
||||
const char *ubus_socket = NULL;
|
||||
int ret = 0, ch;
|
||||
int err = 0, ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "hs:t:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "hs:I:c:")) != -1) {
|
||||
switch (ch) {
|
||||
case 's':
|
||||
ubus_socket = optarg;
|
||||
break;
|
||||
case 't':
|
||||
configure_transaction_timeout(strtol(optarg, NULL, 10));
|
||||
case 'I':
|
||||
input_json = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
err = bbfdm_cli_exec_command(input_json, argc-optind+1, &argv[optind-1]);
|
||||
exit(err);
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit(0);
|
||||
|
|
@ -1269,6 +1236,12 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
err = bbfdm_load_config(input_json);
|
||||
if (err != UBUS_STATUS_OK) {
|
||||
fprintf(stderr, "Failed to load bbfdm config from json file '%s'\n", input_json);
|
||||
return -1;
|
||||
}
|
||||
|
||||
openlog("bbfdm", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
|
||||
|
||||
memset(&usp_ctx, 0, sizeof(struct usp_context));
|
||||
|
|
@ -1279,26 +1252,23 @@ int main(int argc, char **argv)
|
|||
|
||||
uloop_init();
|
||||
|
||||
ret = ubus_connect_ctx(&usp_ctx.ubus_ctx, ubus_socket);
|
||||
if (ret != UBUS_STATUS_OK) {
|
||||
err = ubus_connect_ctx(&usp_ctx.ubus_ctx, ubus_socket);
|
||||
if (err != UBUS_STATUS_OK) {
|
||||
fprintf(stderr, "Failed to connect to ubus\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
signal_init();
|
||||
|
||||
ret = register_events_to_ubus(&usp_ctx.ubus_ctx, &usp_ctx.event_handlers);
|
||||
if (ret != 0) {
|
||||
err = register_events_to_ubus(&usp_ctx.ubus_ctx, &usp_ctx.event_handlers);
|
||||
if (err != 0)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ubus_add_uloop(&usp_ctx.ubus_ctx);
|
||||
|
||||
ret = usp_init(&usp_ctx);
|
||||
if (ret != UBUS_STATUS_OK) {
|
||||
ret = UBUS_STATUS_UNKNOWN_ERROR;
|
||||
err = usp_init(&usp_ctx);
|
||||
if (err != UBUS_STATUS_OK)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
usp_ctx.schema_timer.cb = periodic_schema_updater;
|
||||
uloop_timeout_set(&usp_ctx.schema_timer, BBF_SCHEMA_UPDATE_TIMEOUT);
|
||||
|
|
@ -1317,5 +1287,5 @@ exit:
|
|||
usp_cleanup(&usp_ctx);
|
||||
closelog();
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
677
bbfdmd/src/cli.c
Normal file
677
bbfdmd/src/cli.c
Normal file
|
|
@ -0,0 +1,677 @@
|
|||
/*
|
||||
* cli.c: Cli command for bbfdmd
|
||||
*
|
||||
* Copyright (C) 2023 iopsys Software Solutions AB. All rights reserved.
|
||||
*
|
||||
* Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "libbbfdm-api/dmapi.h"
|
||||
#include "libbbfdm-api/dmjson.h"
|
||||
#include "libbbfdm-api/dmentry.h"
|
||||
|
||||
#define UNUSED __attribute__((unused))
|
||||
|
||||
typedef struct {
|
||||
struct dmctx bbf_ctx;
|
||||
unsigned int instance_mode;
|
||||
unsigned int proto;
|
||||
char in_type[128];
|
||||
char in_name[128];
|
||||
char out_type[128];
|
||||
char *cmd;
|
||||
bool ubus_status;
|
||||
} client_data_t;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int num_args;
|
||||
int (*exec_cmd)(client_data_t *client_data, char *argv[]);
|
||||
char *usage;
|
||||
} cli_cmd_t;
|
||||
|
||||
static int cli_exec_help(client_data_t *client_data UNUSED, char *argv[] UNUSED);
|
||||
static int cli_exec_get(client_data_t *client_data, char *argv[]);
|
||||
static int cli_exec_set(client_data_t *client_data, char *argv[]);
|
||||
static int cli_exec_add(client_data_t *client_data, char *argv[]);
|
||||
static int cli_exec_del(client_data_t *client_data, char *argv[]);
|
||||
static int cli_exec_instances(client_data_t *client_data, char *argv[]);
|
||||
static int cli_exec_schema(client_data_t *client_data, char *argv[]);
|
||||
|
||||
cli_cmd_t cli_commands[] = {
|
||||
// Name NumArgs Exec callback Usage String
|
||||
{ "help", 0, cli_exec_help, "help" },
|
||||
{ "get", 1, cli_exec_get, "get [path-expr]" },
|
||||
{ "set", 2, cli_exec_set, "set [path-expr] [value]"},
|
||||
{ "add", 1, cli_exec_add, "add [object]"},
|
||||
{ "del", 1, cli_exec_del, "del [path-expr]"},
|
||||
{ "instances", 1, cli_exec_instances, "instances [path-expr]" },
|
||||
{ "schema", 1, cli_exec_schema, "schema [path-expr]"},
|
||||
};
|
||||
|
||||
typedef void (*__ubus_cb)(struct ubus_request *req, int type, struct blob_attr *msg);
|
||||
|
||||
static int bbfdm_ubus_invoke(const char *obj, const char *method, struct blob_attr *msg, __ubus_cb bbfdm_ubus_callback, void *callback_arg)
|
||||
{
|
||||
struct ubus_context *ctx = NULL;
|
||||
uint32_t id;
|
||||
int rc = 0;
|
||||
|
||||
ctx = ubus_connect(NULL);
|
||||
if (ctx == NULL) {
|
||||
printf("Can't create ubus context\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ubus_lookup_id(ctx, obj, &id))
|
||||
rc = ubus_invoke(ctx, id, method, msg, bbfdm_ubus_callback, callback_arg, 20000);
|
||||
else
|
||||
rc = -1;
|
||||
|
||||
|
||||
ubus_free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct blob_attr *get_results_array(struct blob_attr *msg)
|
||||
{
|
||||
struct blob_attr *tb[1] = {0};
|
||||
const struct blobmsg_policy p[1] = {
|
||||
{ "results", BLOBMSG_TYPE_ARRAY }
|
||||
};
|
||||
|
||||
if (msg == NULL)
|
||||
return NULL;
|
||||
|
||||
blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg));
|
||||
|
||||
return tb[0];
|
||||
}
|
||||
|
||||
static void __ubus_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
|
||||
{
|
||||
struct blob_attr *cur = NULL;
|
||||
bool print_msg = false;
|
||||
int rem = 0;
|
||||
const struct blobmsg_policy p[6] = {
|
||||
{ "path", BLOBMSG_TYPE_STRING },
|
||||
{ "data", BLOBMSG_TYPE_STRING },
|
||||
{ "type", BLOBMSG_TYPE_STRING },
|
||||
{ "fault", BLOBMSG_TYPE_INT32 },
|
||||
{ "input", BLOBMSG_TYPE_ARRAY },
|
||||
{ "output", BLOBMSG_TYPE_ARRAY },
|
||||
};
|
||||
|
||||
if (msg == NULL || req == NULL)
|
||||
return;
|
||||
|
||||
client_data_t *client_data = (client_data_t *)req->priv;
|
||||
struct blob_attr *parameters = get_results_array(msg);
|
||||
|
||||
if (parameters == NULL) {
|
||||
client_data->ubus_status = false;
|
||||
return;
|
||||
}
|
||||
|
||||
blobmsg_for_each_attr(cur, parameters, rem) {
|
||||
struct blob_attr *tb[6] = {0};
|
||||
|
||||
blobmsg_parse(p, 6, tb, blobmsg_data(cur), blobmsg_len(cur));
|
||||
|
||||
char *name = tb[0] ? blobmsg_get_string(tb[0]) : "";
|
||||
char *data = tb[1] ? blobmsg_get_string(tb[1]) : "";
|
||||
|
||||
if (tb[3]) {
|
||||
printf("ERROR: %u retrieving %s\n", blobmsg_get_u32(tb[3]), name);
|
||||
client_data->ubus_status = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(client_data->cmd, "get") == 0)
|
||||
printf("%s => %s\n", name, data);
|
||||
else if (strcmp(client_data->cmd, "set") == 0) {
|
||||
printf("%s => Set value is successfully done\n", name);
|
||||
} else if (strcmp(client_data->cmd, "add") == 0) {
|
||||
printf("Added %s%s.\n", name, data);
|
||||
} else if (strcmp(client_data->cmd, "del") == 0) {
|
||||
printf("Deleted %s\n", name);
|
||||
} else if (strcmp(client_data->cmd, "instances") == 0) {
|
||||
printf("%s\n", name);
|
||||
} else if (strcmp(client_data->cmd, "schema") == 0) {
|
||||
char *type = tb[2] ? blobmsg_get_string(tb[2]) : "";
|
||||
int cmd = get_dm_type(type);
|
||||
|
||||
if (print_msg == false) {
|
||||
printf("\nDumping %s Schema...\n\n", name);
|
||||
print_msg = true;
|
||||
}
|
||||
|
||||
printf("%s\n", name);
|
||||
|
||||
if (cmd == DMT_COMMAND) {
|
||||
struct blob_attr *input = tb[4];
|
||||
struct blob_attr *output = tb[5];
|
||||
struct blob_attr *in_cur = NULL, *out_cur = NULL;
|
||||
int in_rem = 0, out_rem = 0;
|
||||
|
||||
if (input) {
|
||||
blobmsg_for_each_attr(in_cur, input, in_rem) {
|
||||
struct blob_attr *in_tb[6] = {0};
|
||||
|
||||
blobmsg_parse(p, 6, in_tb, blobmsg_data(in_cur), blobmsg_len(in_cur));
|
||||
|
||||
char *arg = in_tb[0] ? blobmsg_get_string(in_tb[0]) : "";
|
||||
printf("%s input:%s\n", name, arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (output) {
|
||||
blobmsg_for_each_attr(out_cur, output, out_rem) {
|
||||
struct blob_attr *out_tb[6] = {0};
|
||||
|
||||
blobmsg_parse(p, 6, out_tb, blobmsg_data(out_cur), blobmsg_len(out_cur));
|
||||
|
||||
char *arg = out_tb[0] ? blobmsg_get_string(out_tb[0]) : "";
|
||||
printf("%s output:%s\n", name, arg);
|
||||
}
|
||||
}
|
||||
} else if (cmd == DMT_EVENT) {
|
||||
struct blob_attr *input = tb[4];
|
||||
struct blob_attr *in_cur = NULL;
|
||||
int in_rem = 0;
|
||||
|
||||
if (input) {
|
||||
blobmsg_for_each_attr(in_cur, input, in_rem) {
|
||||
struct blob_attr *in_tb[6] = {0};
|
||||
|
||||
blobmsg_parse(p, 6, in_tb, blobmsg_data(in_cur), blobmsg_len(in_cur));
|
||||
|
||||
char *arg = in_tb[0] ? blobmsg_get_string(in_tb[0]) : "";
|
||||
printf("%s event_arg:%s\n", name, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
client_data->ubus_status = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int in_ubus_out_cli_exec_cmd(client_data_t *client_data, const char *path, const char *value)
|
||||
{
|
||||
struct blob_buf b = {0};
|
||||
void *table = NULL;
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
memset(&b, 0, sizeof(struct blob_buf));
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
|
||||
blobmsg_add_string(&b, "path", path);
|
||||
if (value) blobmsg_add_string(&b, "value", value);
|
||||
|
||||
table = blobmsg_open_table(&b, "optional");
|
||||
blobmsg_add_string(&b, "proto", (client_data->proto == BBFDM_CWMP) ? "cwmp" : "usp");
|
||||
blobmsg_add_string(&b, "format", "raw");
|
||||
blobmsg_add_u32(&b, "instance_mode", client_data->instance_mode);
|
||||
blobmsg_close_table(&b, table);
|
||||
|
||||
int e = bbfdm_ubus_invoke(client_data->in_name, client_data->cmd, b.head, __ubus_callback, client_data);
|
||||
|
||||
if (e < 0) {
|
||||
printf("ERROR: ubus invoke for [object:%s method:%s] exit with error(%d)\n", client_data->in_name, client_data->cmd, e);
|
||||
err = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (client_data->ubus_status == false) {
|
||||
printf("ERROR: ubus call for [object:%s method:%s] exit with error\n", client_data->in_name, client_data->cmd);
|
||||
err = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
blob_buf_free(&b);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bbfdm_load_client_config(const char *json_path, client_data_t *client_data)
|
||||
{
|
||||
json_object *json_obj = NULL;
|
||||
char *opt_val = NULL;
|
||||
|
||||
if (!json_path || !strlen(json_path)) {
|
||||
printf("ERROR: json file not specified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
json_obj = json_object_from_file(json_path);
|
||||
if (!json_obj) {
|
||||
printf("ERROR: not possible to load json file (%s)\n", json_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
opt_val = dmjson_get_value(json_obj, 3, "client", "config", "proto");
|
||||
if (opt_val && strlen(opt_val)) {
|
||||
client_data->proto = get_proto_type(opt_val);
|
||||
} else {
|
||||
client_data->proto = BBFDM_BOTH;
|
||||
}
|
||||
|
||||
opt_val = dmjson_get_value(json_obj, 3, "client", "config", "instance_mode");
|
||||
if (opt_val && strlen(opt_val)) {
|
||||
int inst_mode = (int) strtol(opt_val, NULL, 10);
|
||||
client_data->instance_mode = get_instance_mode(inst_mode);
|
||||
} else {
|
||||
client_data->instance_mode = INSTANCE_MODE_NUMBER;
|
||||
}
|
||||
|
||||
opt_val = dmjson_get_value(json_obj, 3, "client", "input", "type");
|
||||
if (opt_val && strlen(opt_val)) {
|
||||
snprintf(client_data->in_type, sizeof(client_data->in_type), "%s", opt_val);
|
||||
} else {
|
||||
printf("ERROR: [client.input.type] not specified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
opt_val = dmjson_get_value(json_obj, 3, "client", "input", "name");
|
||||
if (opt_val && strlen(opt_val)) {
|
||||
snprintf(client_data->in_name, sizeof(client_data->in_name), "%s", opt_val);
|
||||
} else {
|
||||
printf("ERROR: [client.input.name] not specified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
opt_val = dmjson_get_value(json_obj, 3, "client", "output", "type");
|
||||
if (opt_val && strlen(opt_val)) {
|
||||
snprintf(client_data->out_type, sizeof(client_data->out_type), "%s", opt_val);
|
||||
} else {
|
||||
printf("ERROR: [client.output.type] not specified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
json_object_put(json_obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cli_exec_help(client_data_t *client_data UNUSED, char *argv[] UNUSED)
|
||||
{
|
||||
cli_cmd_t *cli_cmd;
|
||||
|
||||
printf("Valid commands:\n");
|
||||
|
||||
// Print out the help usage of all commands
|
||||
for (size_t i = 0; i < ARRAY_SIZE(cli_commands); i++) {
|
||||
cli_cmd = &cli_commands[i];
|
||||
printf(" %s\n", cli_cmd->usage);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int in_dotso_out_cli_exec_get(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
client_data->bbf_ctx.in_param = argv[0];
|
||||
|
||||
err = bbf_entry_method(&client_data->bbf_ctx, BBF_GET_VALUE);
|
||||
if (!err) {
|
||||
struct dm_parameter *n;
|
||||
|
||||
list_for_each_entry(n, &client_data->bbf_ctx.list_parameter, list) {
|
||||
printf("%s => %s\n", n->name, n->data);
|
||||
}
|
||||
} else {
|
||||
printf("ERROR: %d retrieving %s\n", err, client_data->bbf_ctx.in_param);
|
||||
err = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_ubus_out_cli_exec_get(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]);
|
||||
}
|
||||
|
||||
static int cli_exec_get(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
if (strcasecmp(client_data->in_type, "DotSO") == 0)
|
||||
err = in_dotso_out_cli_exec_get(client_data, argv);
|
||||
else if (strcasecmp(client_data->in_type, "UBUS") == 0)
|
||||
err = in_ubus_out_cli_exec_get(client_data, argv);
|
||||
else
|
||||
err = EXIT_FAILURE;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_dotso_out_cli_exec_set(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
client_data->bbf_ctx.in_param = argv[0];
|
||||
client_data->bbf_ctx.in_value = argv[1];
|
||||
|
||||
err = bbf_entry_method(&client_data->bbf_ctx, BBF_SET_VALUE);
|
||||
if (!err) {
|
||||
printf("%s => Set value is successfully done\n", client_data->bbf_ctx.in_param);
|
||||
bbf_entry_restart_services(NULL, true);
|
||||
} else {
|
||||
printf("ERROR: %d retrieving %s => %s\n", err, client_data->bbf_ctx.in_param, client_data->bbf_ctx.in_value);
|
||||
bbf_entry_revert_changes(NULL);
|
||||
err = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_ubus_out_cli_exec_set(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]);
|
||||
}
|
||||
|
||||
static int cli_exec_set(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
if (strcasecmp(client_data->in_type, "DotSO") == 0)
|
||||
err = in_dotso_out_cli_exec_set(client_data, argv);
|
||||
else if (strcasecmp(client_data->in_type, "UBUS") == 0)
|
||||
err = in_ubus_out_cli_exec_set(client_data, argv);
|
||||
else
|
||||
err = EXIT_FAILURE;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_dotso_out_cli_exec_add(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
client_data->bbf_ctx.in_param = argv[0];
|
||||
|
||||
err = bbf_entry_method(&client_data->bbf_ctx, BBF_ADD_OBJECT);
|
||||
if (!err) {
|
||||
printf("Added %s%s.\n", client_data->bbf_ctx.in_param, client_data->bbf_ctx.addobj_instance);
|
||||
bbf_entry_restart_services(NULL, true);
|
||||
} else {
|
||||
printf("ERROR: %d retrieving %s\n", err, client_data->bbf_ctx.in_param);
|
||||
bbf_entry_revert_changes(NULL);
|
||||
err = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_ubus_out_cli_exec_add(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]);
|
||||
}
|
||||
|
||||
static int cli_exec_add(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
if (strcasecmp(client_data->in_type, "DotSO") == 0)
|
||||
err = in_dotso_out_cli_exec_add(client_data, argv);
|
||||
else if (strcasecmp(client_data->in_type, "UBUS") == 0)
|
||||
err = in_ubus_out_cli_exec_add(client_data, argv);
|
||||
else
|
||||
err = EXIT_FAILURE;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_dotso_out_cli_exec_del(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
client_data->bbf_ctx.in_param = argv[0];
|
||||
|
||||
err = bbf_entry_method(&client_data->bbf_ctx, BBF_DEL_OBJECT);
|
||||
if (!err) {
|
||||
printf("Deleted %s\n", client_data->bbf_ctx.in_param);
|
||||
bbf_entry_restart_services(NULL, true);
|
||||
} else {
|
||||
printf("ERROR: %d retrieving %s\n", err, client_data->bbf_ctx.in_param);
|
||||
bbf_entry_revert_changes(NULL);
|
||||
err = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_ubus_out_cli_exec_del(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]);
|
||||
}
|
||||
|
||||
static int cli_exec_del(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
if (strcasecmp(client_data->in_type, "DotSO") == 0)
|
||||
err = in_dotso_out_cli_exec_del(client_data, argv);
|
||||
else if (strcasecmp(client_data->in_type, "UBUS") == 0)
|
||||
err = in_ubus_out_cli_exec_del(client_data, argv);
|
||||
else
|
||||
err = EXIT_FAILURE;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_dotso_out_cli_exec_instances(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
client_data->bbf_ctx.in_param = argv[0];
|
||||
client_data->bbf_ctx.nextlevel = false;
|
||||
|
||||
err = bbf_entry_method(&client_data->bbf_ctx, BBF_INSTANCES);
|
||||
if (!err) {
|
||||
struct dm_parameter *n;
|
||||
|
||||
list_for_each_entry(n, &client_data->bbf_ctx.list_parameter, list) {
|
||||
printf("%s\n", n->name);
|
||||
}
|
||||
} else {
|
||||
printf("ERROR: %d retrieving %s\n", err, client_data->bbf_ctx.in_param);
|
||||
err = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_ubus_out_cli_exec_instances(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]);
|
||||
}
|
||||
|
||||
static int cli_exec_instances(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
if (strcasecmp(client_data->in_type, "DotSO") == 0)
|
||||
err = in_dotso_out_cli_exec_instances(client_data, argv);
|
||||
else if (strcasecmp(client_data->in_type, "UBUS") == 0)
|
||||
err = in_ubus_out_cli_exec_instances(client_data, argv);
|
||||
else
|
||||
err = EXIT_FAILURE;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_dotso_out_cli_exec_schema(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
client_data->bbf_ctx.in_param = argv[0];
|
||||
client_data->bbf_ctx.nextlevel = false;
|
||||
client_data->bbf_ctx.iscommand = true;
|
||||
client_data->bbf_ctx.isevent = true;
|
||||
client_data->bbf_ctx.isinfo = true;
|
||||
|
||||
err = bbf_entry_method(&client_data->bbf_ctx, BBF_SCHEMA);
|
||||
if (!err) {
|
||||
struct dm_parameter *n;
|
||||
|
||||
printf("\nDumping %s Schema...\n\n", client_data->bbf_ctx.in_param);
|
||||
|
||||
list_for_each_entry(n, &client_data->bbf_ctx.list_parameter, list) {
|
||||
int cmd = get_dm_type(n->type);
|
||||
|
||||
printf("%s\n", n->name);
|
||||
|
||||
if (cmd == DMT_COMMAND) {
|
||||
if (n->data) {
|
||||
const char **in, **out;
|
||||
operation_args *args;
|
||||
int i;
|
||||
|
||||
args = (operation_args *) n->data;
|
||||
in = args->in;
|
||||
if (in) {
|
||||
for (i = 0; in[i] != NULL; i++)
|
||||
printf("%s input:%s\n", n->name, in[i]);
|
||||
}
|
||||
|
||||
out = args->out;
|
||||
if (out) {
|
||||
for (i = 0; out[i] != NULL; i++)
|
||||
printf("%s output:%s\n", n->name, out[i]);
|
||||
}
|
||||
}
|
||||
} else if (cmd == DMT_EVENT) {
|
||||
if (n->data) {
|
||||
event_args *ev;
|
||||
|
||||
ev = (event_args *)n->data;
|
||||
|
||||
if (ev->param) {
|
||||
const char **in = ev->param;
|
||||
|
||||
for (int i = 0; in[i] != NULL; i++)
|
||||
printf("%s event_arg:%s\n", n->name, in[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("ERROR: %d retrieving %s\n", err, client_data->bbf_ctx.in_param);
|
||||
err = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int in_ubus_out_cli_exec_schema(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]);
|
||||
}
|
||||
|
||||
static int cli_exec_schema(client_data_t *client_data, char *argv[])
|
||||
{
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
if (strcasecmp(client_data->in_type, "DotSO") == 0)
|
||||
err = in_dotso_out_cli_exec_schema(client_data, argv);
|
||||
else if (strcasecmp(client_data->in_type, "UBUS") == 0)
|
||||
err = in_ubus_out_cli_exec_schema(client_data, argv);
|
||||
else
|
||||
err = EXIT_FAILURE;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cli_exec_command(client_data_t *client_data, int argc, char *argv[])
|
||||
{
|
||||
cli_cmd_t *cli_cmd = NULL;
|
||||
int err = EXIT_SUCCESS;
|
||||
bool registred_command = false;
|
||||
|
||||
client_data->cmd = argv[0];
|
||||
if (!client_data->cmd || strlen(client_data->cmd) == 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (strcasecmp(client_data->in_type, "DotSO") == 0) {
|
||||
|
||||
bbf_ctx_init(&client_data->bbf_ctx, DM_ROOT_OBJ, DM_VENDOR_EXTENSION, DM_VENDOR_EXTENSION_EXCLUDE);
|
||||
|
||||
client_data->bbf_ctx.dm_type = client_data->proto;
|
||||
client_data->bbf_ctx.instance_mode = client_data->instance_mode;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(cli_commands); i++) {
|
||||
|
||||
cli_cmd = &cli_commands[i];
|
||||
if (strcmp(client_data->cmd, cli_cmd->name)==0) {
|
||||
|
||||
if (argc-1 < cli_cmd->num_args) {
|
||||
printf("ERROR: Number of arguments for %s method is wrong(%d), it should be %d\n", cli_cmd->name, argc-1, cli_cmd->num_args);
|
||||
cli_commands[0].exec_cmd(client_data, NULL);
|
||||
err = EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
err = cli_cmd->exec_cmd(client_data, &argv[1]);
|
||||
registred_command = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!registred_command) {
|
||||
printf("ERROR: Unknown command: %s\n", client_data->cmd);
|
||||
cli_commands[0].exec_cmd(client_data, NULL);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
end:
|
||||
if (strcasecmp(client_data->in_type, "DotSO") == 0) {
|
||||
bbf_ctx_clean(&client_data->bbf_ctx);
|
||||
bbf_global_clean(DM_ROOT_OBJ);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int bbfdm_cli_exec_command(const char *json_path, int argc, char *argv[])
|
||||
{
|
||||
client_data_t client_data = {0};
|
||||
int err = EXIT_SUCCESS;
|
||||
|
||||
memset(&client_data, 0, sizeof(client_data_t));
|
||||
|
||||
err = bbfdm_load_client_config(json_path, &client_data);
|
||||
if (err)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
// Exit if no command specified
|
||||
if (argc < 1) {
|
||||
printf("ERROR: command name not specified\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return cli_exec_command(&client_data, argc, argv);
|
||||
}
|
||||
23
bbfdmd/src/cli.h
Normal file
23
bbfdmd/src/cli.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* cli.h: Cli command for bbfdmd
|
||||
*
|
||||
* Copyright (C) 2023 iopsys Software Solutions AB. All rights reserved.
|
||||
*
|
||||
* Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
int bbfdm_cli_exec_command(const char *json_path, int argc, char *argv[]);
|
||||
|
|
@ -181,7 +181,7 @@ bool validate_msglen(usp_data_t *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
int bbf_get_dm_type(char *dm_type)
|
||||
int get_dm_type(char *dm_type)
|
||||
{
|
||||
if (dm_type == NULL)
|
||||
return DMT_STRING;
|
||||
|
|
@ -213,3 +213,27 @@ int bbf_get_dm_type(char *dm_type)
|
|||
|
||||
return DMT_STRING;
|
||||
}
|
||||
|
||||
int get_proto_type(const char *proto)
|
||||
{
|
||||
int type = BBFDM_BOTH;
|
||||
|
||||
if (proto) {
|
||||
if (is_str_eq("cwmp", proto))
|
||||
type = BBFDM_CWMP;
|
||||
else if (is_str_eq("usp", proto))
|
||||
type = BBFDM_USP;
|
||||
else
|
||||
type = BBFDM_BOTH;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
int get_instance_mode(int instance_mode)
|
||||
{
|
||||
if (instance_mode > INSTANCE_MODE_ALIAS)
|
||||
instance_mode = INSTANCE_MODE_NUMBER;
|
||||
|
||||
return instance_mode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@
|
|||
|
||||
#define USP_ERR_OK 0
|
||||
|
||||
extern DMOBJ *DM_ROOT_OBJ;
|
||||
extern DM_MAP_VENDOR *DM_VENDOR_EXTENSION[2];
|
||||
extern DM_MAP_VENDOR_EXCLUDE *DM_VENDOR_EXTENSION_EXCLUDE;
|
||||
|
||||
bool match(const char *string, const char *pattern);
|
||||
bool is_str_eq(const char *s1, const char *s2);
|
||||
bool is_node_instance(char *path);
|
||||
|
|
@ -46,7 +50,10 @@ void print_info(const char *format, ...);
|
|||
void print_debug(const char *format, ...);
|
||||
bool get_boolean_string(char *value);
|
||||
bool validate_msglen(usp_data_t *data);
|
||||
int bbf_get_dm_type(char *dm_type);
|
||||
|
||||
int get_dm_type(char *dm_type);
|
||||
int get_proto_type(const char *proto);
|
||||
int get_instance_mode(int instance_mode);
|
||||
|
||||
#define DEBUG(fmt, args...) \
|
||||
print_debug("[%s:%d]"fmt, __func__, __LINE__, ##args)
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ int bbf_dm_get_supported_dm(usp_data_t *data)
|
|||
INFO("Preparing result for(%s)", data->bbf_ctx.in_param);
|
||||
|
||||
list_for_each_entry(param, &data->bbf_ctx.list_parameter, list) {
|
||||
int cmd = bbf_get_dm_type(param->type);
|
||||
int cmd = get_dm_type(param->type);
|
||||
|
||||
void *table = blobmsg_open_table(&data->bb, NULL);
|
||||
if (cmd == DMT_COMMAND) {
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ struct pathNode {
|
|||
char path[MAX_DM_PATH];
|
||||
};
|
||||
|
||||
extern DMOBJ *DM_ROOT_OBJ;
|
||||
|
||||
void handle_pending_signal(int sig);
|
||||
void print_last_dm_object(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ static void add_data_blob(struct blob_buf *bb, char *param, char *value, char *t
|
|||
return;
|
||||
|
||||
DEBUG("# Adding BLOB (%s)::(%s)", param, value);
|
||||
switch (bbf_get_dm_type(type)) {
|
||||
switch (get_dm_type(type)) {
|
||||
case DMT_UNINT:
|
||||
blobmsg_add_u64(bb, param, (uint32_t)strtoul(value, NULL, 10));
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# BBFDM Dynamic Object/Parameter/Operate/Event
|
||||
|
||||
`bbf_dm` library allows all applications installed on the box to import its own Data Model parameters at run time in two formats:
|
||||
`bbfdm` library allows all applications installed on the box to import its own Data Model parameters at run time in two formats:
|
||||
|
||||
- **Shared library**
|
||||
|
||||
|
|
|
|||
|
|
@ -16,41 +16,41 @@ supervisorctl status all
|
|||
|
||||
function run_valgrind()
|
||||
{
|
||||
echo "Running # bbf_dm $@ #"
|
||||
exec_cmd 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 $@
|
||||
echo "Running # bbfdmd $@ #"
|
||||
exec_cmd valgrind -q --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes /usr/sbin/bbfdmd $@
|
||||
}
|
||||
|
||||
function run_valgrind_verbose()
|
||||
{
|
||||
echo "Running # bbf_dm $@ #"
|
||||
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 $@
|
||||
echo "Running # bbfdmd $@ #"
|
||||
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 /usr/sbin/bbfdmd $@
|
||||
}
|
||||
|
||||
function run_valgrind_redirect()
|
||||
{
|
||||
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
|
||||
echo "Running # bbfdmd $@ #" >> 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 /usr/sbin/bbfdmd $@ | tee -a output-report-device-get.txt
|
||||
}
|
||||
|
||||
echo "Running memory check on datamodel"
|
||||
|
||||
run_valgrind_verbose -u get Device.RootDataModelVersion
|
||||
run_valgrind_verbose -c get Device.RootDataModelVersion
|
||||
|
||||
run_valgrind -u get Device.
|
||||
run_valgrind -c get Device.
|
||||
|
||||
run_valgrind -u instances Device.
|
||||
run_valgrind -c instances Device.
|
||||
|
||||
run_valgrind -u schema Device.
|
||||
run_valgrind -c schema Device.
|
||||
|
||||
run_valgrind_verbose -u get Device.IP.Interface.*.IPv4Address.
|
||||
run_valgrind_redirect -c get Device.
|
||||
|
||||
run_valgrind_redirect -c schema Device.
|
||||
|
||||
run_valgrind_verbose -c get Device.RootDataModelVersion
|
||||
|
||||
run_valgrind_verbose -c get Device.IP.Interface.*.IPv6Address.*.IPAddress
|
||||
|
||||
run_valgrind_redirect -u get Device.
|
||||
run_valgrind_redirect -c get Device.
|
||||
run_valgrind -c set Device.WiFi.SSID.1.Enable 1
|
||||
run_valgrind -c add Device.WiFi.SSID.
|
||||
run_valgrind -c del Device.WiFi.SSID.3.
|
||||
|
||||
supervisorctl stop all
|
||||
supervisorctl status
|
||||
|
|
|
|||
|
|
@ -78,10 +78,6 @@ echo "Validate datamodel_default generated XML file"
|
|||
xmllint --schema test/tools/cwmp-datamodel-1-8.xsd tools/out/datamodel_default.xml --noout
|
||||
check_ret $?
|
||||
|
||||
echo "********* Validate C File *********"
|
||||
|
||||
## TODO
|
||||
|
||||
date +%s > timestamp.log
|
||||
|
||||
echo "Tools Test :: PASS"
|
||||
|
|
|
|||
27
json/input.json
Executable file
27
json/input.json
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"daemon": {
|
||||
"config": {
|
||||
},
|
||||
"input": {
|
||||
"type": "DotSO",
|
||||
"name": "/usr/lib/libbbfdm.so"
|
||||
},
|
||||
"output": {
|
||||
"type": "UBUS",
|
||||
"name": "bbfdm"
|
||||
}
|
||||
},
|
||||
"client": {
|
||||
"config": {
|
||||
"proto": "usp",
|
||||
"instance_mode": 0
|
||||
},
|
||||
"input": {
|
||||
"type": "UBUS",
|
||||
"name": "bbfdm"
|
||||
},
|
||||
"output": {
|
||||
"type": "CLI"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -327,7 +327,6 @@ int bbf_entry_method(struct dmctx *ctx, int cmd)
|
|||
if (!fault)
|
||||
dmuci_change_packages(&head_package_change);
|
||||
break;
|
||||
break;
|
||||
case BBF_ADD_OBJECT:
|
||||
fault = dm_entry_add_object(ctx);
|
||||
if (!fault)
|
||||
|
|
|
|||
|
|
@ -1,22 +1,16 @@
|
|||
LIB = libbbf_test.so
|
||||
BIN = bbf_dm
|
||||
|
||||
BIN_OBJ = bbf_dm.o
|
||||
LIB_OBJS = libbbf_test.o
|
||||
LIB_CFLAGS = $(CFLAGS) -Wall -Werror -fPIC -I /usr/local/include/
|
||||
LIB_LDFLAGS = $(LDFLAGS) -lbbfdm-api
|
||||
BIN_LDFLAGS = $(LDFLAGS) -lbbfdm-api -lbbfdm
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(LIB_CFLAGS) $(FPIC) -c -o $@ $<
|
||||
|
||||
all: $(LIB) $(BIN)
|
||||
all: $(LIB)
|
||||
|
||||
$(LIB): $(LIB_OBJS)
|
||||
$(CC) $(LIB_CFLAGS) $(LIB_LDFLAGS) -shared -o $@ $^
|
||||
|
||||
$(BIN): $(BIN_OBJ)
|
||||
$(CC) -o $@ $^ $(BIN_LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -fv *.o $(LIB) $(BIN)
|
||||
rm -fv *.o $(LIB)
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <libbbfdm-api/dmapi.h>
|
||||
#include <libbbfdm-api/dmentry.h>
|
||||
#include <libbbfdm/device.h>
|
||||
#include <libbbfdm/vendor.h>
|
||||
|
||||
static DMOBJ *TR181_ROOT_TREE = tEntryRoot;
|
||||
static DM_MAP_VENDOR *TR181_VENDOR_EXTENSION[2] = {
|
||||
tVendorExtension,
|
||||
tVendorExtensionOverwrite
|
||||
};
|
||||
static DM_MAP_VENDOR_EXCLUDE *TR181_VENDOR_EXTENSION_EXCLUDE = tVendorExtensionExclude;
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
char *str;
|
||||
} cmd_t;
|
||||
|
||||
|
||||
cmd_t CMD[] = {
|
||||
{ BBF_GET_VALUE, "get"},
|
||||
{ BBF_SCHEMA, "schema"},
|
||||
{ BBF_INSTANCES, "instances"},
|
||||
//{ BBF_SET_VALUE, "set"},
|
||||
//{ BBF_ADD_OBJECT, "add"},
|
||||
//{ BBF_DEL_OBJECT, "del"},
|
||||
//{ BBF_USP_OPERATE, "operate"},
|
||||
};
|
||||
|
||||
static int get_cmd_from_str(char *str)
|
||||
{
|
||||
int i, cmd = BBF_GET_VALUE;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(CMD); i++) {
|
||||
if (DM_STRCMP(CMD[i].str, str) == 0) {
|
||||
cmd = CMD[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static void print_help(char *prog)
|
||||
{
|
||||
printf("Valid commands:\n");
|
||||
printf("%s -c => Run with cwmp proto\n", prog);
|
||||
printf("%s -u => Run with usp proto\n", prog);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int bbf_dm_exec(int argc, char *argv[])
|
||||
{
|
||||
struct dmctx bbf_ctx;
|
||||
int fault = 0;
|
||||
int cmd = 0;
|
||||
|
||||
memset(&bbf_ctx, 0, sizeof(struct dmctx));
|
||||
|
||||
cmd = get_cmd_from_str(argv[2]);
|
||||
|
||||
bbf_ctx.instance_mode = INSTANCE_MODE_NUMBER;
|
||||
|
||||
if (DM_STRCMP(argv[1], "-c") == 0)
|
||||
bbf_ctx.dm_type = BBFDM_CWMP;
|
||||
else
|
||||
bbf_ctx.dm_type = BBFDM_USP;
|
||||
|
||||
if (argc > 3 && DM_STRLEN(argv[3]))
|
||||
bbf_ctx.in_param = argv[3];
|
||||
|
||||
if (cmd == 1) {
|
||||
bbf_ctx.nextlevel = false;
|
||||
bbf_ctx.iscommand = true;
|
||||
bbf_ctx.isevent = true;
|
||||
bbf_ctx.isinfo = true;
|
||||
}
|
||||
|
||||
if (cmd == 2) {
|
||||
bbf_ctx.nextlevel = false;
|
||||
}
|
||||
|
||||
if (cmd == 3 && argc > 4 && DM_STRLEN(argv[4]))
|
||||
bbf_ctx.in_value = argv[4];
|
||||
|
||||
bbf_ctx_init(&bbf_ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE);
|
||||
|
||||
fault = bbf_entry_method(&bbf_ctx, cmd);
|
||||
if (!fault) {
|
||||
struct dm_parameter *n;
|
||||
|
||||
list_for_each_entry(n, &bbf_ctx.list_parameter, list) {
|
||||
printf(" %s::%s::%s\n", n->name, n->data, n->type);
|
||||
}
|
||||
} else {
|
||||
printf("Fault %d\n", fault);
|
||||
}
|
||||
|
||||
bbf_ctx_clean(&bbf_ctx);
|
||||
return fault;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 3)
|
||||
print_help(argv[0]);
|
||||
|
||||
bbf_dm_exec(argc, argv);
|
||||
|
||||
bbf_global_clean(TR181_ROOT_TREE);
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
config bbfdmd 'bbfdmd'
|
||||
option loglevel '1'
|
||||
option refresh_time '10'
|
||||
option transaction_timeout '10'
|
||||
Loading…
Add table
Reference in a new issue