From: Mohamed <mohamed.kallel@pivasoftware.com>
The xml get_parameter_values handler is ready to get the value from external
ubus output now. and is supporting many parameters
Contributed by Inteno Broadband Technology AB && PIVA SOFTWARE
Signed-off-by: Mohamed Kallel <mohamed.kallel@pivasoftware.com>
Signed-off-by: Ahmed Zribi <ahmed.zribi@pivasoftware.com>
---
bin/Makefile.am | 3 +-
configure.ac | 3 ++
src/external.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++---
src/external.h | 5 ++-
src/freecwmp.c | 17 ++++++++++
src/xml.c | 81 +++++++++++++++++++++++++++++------------------
6 files changed, 164 insertions(+), 39 deletions(-)
diff --git a/bin/Makefile.am b/bin/Makefile.am
index 75b9bda..9078ab3 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -48,5 +48,6 @@ freecwmpd_LDADD = \
$(LIBUBUS_LIBS) \
$(MICROXML_LIBS) \
$(LIBCURL_LIBS) \
- $(LIBZSTREAM_LIBS)
+ $(LIBZSTREAM_LIBS) \
+ $(LIBPTHREAD_LIBS)
diff --git a/configure.ac b/configure.ac
index 5ae95c4..765bfe0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,6 +28,9 @@ AC_PROG_CC
AM_PROG_CC_C_O
# checks for libraries
+LIBPTHREAD_LIBS='-lpthread'
+AC_SUBST([LIBPTHREAD_LIBS])
+
AC_ARG_WITH([libfreecwmp-include-path],
[AS_HELP_STRING([--with-libfreecwmp-include-path],
[location of the libfreecwmp library headers])],
diff --git a/src/external.c b/src/external.c
index 46a4931..44be0b6 100644
--- a/src/external.c
+++ b/src/external.c
@@ -5,6 +5,7 @@
* (at your option) any later version.
*
* Copyright (C) 2011 Luka Perkov <freecwmp@lukaperkov.net>
+ * Copyright (C) 2012 Mohamed Kallel <mohamed.kallel@pivasoftware.com>
*/
#include <errno.h>
@@ -25,8 +26,15 @@
#include "freecwmp.h"
static struct uloop_process uproc;
+pthread_t ubus_thread;
LIST_HEAD(external_list_parameter);
+void *thread_uloop_run(void *v)
+{
+ uloop_run();
+ return NULL;
+}
+
void external_add_list_paramameter(char *param_name, char *param_data, char
*param_type, char *fault_code)
{
struct external_parameter *external_parameter;
@@ -140,6 +148,80 @@ error:
return -1;
}
+int external_get_action_write(char *action, char *name, char *arg)
+{
+ lfc_log_message(NAME, L_NOTICE, "adding to get %s script '%s'\n",
+ action, name);
+
+ FILE *fp;
+
+ if (access(fc_script_actions, R_OK | W_OK | X_OK) != -1) {
+ fp = fopen(fc_script_actions, "a");
+ if (!fp) return -1;
+ } else {
+ fp = fopen(fc_script_actions, "w");
+ if (!fp) return -1;
+
+ fprintf(fp, "#!/bin/sh\n");
+
+ if (chmod(fc_script_actions,
+ strtol("0700", 0, 8)) < 0) {
+ return -1;
+ }
+ }
+
+#ifdef DUMMY_MODE
+ fprintf(fp, "/bin/sh `pwd`/%s --ubus get %s %s %s\n", fc_script,
action, name, arg ? arg : "");
+#else
+ fprintf(fp, "/bin/sh %s --ubus get %s %s %s\n", fc_script, action,
name, arg ? arg : "");
+#endif
+
+ fclose(fp);
+
+ return 0;
+}
+
+int external_get_action_execute()
+{
+ lfc_log_message(NAME, L_NOTICE, "executing get script\n");
+
+ pthread_create(&ubus_thread, NULL, &thread_uloop_run, NULL);
+
+ if ((uproc.pid = fork()) == -1) {
+ return -1;
+ }
+
+ if (uproc.pid == 0) {
+ /* child */
+
+ const char *argv[3];
+ int i = 0;
+ argv[i++] = "/bin/sh";
+ argv[i++] = fc_script_actions;
+ argv[i++] = NULL;
+
+ execvp(argv[0], (char **) argv);
+ exit(ESRCH);
+
+ } else if (uproc.pid < 0)
+ return -1;
+
+ /* parent */
+ int status;
+ while (wait(&status) != uproc.pid) {
+ DD("waiting for child to exit");
+ }
+
+ pthread_cancel(ubus_thread);
+ pthread_join(ubus_thread, NULL);
+
+ // TODO: add some kind of checks
+
+ remove(fc_script_actions);
+
+ return 0;
+}
+
int external_set_action_write(char *action, char *name, char *value)
{
lfc_log_message(NAME, L_NOTICE, "adding to set %s script '%s'\n",
@@ -147,16 +229,16 @@ int external_set_action_write(char *action, char *name,
char *value)
FILE *fp;
- if (access(fc_script_set_actions, R_OK | W_OK | X_OK) != -1) {
- fp = fopen(fc_script_set_actions, "a");
+ if (access(fc_script_actions, R_OK | W_OK | X_OK) != -1) {
+ fp = fopen(fc_script_actions, "a");
if (!fp) return -1;
} else {
- fp = fopen(fc_script_set_actions, "w");
+ fp = fopen(fc_script_actions, "w");
if (!fp) return -1;
fprintf(fp, "#!/bin/sh\n");
- if (chmod(fc_script_set_actions,
+ if (chmod(fc_script_actions,
strtol("0700", 0, 8)) < 0) {
return -1;
}
@@ -187,7 +269,7 @@ int external_set_action_execute()
const char *argv[3];
int i = 0;
argv[i++] = "/bin/sh";
- argv[i++] = fc_script_set_actions;
+ argv[i++] = fc_script_actions;
argv[i++] = NULL;
execvp(argv[0], (char **) argv);
@@ -204,7 +286,7 @@ int external_set_action_execute()
// TODO: add some kind of checks
- if (remove(fc_script_set_actions) != 0)
+ if (remove(fc_script_actions) != 0)
return -1;
return 0;
diff --git a/src/external.h b/src/external.h
index 0e09415..f69fb34 100644
--- a/src/external.h
+++ b/src/external.h
@@ -5,6 +5,7 @@
* (at your option) any later version.
*
* Copyright (C) 2011 Luka Perkov <freecwmp@lukaperkov.net>
+ * Copyright (C) 2012 Mohamed Kallel <mohamed.kallel@pivasoftware.com>
*/
#ifndef _FREECWMP_EXTERNAL_H__
@@ -16,7 +17,7 @@ static char *fc_script = "./ext/openwrt/scripts/freecwmp.sh";
#else
static char *fc_script = "/usr/sbin/freecwmp";
#endif
-static char *fc_script_set_actions = "/tmp/freecwmp_set_action_values.sh";
+static char *fc_script_actions = "/tmp/freecwmp_actions.sh";
/*
* external_parameter structure is used to get data from external command when
a parameter method is triggered
@@ -31,6 +32,8 @@ struct external_parameter {
};
int external_get_action(char *action, char *name, char **value);
+int external_get_action_write(char *action, char *name, char *arg);
+int external_get_action_execute();
int external_set_action_write(char *action, char *name, char *value);
int external_set_action_execute();
int external_simple(char *arg);
diff --git a/src/freecwmp.c b/src/freecwmp.c
index d311cf4..0ad0e94 100644
--- a/src/freecwmp.c
+++ b/src/freecwmp.c
@@ -18,6 +18,7 @@
#include <arpa/inet.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include <signal.h>
#include <libfreecwmp.h>
#include <libubox/uloop.h>
@@ -194,11 +195,27 @@ netlink_init(void)
return 0;
}
+void signal_kill_all_handler(int sig)
+{
+ pthread_exit(NULL);
+}
+
int main (int argc, char **argv)
{
lfc_log_message(NAME, L_NOTICE, "daemon started\n");
bool foreground = false;
+ struct sigaction sigint_action;
+
+ sigint_action.sa_handler = &signal_kill_all_handler;
+ sigemptyset(&sigint_action.sa_mask);
+
+ /*
+ * reset handler in case when pthread_cancel didn't stop
+ * threads for some reason
+ */
+ sigint_action.sa_flags = SA_RESETHAND;
+ sigaction(SIGTERM, &sigint_action, NULL);
setlocale(LC_CTYPE, "");
umask(0037);
diff --git a/src/xml.c b/src/xml.c
index 0aa4f35..f89fd3c 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -21,6 +21,8 @@
#include "messages.h"
#include "time.h"
+extern struct list_head external_list_parameter;
+
struct rpc_method {
const char *name;
int (*handler)(mxml_node_t *body_in, mxml_node_t *tree_in,
@@ -628,7 +630,8 @@ int xml_handle_get_parameter_values(mxml_node_t *body_in,
mxml_node_t *tree_in,
mxml_node_t *tree_out)
{
- mxml_node_t *n, *b = body_in;
+ mxml_node_t *n, *parameter_list, *b = body_in;
+ struct external_parameter *external_parameter;
char *parameter_name = NULL;
char *parameter_value = NULL;
char *c;
@@ -656,54 +659,71 @@ int xml_handle_get_parameter_values(mxml_node_t *body_in,
parameter_name = b->value.text.string;
}
+ /*
+ * If the string node from GetParameterValues does not contain
child node (txt node)
+ * Then the parameter name is empty string which means get all
parameters from the data model
+ */
+ if (b && b->type == MXML_ELEMENT &&
+ !strcmp(b->value.element.name, "string") &&
+ !b->child) {
+ parameter_name = "";
+ }
+
if (parameter_name) {
if (!config_get_cwmp(parameter_name, ¶meter_value))
{
+
external_add_list_paramameter(parameter_name,parameter_value, "xsd:string",
NULL);
+ FREE(parameter_value);
// got the parameter value using libuci
- } else if (!external_get_action("value",
- parameter_name, ¶meter_value)) {
+ } else if (!external_get_action_write("value",
parameter_name, NULL)) {
// got the parameter value via external script
} else {
// error occurred when getting parameter value
goto out;
}
- counter++;
+ }
- n = mxmlFindElement(tree_out, tree_out,
"ParameterList", NULL, NULL, MXML_DESCEND);
- if (!n) goto out;
+ b = mxmlWalkNext(b, body_in, MXML_DESCEND);
+ parameter_name = NULL;
+ }
- n = mxmlNewElement(n, "ParameterValueStruct");
- if (!n) goto out;
+ if (external_get_action_execute())
+ goto out;
- n = mxmlNewElement(n, "Name");
- if (!n) goto out;
+ parameter_list = mxmlFindElement(tree_out, tree_out, "ParameterList",
NULL, NULL, MXML_DESCEND);
+ if (!parameter_list) goto out;
- n = mxmlNewText(n, 0, parameter_name);
- if (!n) goto out;
+ while (external_list_parameter.next != &external_list_parameter) {
+
+ external_parameter = list_entry(external_list_parameter.next,
struct external_parameter, list);
+
+ if (external_parameter->fault_code &&
external_parameter->fault_code[0]=='9') {
+ // TODO return FAULT message the fault code is saved in
external_parameter->fault_code
+ goto out;
+ }
- n = n->parent->parent;
- n = mxmlNewElement(n, "Value");
+ n = mxmlNewElement(parameter_list, "ParameterValueStruct");
if (!n) goto out;
+ n = mxmlNewElement(n, "Name");
+ if (!n) goto out;
+
+ n = mxmlNewText(n, 0, external_parameter->name);
+ if (!n) goto out;
+
+ n = n->parent->parent;
+ n = mxmlNewElement(n, "Value");
+ if (!n) goto out;
+
#ifdef ACS_MULTI
- mxmlElementSetAttr(n, "xsi:type", "xsd:string");
+ mxmlElementSetAttr(n, "xsi:type", external_parameter->type);
#endif
- n = mxmlNewText(n, 0, parameter_value ? parameter_value
: "");
- if (!n) goto out;
+ n = mxmlNewText(n, 0, external_parameter->data ?
external_parameter->data : "");
+ if (!n) goto out;
- /*
- * three day's work to finally find memory leak if we
- * free parameter_name;
- * it points to: b->value.text.string
- *
- * also, parameter_value can be NULL so we don't do
checks
- */
- parameter_name = NULL;
- }
+ counter++;
- FREE(parameter_value);
- b = mxmlWalkNext(b, body_in, MXML_DESCEND);
+ external_parameter_delete(external_parameter);
}
-
#ifdef ACS_MULTI
b = mxmlFindElement(tree_out, tree_out, "ParameterList",
NULL, NULL, MXML_DESCEND);
@@ -716,11 +736,10 @@ int xml_handle_get_parameter_values(mxml_node_t *body_in,
FREE(c);
#endif
- FREE(parameter_value);
return 0;
out:
- FREE(parameter_value);
+ external_free_list_parameter();
return -1;
}
--
1.7.4.1
|