diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 00000000..e69de29b
diff --git a/COPYING b/COPYING
new file mode 100644
index 00000000..6170c801
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,312 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ cwmp is GPLv2 licensed cwmp implementation
+ Copyright (C) 2011-2012 Luka Perkov
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ 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, see .
+
+ cwmp Copyright (C) 2011-2012 Luka Perkov
+ This program comes with ABSOLUTELY NO WARRANTY.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 00000000..e69de29b
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 00000000..1c5d6ee1
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,3 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+SUBDIRS = bin
diff --git a/NEWS b/NEWS
new file mode 100644
index 00000000..e69de29b
diff --git a/README b/README
new file mode 100644
index 00000000..3cd720de
--- /dev/null
+++ b/README
@@ -0,0 +1,29 @@
+configure autotools
+===================
+
+$ autoreconf -if
+
+clean it all up
+===============
+
+$ make distclean
+
+or
+
+$ git clean -df
+
+development environment
+=======================
+
+Make sure you have all the packages installed from packages-arch-tr069 git
+repository.
+
+$ ln -sf `pwd`/scripts/defaults /usr/share/icwmp/defaults
+
+
+run icwmpd
+=============
+
+$ export UCI_CONFIG_DIR="`pwd`/config/"
+$ export UBUS_SOCKET="/tmp/ubus.sock"
+$ ./bin/icwmpd -f
diff --git a/bin/Makefile.am b/bin/Makefile.am
new file mode 100644
index 00000000..70270c95
--- /dev/null
+++ b/bin/Makefile.am
@@ -0,0 +1,109 @@
+CWMP_VERSION = 3.0.0
+LIB_BBFDM_VERSION = 3:0:0
+
+lib_LTLIBRARIES = libbbfdm.la
+
+libbbfdm_la_SOURCES = \
+ ../md5.c \
+ ../dmcwmp.c \
+ ../dmentry.c \
+ ../dmmem.c \
+ ../dmubus.c \
+ ../dmjson.c \
+ ../dmuci.c \
+ ../dmcommon.c \
+ ../dmoperate.c \
+ ../dmdiagnostics.c \
+ ../wepkey.c
+
+if BBF_TR181
+libbbfdm_la_SOURCES += \
+ ../dmtree/tr181/device.c \
+ ../dmtree/tr181/deviceinfo.c \
+ ../dmtree/tr181/managementserver.c \
+ ../dmtree/tr181/softwaremodules.c \
+ ../dmtree/tr181/times.c \
+ ../dmtree/tr181/upnp.c \
+ ../dmtree/tr181/x_iopsys_eu_ice.c \
+ ../dmtree/tr181/x_iopsys_eu_igmp.c \
+ ../dmtree/tr181/x_iopsys_eu_ipacccfg.c \
+ ../dmtree/tr181/x_iopsys_eu_logincfg.c \
+ ../dmtree/tr181/x_iopsys_eu_power_mgmt.c \
+ ../dmtree/tr181/x_iopsys_eu_syslog.c \
+ ../dmtree/tr181/x_iopsys_eu_dropbear.c \
+ ../dmtree/tr181/x_iopsys_eu_owsd.c \
+ ../dmtree/tr181/x_iopsys_eu_buttons.c \
+ ../dmtree/tr181/x_iopsys_eu_wifilife.c \
+ ../dmtree/tr181/xmpp.c \
+ ../dmtree/tr181/wifi.c \
+ ../dmtree/tr181/ethernet.c \
+ ../dmtree/tr181/atm.c \
+ ../dmtree/tr181/ptm.c \
+ ../dmtree/tr181/bridging.c \
+ ../dmtree/tr181/hosts.c \
+ ../dmtree/tr181/dhcpv4.c \
+ ../dmtree/tr181/ip.c \
+ ../dmtree/tr181/ppp.c \
+ ../dmtree/tr181/nat.c \
+ ../dmtree/tr181/routing.c \
+ ../dmtree/tr181/userinterface.c \
+ ../dmtree/tr181/firewall.c \
+ ../dmtree/tr181/dns.c \
+ ../dmtree/tr181/users.c \
+ ../dmtree/tr181/dhcpv6.c \
+ ../dmtree/tr181/dsl.c \
+ ../dmtree/tr181/interfacestack.c \
+ ../dmtree/tr181/qos.c
+endif
+
+if BBF_TR104
+libbbfdm_la_SOURCES += \
+ ../dmtree/tr104/voice_services.c
+endif
+
+if BBF_TR143
+libbbfdm_la_SOURCES += \
+ ../dmtree/tr143/diagnostics.c
+endif
+
+if BBF_TR064
+libbbfdm_la_SOURCES += \
+ ../dmtree/tr064/upnp_device.c \
+ ../dmtree/tr064/upnp_deviceinfo.c \
+ ../dmtree/tr064/upnp_configuration.c \
+ ../dmtree/tr064/upnp_monitoring.c \
+ ../dmtree/tr064/upnp_common.c
+endif
+
+libbbfdm_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(LIBUCI_CFLAGS) \
+ $(LIBUBOX_CFLAGS) \
+ $(LIBUBUS_CFLAGS)
+
+libbbfdm_la_LDFLAGS = \
+ $(AM_LDFLAGS) \
+ $(LIBUCI_LDFLAGS) \
+ $(LIBUBOX_LDFLAGS) \
+ $(LIBUBUS_LDFLAGS) \
+ -share \
+ -version-info $(LIB_BBFDM_VERSION)
+
+libbbfdm_la_LIBADD = \
+ $(AM_LIBS) \
+ $(LIBUCI_LIBS) \
+ $(LIBUBOX_LIBS) \
+ $(LIBUBUS_LIBS) \
+ $(LIBJSON_LIBS) \
+ $(LIBTRACE_LIBS) \
+ $(LBLOBMSG_LIBS)
+
+libbbfdm_la_CFLAGS+=-DCWMP_VERSION=\"$(CWMP_VERSION)\"
+libbbfdm_la_LDFLAGS+=-DCWMP_VERSION=\"$(CWMP_VERSION)\"
+
+libbbfdm_la_CFLAGS+=-I../
+libbbfdm_la_CFLAGS+=-I../dmtree/
+libbbfdm_la_CFLAGS+=-I../dmtree/tr181
+libbbfdm_la_CFLAGS+=-I../dmtree/tr104
+libbbfdm_la_CFLAGS+=-I../dmtree/tr143
+libbbfdm_la_CFLAGS+=-I../dmtree/tr064
\ No newline at end of file
diff --git a/config/dmmap b/config/dmmap
new file mode 100644
index 00000000..e69de29b
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 00000000..bb82bb6d
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,84 @@
+AC_INIT([libbbfdm], [0.1], [mohamed.kallel@pivasoftware.com])
+AM_INIT_AUTOMAKE
+
+AM_INIT_AUTOMAKE([subdir-objects])
+
+AC_ARG_ENABLE(tr181, [AS_HELP_STRING([--enable-tr181], [enable tr181 device feature])], AC_DEFINE(BBF_TR181),)
+AM_CONDITIONAL([BBF_TR181],[test "x$enable_tr181" = "xyes"])
+
+AC_ARG_ENABLE(tr104, [AS_HELP_STRING([--enable-tr104], [enable tr104 voice feature])], AC_DEFINE(BBF_TR104),)
+AM_CONDITIONAL([BBF_TR104],[test "x$enable_tr104" = "xyes"])
+
+AC_ARG_ENABLE(tr143, [AS_HELP_STRING([--enable-tr143], [enable tr143 diagnostics feature])], AC_DEFINE(BBF_TR143),)
+AM_CONDITIONAL([BBF_TR143],[test "x$enable_tr143" = "xyes"])
+
+AC_ARG_ENABLE(tr064, [AS_HELP_STRING([--enable-tr064], [enable tr064 upnp feature])], AC_DEFINE(BBF_TR064),)
+AM_CONDITIONAL([BBF_TR064],[test "x$enable_tr064" = "xyes"])
+
+# checks for programs
+AC_PROG_CC
+AM_PROG_CC_C_O
+LT_INIT
+AC_ENABLE_SHARED
+
+LIBJSON_LIBS='-ljson-c'
+AC_SUBST([LIBJSON_LIBS])
+
+AC_ARG_WITH([uci-include-path],
+ [AS_HELP_STRING([--with-uci-include-path],
+ [location of the uci library headers])],
+ [LIBUCI_CFLAGS="-I$withval"])
+AC_SUBST([LIBUCI_CFLAGS])
+
+AC_ARG_WITH([uci-lib-path],
+ [AS_HELP_STRING([--with-uci-lib-path], [location of the uci library])], [LIBUCI_LDFLAGS="-L$withval"])
+AC_SUBST([LIBUCI_LDFLAGS])
+
+LIBUCI_LIBS='-luci'
+AC_SUBST([LIBUCI_LIBS])
+
+LIBTRACE_LIBS='-ltrace'
+AC_SUBST([LIBTRACE_LIBS])
+
+AC_ARG_WITH([libubox-include-path],
+ [AS_HELP_STRING([--with-libubox-include-path],
+ [location of the libubox library headers])],
+ [LIBUBOX_CFLAGS="-I$withval"])
+AC_SUBST([LIBUBOX_CFLAGS])
+
+AC_ARG_WITH([libubox-lib-path],
+ [AS_HELP_STRING([--with-libubox-lib-path], [location of the libubox library])], [LIBUBOX_LDFLAGS="-L$withval"])
+AC_SUBST([LIBUBOX_LDFLAGS])
+
+LIBUBOX_LIBS='-lubox'
+AC_SUBST([LIBUBOX_LIBS])
+
+AC_ARG_WITH([libubus-include-path],
+ [AS_HELP_STRING([--with-libubus-include-path],
+ [location of the libubus library headers])],
+ [LIBUBUS_CFLAGS="-I$withval"])
+AC_SUBST([LIBUBUS_CFLAGS])
+
+AC_ARG_WITH([libubus-lib-path],
+ [AS_HELP_STRING([--with-libubus-lib-path], [location of the libubus library])], [LIBUBOX_LDFLAGS="-L$withval"])
+AC_SUBST([LIBUBUS_LDFLAGS])
+
+LIBUBUS_LIBS='-lubus'
+AC_SUBST([LIBUBUS_LIBS])
+
+LBLOBMSG_LIBS='-lblobmsg_json'
+AC_SUBST([LBLOBMSG_LIBS])
+
+# checks for header files
+AC_CHECK_HEADERS([stdlib.h string.h])
+
+# checks for typedefs, structures, and compiler characteristics
+AC_TYPE_UINT8_T
+
+# Makefiles
+AC_CONFIG_FILES([
+Makefile
+bin/Makefile
+])
+
+AC_OUTPUT
diff --git a/dmcommon.c b/dmcommon.c
new file mode 100644
index 00000000..a50eea48
--- /dev/null
+++ b/dmcommon.c
@@ -0,0 +1,1715 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2012-2014 PIVA SOFTWARE (www.pivasoftware.com)
+ * Author: Imen Bhiri
+ * Author: Feten Besbes
+ * Author: Omar Kallel
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "dmcwmp.h"
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcommon.h"
+#include "dmjson.h"
+
+char *array_notifcation_char[__MAX_notification] = {
+ [notification_none] = "0",
+ [notification_passive] = "1",
+ [notification_active] = "2",
+ [notification_passive_lw] = "3",
+ [notification_ppassive_passive_lw] = "4",
+ [notification_aactive_lw] = "5",
+ [notification_passive_active_lw] = "6",
+};
+
+int set_uci_dhcpserver_option(struct dmctx *ctx, struct uci_section *s, char *option, char *value)
+{
+ struct uci_list *v;
+ struct uci_element *e, *tmp;
+ char *pch, *spch, bufopt[8];
+ int len = 0;
+ if (value == NULL)
+ return -1;
+
+ dmuci_get_value_by_section_list(s, "dhcp_option", &v);
+ if (v != NULL) {
+ uci_foreach_element(v, e) {
+ pch = strchr(e->name, ',');
+ if (pch) {
+ len = pch - e->name;
+ strncpy(bufopt, e->name, len);
+ bufopt[len] = '\0';
+ if (strcmp(bufopt, option) == 0) {
+ dmuci_del_list_value_by_section(s, "dhcp_option", e->name);
+ break;
+ }
+ }
+ }
+ }
+ if (value[0] != '\0') {
+ dmasprintf(&spch, "%s,%s", option, value);
+ dmuci_add_list_value_by_section(s, "dhcp_option", spch);
+ }
+ return 0;
+}
+
+int update_uci_dhcpserver_option(struct dmctx *ctx, struct uci_section *s, char *option, char *new_option, char *value)
+{
+ struct uci_list *v;
+ struct uci_element *e, *tmp;
+ char *pch, *spch, bufopt[8];
+ int len = 0;
+ if (value == NULL)
+ return -1;
+
+ dmuci_get_value_by_section_list(s, "dhcp_option", &v);
+ if (v != NULL) {
+ uci_foreach_element(v, e) {
+ pch = strchr(e->name, ',');
+ if (pch[0] != '\0' && strcmp(++pch, value) == 0) {
+ len = pch - e->name - 1;
+ strncpy(bufopt, e->name, len);
+ bufopt[len] = '\0';
+ if (strcmp(bufopt, option) == 0) {
+ dmuci_del_list_value_by_section(s, "dhcp_option", e->name);
+ break;
+ }
+ }
+ }
+ }
+ if (value[0] != '\0') {
+ dmasprintf(&spch, "%s,%s", new_option, value);
+ dmuci_add_list_value_by_section(s, "dhcp_option", spch);
+ }
+ return 0;
+}
+
+void compress_spaces(char *str)
+{
+ char *dst = str;
+ for (; *str; ++str) {
+ *dst++ = *str;
+ if (isspace(*str)) {
+ do ++str;
+ while (isspace(*str));
+ --str;
+ }
+ }
+ *dst = '\0';
+}
+char *cut_fx(char *str, char *delimiter, int occurence)
+{
+ int i = 1;
+ char *pch, *spch;
+ pch = strtok_r(str, delimiter, &spch);
+ while (pch != NULL && i= '0') {
+ nbr++;
+ }
+ return ((*nbr) ? 0 : 1);
+}
+
+/* int strstructered(char *str1, char *str2)
+ * Return:
+ * STRUCTERED_SAME: if str1 is same of str2 (with # match any number)
+ * STRUCTERED_PART: if str2 is part of str1 (with # match any number)
+ * STRUCTERED_NULL: if str2 is not part of str1 (with # match any number)
+ *
+ */
+int strstructered(char *str1, char *str2)
+{
+ char buf[16];
+ int i = 0;
+ for (; *str1 && *str2; str1++, str2++) {
+ if (*str1 == *str2)
+ continue;
+ if (*str2 == '#') {
+ i = 0;
+ do {
+ buf[i++] = *str1;
+ } while (*(str1+1) && *(str1+1) != dm_delim && str1++);
+ buf[i] = '\0';
+ if (dmisnumeric(buf))
+ continue;
+ }
+ else if (*str1 == '#') {
+ i = 0;
+ do {
+ buf[i++] = *str2;
+ } while (*(str2+1) && *(str2+1) != dm_delim && str2++);
+ buf[i] = '\0';
+ if (dmisnumeric(buf))
+ continue;
+ }
+ return STRUCTERED_NULL;
+ }
+ if (*str1 == '\0' && *str2 == '\0')
+ return STRUCTERED_SAME;
+ else if (*str2 == '\0')
+ return STRUCTERED_PART;
+ return STRUCTERED_NULL;
+}
+
+
+pid_t get_pid(char *pname)
+{
+ DIR* dir;
+ struct dirent* ent;
+ char* endptr;
+ char buf[512];
+
+ if (!(dir = opendir("/proc"))) {
+ return -1;
+ }
+ while((ent = readdir(dir)) != NULL) {
+ long lpid = strtol(ent->d_name, &endptr, 10);
+ if (*endptr != '\0') {
+ continue;
+ }
+ snprintf(buf, sizeof(buf), "/proc/%ld/cmdline", lpid);
+ FILE* fp = fopen(buf, "r");
+ if (fp) {
+ if (fgets(buf, sizeof(buf), fp) != NULL) {
+ char* first = strtok(buf, " ");
+ if (strstr(first, pname)) {
+ fclose(fp);
+ closedir(dir);
+ return (pid_t)lpid;
+ }
+ }
+ fclose(fp);
+ }
+ }
+ closedir(dir);
+ return -1;
+}
+
+int check_file(char *path)
+{
+ glob_t globbuf;
+ if(glob(path, 0, NULL, &globbuf) == 0) {
+ globfree(&globbuf);
+ return 1;
+ }
+ return 0;
+}
+
+char *cidr2netmask(int bits)
+{
+ uint32_t mask;
+ struct in_addr ip_addr;
+ uint8_t u_bits = (uint8_t)bits;
+ char *netmask;
+ char tmp[32] = {0};
+
+ mask = ((0xFFFFFFFFUL << (32 - u_bits)) & 0xFFFFFFFFUL);
+ mask = htonl(mask);
+ ip_addr.s_addr = mask;
+ return inet_ntoa(ip_addr);
+}
+
+void remove_substring(char *s, const char *str_remove)
+{
+ int len = strlen(str_remove);
+ while (s = strstr(s, str_remove)) {
+ memmove(s, s+len, 1+strlen(s+len));
+ }
+}
+
+bool is_strword_in_optionvalue(char *optionvalue, char *str)
+{
+ int len;
+ char *s = optionvalue;
+ while ((s = strstr(s, str))) {
+ len = strlen(str); //should be inside while, optimization reason
+ if(s[len] == '\0' || s[len] == ' ')
+ return true;
+ s++;
+ }
+ return false;
+}
+
+int get_interface_enable_ubus(char *iface, char *refparam, struct dmctx *ctx, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", iface, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 1, "up");
+ return 0;
+}
+
+int set_interface_enable_ubus(char *iface, char *refparam, struct dmctx *ctx, int action, char *value)
+{
+ bool b;
+ char *ubus_object;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ dmastrcat(&ubus_object, "network.interface.", iface);
+ if(b) {
+ dmubus_call_set(ubus_object, "up", UBUS_ARGS{}, 0);
+ }
+ else
+ dmubus_call_set(ubus_object, "down", UBUS_ARGS{}, 0);
+ dmfree(ubus_object);
+ return 0;
+ }
+ return 0;
+}
+
+int get_interface_firewall_enabled(char *iface, char *refparam, struct dmctx *ctx, char **value)
+{
+ char *input = "", *forward = "";
+ struct uci_section *s = NULL;
+
+ uci_foreach_option_cont("firewall", "zone", "network", iface, s) {
+ dmuci_get_value_by_section_string(s, "input", &input);
+ dmuci_get_value_by_section_string(s, "forward", &forward);
+ if (strcmp(input, "ACCEPT") !=0 && strcmp(forward, "ACCEPT") !=0) {
+ *value = "1";
+ return 0;
+ }
+ }
+ *value = "0";
+ return 0;
+}
+
+struct uci_section *create_firewall_zone_config(char *fwl, char *iface, char *input, char *forward, char *output)
+{
+ struct uci_section *s;
+ char *value, *name;
+
+ dmuci_add_section_and_rename("firewall", "zone", &s, &value);
+ dmasprintf(&name, "%s_%s", fwl, iface);
+ dmuci_set_value_by_section(s, "name", name);
+ dmuci_set_value_by_section(s, "input", input);
+ dmuci_set_value_by_section(s, "forward", forward);
+ dmuci_set_value_by_section(s, "output", output);
+ dmuci_set_value_by_section(s, "network", iface);
+ dmfree(name);
+ return s;
+}
+
+int set_interface_firewall_enabled(char *iface, char *refparam, struct dmctx *ctx, int action, char *value)
+{
+ bool b;
+ int cnt = 0;
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b)
+ value = "DROP";
+ else
+ value = "ACCEPT";
+ uci_foreach_option_cont("firewall", "zone", "network", iface, s) {
+ dmuci_set_value_by_section(s, "input", value);
+ dmuci_set_value_by_section(s, "forward", value);
+ cnt++;
+ }
+ if (cnt == 0 && b)
+ create_firewall_zone_config("fwl", iface, "DROP", "DROP", "ACCEPT");
+ return 0;
+ }
+ return 0;
+}
+
+int dmcmd(char *cmd, int n, ...)
+{
+ va_list arg;
+ int i, pid;
+ static int dmcmd_pfds[2];
+ char *argv[n+2];
+
+ argv[0] = cmd;
+
+ va_start(arg,n);
+ for (i=0; i 0) {
+ t = len;
+ len += rxed;
+ *value = dmrealloc(*value, len);
+ memcpy(*value + t - 1, buffer, rxed);
+ *(*value + len -1) = '\0';
+ }
+ if (*value == NULL)
+ *value = dmstrdup("");
+}
+
+int dmcmd_read(int pipe, char *buffer, int size)
+{
+ int rd;
+ if (size < 2) return -1;
+ if ((rd = read(pipe, buffer, (size-1))) > 0) {
+ buffer[rd] = '\0';
+ return (rd + 1);
+ }
+ else {
+ buffer[0] = '\0';
+ return -1;
+ }
+ return -1;
+}
+
+int ipcalc(char *ip_str, char *mask_str, char *start_str, char *end_str, char *ipstart_str, char *ipend_str)
+{
+//TODO test it in accordance with inteno issue #7467
+ struct in_addr ip;
+ struct in_addr mask;
+ struct in_addr ups;
+ struct in_addr upe;
+ int start, end;
+ unsigned int umask;
+ unsigned int addr;
+
+ inet_aton(ip_str, &ip);
+ inet_aton(mask_str, &mask);
+
+ start = atoi(start_str);
+
+ ups.s_addr = htonl(ntohl(ip.s_addr & mask.s_addr) + start);
+ strcpy(ipstart_str, inet_ntoa(ups));
+
+ if (end_str) {
+ end = atoi(end_str);
+ upe.s_addr = htonl(ntohl(ups.s_addr) + end);
+ strcpy(ipend_str, inet_ntoa(upe));
+ }
+ return 0;
+}
+
+int ipcalc_rev_start(char *ip_str, char *mask_str, char *ipstart_str, char *start_str)
+{
+//TODO test it in accordance with inteno issue #7467
+ struct in_addr ip;
+ struct in_addr mask;
+ struct in_addr ups;
+ struct in_addr upe;
+ int start;
+ unsigned int umask;
+ unsigned int addr;
+
+ inet_aton(ip_str, &ip);
+ inet_aton(mask_str, &mask);
+ inet_aton(ipstart_str, &ups);
+
+ start = ntohl(ups.s_addr) - ntohl(ip.s_addr & mask.s_addr);
+ sprintf(start_str, "%d", start);
+ return 0;
+}
+
+int ipcalc_rev_end(char *ip_str, char *mask_str, char *start_str, char *ipend_str, char *end_str)
+{
+//TODO test it in accordance with inteno issue #7467
+ struct in_addr ip;
+ struct in_addr mask;
+ struct in_addr upe;
+ int end;
+
+ inet_aton(ip_str, &ip);
+ inet_aton(mask_str, &mask);
+ inet_aton(ipend_str, &upe);
+
+ end = ntohl(upe.s_addr) - ntohl(ip.s_addr & mask.s_addr) - atoi(start_str);
+ sprintf(end_str, "%d", end);
+ return 0;
+}
+
+int network_get_ipaddr(char **value, char *iface)
+{
+ json_object *res, *jobj;
+ char *ipv6_value = "";
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", iface, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ *value = dm_ubus_get_value(jobj, 1, "address");
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv6-address");
+ ipv6_value = dm_ubus_get_value(jobj, 1, "address");
+
+ if((*value)[0] == '\0' || ipv6_value[0] == '\0') {
+ if ((*value)[0] == '\0')
+ *value = ipv6_value;
+ }
+ else if (ip_version == 6) {
+ *value = ipv6_value;
+ return 0;
+ }
+ return 0;
+}
+
+void remove_vid_interfaces_from_ifname(char *vid, char *ifname, char *new_ifname)
+{
+ char *sv, *pch, *p = new_ifname, *spch;
+ new_ifname[0] = '\0';
+ bool append;
+
+ ifname = dmstrdup(ifname);
+ pch = strtok_r(ifname, " ", &spch);
+ while (pch != NULL) {
+ append = false;
+ char *sv = strchr(pch, '.');
+ if (sv) {
+ sv++;
+ if (strcmp(sv, vid) != 0) {
+ append = true;
+ }
+ }
+ else {
+ append = true;
+ }
+ if (append) {
+ if (p == new_ifname) {
+ dmstrappendstr(p, pch);
+ }
+ else {
+ dmstrappendchr(p, ' ');
+ dmstrappendstr(p, pch);
+ }
+ }
+ pch = strtok_r(NULL, " ", &spch);
+ }
+ dmstrappendend(p);
+ dmfree(ifname);
+}
+
+void update_section_option_list(char *config, char *section, char *option, char *option_2,char *val, char *val_2, char *name)
+{
+ char *add_value;
+ int i = 0;
+ char *baseifname;
+ struct uci_section *prev_s= NULL, *s;
+ char *instance = NULL, *last_instance = NULL, *value;
+ bool add_sec = true;
+
+ if (name[0] == '\0') {
+ add_sec = false;
+ }
+ if (config == DMMAP)
+ {
+ uci_path_foreach_option_eq(icwmpd, config, section, option_2, val_2, s) {
+ dmuci_get_value_by_section_string(s, option, &baseifname);
+ if (!strstr(name, baseifname))
+ {
+ //delete section if baseifname does not belong to ifname
+ if (prev_s) {
+ DMUCI_DELETE_BY_SECTION(icwmpd, prev_s, NULL, NULL);
+ }
+ prev_s = s;
+ } else if (strstr(name, baseifname) && (strcmp(baseifname,val) ==0)) {
+ //do not add baseifname if exist
+ add_sec = false;
+ }
+ }
+ if (prev_s) {
+ DMUCI_DELETE_BY_SECTION(icwmpd, prev_s, NULL, NULL);
+ }
+ if (add_sec) {
+ DMUCI_ADD_SECTION(icwmpd, config, section, &s, &add_value);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, option, val);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, option_2, val_2);
+ }
+ }
+ else
+ {
+ uci_foreach_option_eq(config, section, option_2, val_2, s) {
+ dmuci_get_value_by_section_string(s, option, &baseifname);
+ if (!strstr(name, baseifname))
+ {
+ //delete section if baseifname does not belong to ifname
+ if (prev_s) {
+ dmuci_delete_by_section(prev_s, NULL, NULL);
+ }
+ prev_s = s;
+ } else if (strstr(name, baseifname) && (strcmp(baseifname,val) ==0)) {
+ //do not add baseifname if exist
+ add_sec = false;
+ }
+ }
+ if (prev_s) {
+ dmuci_delete_by_section(prev_s, NULL, NULL);
+ }
+ if (add_sec) {
+ dmuci_add_section_and_rename(config, section, &s, &add_value);
+ dmuci_set_value_by_section(s, option, val);
+ dmuci_set_value_by_section(s, option_2, val_2);
+ }
+ }
+}
+
+void update_section_list_icwmpd(char *config, char *section, char *option, int number, char *filter, char *option1, char *val1, char *option2, char *val2)
+{
+ char *add_value;
+ struct uci_section *s = NULL;
+ int i = 0;
+
+ if (option) {
+ uci_path_foreach_option_eq(icwmpd, config, section, option, filter, s) {
+ return;
+ }
+ } else {
+ uci_path_foreach_sections(icwmpd, config, section, s) {
+ return;
+ }
+ }
+ while (i < number) {
+ DMUCI_ADD_SECTION(icwmpd, config, section, &s, &add_value);
+ if (option)DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, option, filter);
+ if (option1)DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, option1, val1);
+ if (option2)DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, option2, val2);
+ i++;
+ }
+}
+
+void update_section_list(char *config, char *section, char *option, int number, char *filter, char *option1, char *val1, char *option2, char *val2)
+{
+ char *add_value;
+ struct uci_section *s = NULL;
+ int i = 0;
+
+ if (config == DMMAP)
+ {
+ if (option) {
+ uci_path_foreach_option_eq(icwmpd, config, section, option, filter, s) {
+ return;
+ }
+ } else {
+ uci_path_foreach_sections(icwmpd, config, section, s) {
+ return;
+ }
+ }
+ while (i < number) {
+ DMUCI_ADD_SECTION(icwmpd, config, section, &s, &add_value);
+ if (option)DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, option, filter);
+ if (option1)DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, option1, val1);
+ if (option2)DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, option2, val2);
+ i++;
+ }
+ }
+ else
+ {
+ if (option) {
+ uci_foreach_option_eq(config, section, option, filter, s) {
+ return;
+ }
+ } else {
+ uci_foreach_sections(config, section, s) {
+ return;
+ }
+ }
+ while (i < number) {
+ dmuci_add_section_and_rename(config, section, &s, &add_value);
+ if (option)dmuci_set_value_by_section(s, option, filter);
+ if (option1)dmuci_set_value_by_section(s, option1, val1);
+ if (option2)dmuci_set_value_by_section(s, option2, val2);
+ i++;
+ }
+ }
+}
+
+char *get_nvram_wpakey() {
+ json_object *res;
+ char *wpakey = "";
+ dmubus_call("router.system", "info", UBUS_ARGS{{}}, 0, &res);
+ if (res)
+ wpakey = dmjson_get_value(res, 2, "keys", "wpa");
+ return dmstrdup(wpakey);
+}
+
+int reset_wlan(struct uci_section *s)
+{
+ dmuci_delete_by_section(s, "gtk_rekey", NULL);
+ dmuci_delete_by_section(s, "cipher", NULL);
+ dmuci_delete_by_section(s, "wps", NULL);
+ dmuci_delete_by_section(s, "key", NULL);
+ dmuci_delete_by_section(s, "key1", NULL);
+ dmuci_delete_by_section(s, "key2", NULL);
+ dmuci_delete_by_section(s, "key3", NULL);
+ dmuci_delete_by_section(s, "key4", NULL);
+ dmuci_delete_by_section(s, "radius_server", NULL);
+ dmuci_delete_by_section(s, "radius_port", NULL);
+ dmuci_delete_by_section(s, "radius_secret", NULL);
+ return 0;
+}
+
+int get_cfg_layer2idx(char *pack, char *section_type, char *option, int shift)
+{
+ char *si, *value;
+ int idx = 0, max = -1;
+ struct uci_section *s = NULL;
+
+ uci_foreach_sections(pack, section_type, s) {
+ dmuci_get_value_by_section_string(s, option, &value);
+ si = value + shift;
+ idx = atoi(si);
+ if (idx > max)
+ max = idx;
+ }
+ return (max + 1);
+}
+
+int wan_remove_dev_interface(struct uci_section *interface_setion, char *dev)
+{
+ char *ifname, new_ifname[64], *p, *pch, *spch;
+ new_ifname[0] = '\0';
+ p = new_ifname;
+ dmuci_get_value_by_section_string(interface_setion, "ifname", &ifname);
+ ifname = dmstrdup(ifname);
+ for (pch = strtok_r(ifname, " ", &spch); pch; pch = strtok_r(NULL, " ", &spch)) {
+ if (!strstr(pch, dev)) {
+ if (new_ifname[0] != '\0') {
+ dmstrappendchr(p, ' ');
+ }
+ dmstrappendstr(p, pch);
+ }
+ }
+ dmstrappendend(p);
+ dmfree(ifname);
+ if (new_ifname[0] == '\0') {
+ dmuci_delete_by_section(interface_setion, NULL, NULL);
+ }
+ else {
+ dmuci_set_value_by_section(interface_setion, "ifname", new_ifname);
+ }
+ return 0;
+}
+
+int filter_lan_device_interface(struct uci_section *s)
+{
+ char *ifname = NULL;
+ char *phy_itf = NULL, *phy_itf_local;
+ char *pch, *spch, *ftype, *islan;
+
+ dmuci_get_value_by_section_string(s, "type", &ftype);
+ if (strcmp(ftype, "alias") != 0) {
+ dmuci_get_value_by_section_string(s, "is_lan", &islan);
+ if (islan[0] == '1' && strcmp(section_name(s), "loopback") != 0 )
+ return 0;
+ dmuci_get_value_by_section_string(s, "ifname", &ifname);
+ db_get_value_string("hw", "board", "ethernetLanPorts", &phy_itf);
+ phy_itf_local = dmstrdup(phy_itf);
+ for (pch = strtok_r(phy_itf_local, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) {
+ if (strstr(ifname, pch)) {
+ dmfree(phy_itf_local);
+ return 0;
+ }
+ }
+ dmfree(phy_itf_local);
+ }
+ return -1;
+}
+
+void update_remove_vlan_from_bridge_interface(char *bridge_key, struct uci_section *vb)
+{
+ char *ifname,*vid;
+ char new_ifname[128];
+ struct uci_section *s;
+
+ uci_foreach_option_eq("network", "interface", "bridge_instance", bridge_key, s)
+ {
+ break;
+ }
+ if (!s) return;
+ dmuci_get_value_by_section_string(vb, "vid", &vid);
+ dmuci_get_value_by_section_string(s, "ifname", &ifname);
+ remove_vid_interfaces_from_ifname(vid, ifname, new_ifname);
+ dmuci_set_value_by_section(s, "ifname", new_ifname);
+}
+
+int filter_lan_ip_interface(struct uci_section *ss, void *v)
+{
+ struct uci_section *lds = (struct uci_section *)v;
+ char *value, *type;
+ dmuci_get_value_by_section_string(ss, "type", &type);
+ if (ss == lds) {
+ return 0;
+ }
+ else if (strcmp(type, "alias") == 0) {
+ dmuci_get_value_by_section_string(ss, "ifname", &value);
+ if(strncmp(value, "br-", 3) == 0)
+ value += 3;
+ if (strcmp(value, section_name(lds)) == 0)
+ return 0;
+ }
+ return -1;
+}
+
+void remove_interface_from_ifname(char *iface, char *ifname, char *new_ifname)
+{
+ char *pch, *spch, *p = new_ifname;
+ new_ifname[0] = '\0';
+
+ ifname = dmstrdup(ifname);
+ pch = strtok_r(ifname, " ", &spch);
+ while (pch != NULL) {
+ if (strcmp(pch, iface) != 0) {
+ if (p == new_ifname) {
+ dmstrappendstr(p, pch);
+ }
+ else {
+ dmstrappendchr(p, ' ');
+ dmstrappendstr(p, pch);
+ }
+ }
+ pch = strtok_r(NULL, " ", &spch);
+ }
+ dmstrappendend(p);
+ dmfree(ifname);
+}
+
+int max_array(int a[], int size)
+{
+ int i, max = 0;
+ for (i = 0; i< size; i++)
+ {
+ if(a[i] > max )
+ max = a[i];
+ }
+ return max;
+}
+
+int check_ifname_is_vlan(char *ifname)
+{
+ struct uci_section *s;
+ char *type;
+
+ uci_foreach_option_eq("network", "device", "name", ifname, s) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if(strcasecmp(type, "untagged") != 0)
+ return 1;
+ }
+ return 0;
+}
+
+int dmcommon_check_notification_value(char *value)
+{
+ int i;
+ for (i = 0; i< __MAX_notification; i++) {
+ if (strcmp(value, array_notifcation_char[i]) == 0)
+ return 0;
+ }
+ return -1;
+}
+
+char *print_bin(unsigned int n, char *buf, int sep)
+{
+ int i = 0, j;
+ for (j = 0; j < 32; j++) {
+ if (j % sep == 0)
+ buf[i++] = ' ';
+ buf[i++] = (n & (1<iface = strtok_r(line, " \t", &spch);
+ pch = strtok_r(NULL, " \t", &spch);
+ hex_to_ip(pch, proute->destination);
+ pch = strtok_r(NULL, " \t", &spch);
+ hex_to_ip(pch, proute->gateway);
+ proute->flags = strtok_r(NULL, " \t", &spch);
+ proute->refcnt = strtok_r(NULL, " \t", &spch);
+ proute->use = strtok_r(NULL, " \t", &spch);
+ proute->metric = strtok_r(NULL, " \t", &spch);
+ pch = strtok_r(NULL, " \t", &spch);
+ hex_to_ip(pch, proute->mask);
+ proute->mtu = strtok_r(NULL, " \t", &spch);
+ proute->window = strtok_r(NULL, " \t", &spch);
+ proute->irtt = strtok_r(NULL, " \t\n\r", &spch);
+}
+
+void hex_to_ip(char *address, char *ret)
+{
+ int ip[4] = {0};
+
+ sscanf(address, "%2x%2x%2x%2x", &(ip[0]), &(ip[1]), &(ip[2]), &(ip[3]));
+ if (htonl(13) == 13) {
+ sprintf(ret, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+ } else {
+ sprintf(ret, "%d.%d.%d.%d", ip[3], ip[2], ip[1], ip[0]);
+ }
+}
+
+void ip_to_hex(char *address, char *ret)
+{
+ int ip[4] = {0};
+
+ sscanf(address, "%d.%d.%d.%d", &(ip[0]), &(ip[1]), &(ip[2]), &(ip[3]));
+ sprintf(ret, "%02X%02X%02X%02X", ip[0], ip[1], ip[2], ip[3]);
+}
+
+/*
+ * dmmap_config sections list manipulation
+ */
+void add_sectons_list_paramameter(struct list_head *dup_list, struct uci_section *config_section, struct uci_section *dmmap_section, void* additional_attribute)
+{
+ struct dmmap_dup *dmmap_config;
+ struct list_head *ilist;
+
+ dmmap_config = dmcalloc(1, sizeof(struct dmmap_dup));
+ list_add_tail(&dmmap_config->list, dup_list);
+ dmmap_config->config_section = config_section;
+ dmmap_config->dmmap_section = dmmap_section;
+ dmmap_config->additional_attribute = additional_attribute;
+}
+
+
+void dmmap_config_dup_delete(struct dmmap_dup *dmmap_config)
+{
+ list_del(&dmmap_config->list);
+}
+
+void free_dmmap_config_dup_list(struct list_head *dup_list)
+{
+ struct dmmap_dup *dmmap_config;
+ while (dup_list->next != dup_list) {
+ dmmap_config = list_entry(dup_list->next, struct dmmap_dup, list);
+ dmmap_config_dup_delete(dmmap_config);
+ }
+}
+
+/*
+ * Function allows to synchronize config section with dmmap config
+ */
+
+struct uci_section *get_origin_section_from_config(char *package, char *section_type, char *orig_section_name)
+{
+ struct uci_section *s;
+
+ uci_foreach_sections(package, section_type, s) {
+ if (strcmp(section_name(s), orig_section_name) == 0){
+ return s;
+ }
+ }
+ return NULL;
+}
+
+struct uci_section *get_dup_section_in_dmmap(char *dmmap_package, char *section_type, char *orig_section_name)
+{
+ struct uci_section *s;
+
+ uci_path_foreach_option_eq(icwmpd, dmmap_package, section_type, "section_name", orig_section_name, s)
+ {
+ return s;
+ }
+
+ return NULL;
+}
+
+struct uci_section *get_dup_section_in_dmmap_eq(char *dmmap_package, char* section_type, char*sect_name, char *opt_name, char* opt_value)
+{
+ struct uci_section *s;
+ char *v;
+
+ uci_path_foreach_option_eq(icwmpd, dmmap_package, section_type, "section_name", sect_name, s) {
+ dmuci_get_value_by_section_string(s, opt_name, &v);
+ if(strcmp(v, opt_value)== 0)
+ return s;
+ }
+ return NULL;
+}
+
+void synchronize_specific_config_sections_with_dmmap(char *package, char *section_type, char *dmmap_package, struct list_head *dup_list)
+{
+ struct uci_section *s, *stmp, *dmmap_sect;
+ FILE *fp;
+ char *v, *dmmap_file_path;
+
+ dmasprintf(&dmmap_file_path, "/etc/icwmpd/%s", dmmap_package);
+ if (access(dmmap_file_path, F_OK)) {
+ /*
+ *File does not exist
+ **/
+ fp = fopen(dmmap_file_path, "w"); // new empty file
+ fclose(fp);
+ }
+ uci_foreach_sections(package, section_type, s) {
+ /*
+ * create/update corresponding dmmap section that have same config_section link and using param_value_array
+ */
+ if ((dmmap_sect = get_dup_section_in_dmmap(dmmap_package, section_type, section_name(s))) == NULL) {
+ dmuci_add_section_icwmpd(dmmap_package, section_type, &dmmap_sect, &v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(s));
+ }
+
+ /*
+ * Add system and dmmap sections to the list
+ */
+ add_sectons_list_paramameter(dup_list, s, dmmap_sect, NULL);
+ }
+
+ /*
+ * Delete unused dmmap sections
+ */
+ uci_path_foreach_sections_safe(icwmpd, dmmap_package, section_type, stmp, s) {
+ dmuci_get_value_by_section_string(s, "section_name", &v);
+ if(get_origin_section_from_config(package, section_type, v) == NULL){
+ dmuci_delete_by_section_unnamed_icwmpd(s, NULL, NULL);
+ }
+ }
+}
+
+void synchronize_specific_config_sections_with_dmmap_eq(char *package, char *section_type, char *dmmap_package,char* option_name, char* option_value, struct list_head *dup_list)
+{
+ struct uci_section *s, *stmp, *dmmap_sect;
+ FILE *fp;
+ char *v, *dmmap_file_path;
+
+ dmasprintf(&dmmap_file_path, "/etc/icwmpd/%s", dmmap_package);
+ if (access(dmmap_file_path, F_OK)) {
+ /*
+ *File does not exist
+ **/
+ fp = fopen(dmmap_file_path, "w"); // new empty file
+ fclose(fp);
+ }
+ uci_foreach_option_eq(package, section_type, option_name, option_value, s) {
+ /*
+ * create/update corresponding dmmap section that have same config_section link and using param_value_array
+ */
+ if ((dmmap_sect = get_dup_section_in_dmmap(dmmap_package, section_type, section_name(s))) == NULL) {
+ dmuci_add_section_icwmpd(dmmap_package, section_type, &dmmap_sect, &v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(s));
+ }
+
+ /*
+ * Add system and dmmap sections to the list
+ */
+ add_sectons_list_paramameter(dup_list, s, dmmap_sect, NULL);
+ }
+
+ /*
+ * Delete unused dmmap sections
+ */
+ uci_path_foreach_sections_safe(icwmpd, dmmap_package, section_type, stmp, s) {
+ dmuci_get_value_by_section_string(s, "section_name", &v);
+ if(get_origin_section_from_config(package, section_type, v) == NULL){
+ dmuci_delete_by_section(s, NULL, NULL);
+ }
+ }
+}
+
+void synchronize_specific_config_sections_with_dmmap_eq_no_delete(char *package, char *section_type, char *dmmap_package, char* option_name, char* option_value, struct list_head *dup_list)
+{
+ struct uci_section *s, *dmmap_sect;
+ FILE *fp;
+ char *v, *dmmap_file_path;
+
+ dmasprintf(&dmmap_file_path, "/etc/icwmpd/%s", dmmap_package);
+ if (access(dmmap_file_path, F_OK)) {
+ /*
+ *File does not exist
+ **/
+ fp = fopen(dmmap_file_path, "w"); // new empty file
+ fclose(fp);
+ }
+ uci_foreach_option_eq(package, section_type, option_name, option_value, s) {
+ /*
+ * create/update corresponding dmmap section that have same config_section link and using param_value_array
+ */
+ if ((dmmap_sect = get_dup_section_in_dmmap(dmmap_package, section_type, section_name(s))) == NULL) {
+ dmuci_add_section_icwmpd(dmmap_package, section_type, &dmmap_sect, &v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(s));
+ }
+ }
+
+ dmmap_sect= NULL;
+ s= NULL;
+ uci_path_foreach_sections(icwmpd, dmmap_package, section_type, dmmap_sect) {
+ dmuci_get_value_by_section_string(dmmap_sect, "section_name", &v);
+ get_config_section_of_dmmap_section("network", "interface", v, &s);
+ add_sectons_list_paramameter(dup_list, s, dmmap_sect, NULL);
+ }
+}
+
+void synchronize_specific_config_sections_with_dmmap_cont(char *package, char *section_type, char *dmmap_package,char* option_name, char* option_value, struct list_head *dup_list)
+{
+ struct uci_section *s, *stmp, *dmmap_sect;
+ FILE *fp;
+ char *v, *dmmap_file_path;
+
+ dmasprintf(&dmmap_file_path, "/etc/icwmpd/%s", dmmap_package);
+ if (access(dmmap_file_path, F_OK)) {
+ /*
+ *File does not exist
+ **/
+ fp = fopen(dmmap_file_path, "w"); // new empty file
+ fclose(fp);
+ }
+ uci_foreach_option_cont(package, section_type, option_name, option_value, s) {
+ /*
+ * create/update corresponding dmmap section that have same config_section link and using param_value_array
+ */
+ if ((dmmap_sect = get_dup_section_in_dmmap(dmmap_package, section_type, section_name(s))) == NULL) {
+ dmuci_add_section_icwmpd(dmmap_package, section_type, &dmmap_sect, &v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(s));
+ }
+
+ /*
+ * Add system and dmmap sections to the list
+ */
+ add_sectons_list_paramameter(dup_list, s, dmmap_sect, NULL);
+ }
+
+ /*
+ * Delete unused dmmap sections
+ */
+ uci_path_foreach_sections_safe(icwmpd, dmmap_package, section_type, stmp, s) {
+ dmuci_get_value_by_section_string(s, "section_name", &v);
+
+ if(get_origin_section_from_config(package, section_type, v) == NULL){
+ dmuci_delete_by_section(s, NULL, NULL);
+ }
+ }
+}
+
+bool synchronize_multi_config_sections_with_dmmap_eq(char *package, char *section_type, char *dmmap_package, char* dmmap_section, char* option_name, char* option_value, void* additional_attribute, struct list_head *dup_list)
+{
+ struct uci_section *s, *stmp, *dmmap_sect;
+ FILE *fp;
+ char *v, *dmmap_file_path, *pack, *sect;
+ bool found = false;
+
+ dmasprintf(&dmmap_file_path, "/etc/icwmpd/%s", dmmap_package);
+ if (access(dmmap_file_path, F_OK)) {
+ /*
+ *File does not exist
+ **/
+ fp = fopen(dmmap_file_path, "w"); // new empty file
+ fclose(fp);
+ }
+
+ uci_foreach_option_eq(package, section_type, option_name, option_value, s) {
+ found = true;
+ /*
+ * create/update corresponding dmmap section that have same config_section link and using param_value_array
+ */
+ if ((dmmap_sect = get_dup_section_in_dmmap(dmmap_package, dmmap_section, section_name(s))) == NULL) {
+ dmuci_add_section_icwmpd(dmmap_package, dmmap_section, &dmmap_sect, &v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(s));
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "package", package);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section", section_type);
+ }
+
+ /*
+ * Add system and dmmap sections to the list
+ */
+ add_sectons_list_paramameter(dup_list, s, dmmap_sect, additional_attribute);
+ }
+
+ /*
+ * Delete unused dmmap sections
+ */
+ uci_path_foreach_sections_safe(icwmpd, dmmap_package, dmmap_section, stmp, s) {
+ dmuci_get_value_by_section_string(s, "section_name", &v);
+ dmuci_get_value_by_section_string(s, "package", &pack);
+ dmuci_get_value_by_section_string(s, "section", §);
+ if(v!=NULL && strlen(v)>0 && strcmp(package, pack)==0 && strcmp(section_type, sect)== 0){
+ if(get_origin_section_from_config(package, section_type, v) == NULL){
+ dmuci_delete_by_section(s, NULL, NULL);
+ }
+ }
+ }
+
+ return found;
+}
+
+bool synchronize_multi_config_sections_with_dmmap_eq_diff(char *package, char *section_type, char *dmmap_package, char* dmmap_section, char* option_name, char* option_value, char* opt_diff_name, char* opt_diff_value, void* additional_attribute, struct list_head *dup_list)
+{
+ struct uci_section *s, *stmp, *dmmap_sect;
+ FILE *fp;
+ char *v, *dmmap_file_path, *pack, *sect, *optval;
+ bool found= false;
+
+ dmasprintf(&dmmap_file_path, "/etc/icwmpd/%s", dmmap_package);
+ if (access(dmmap_file_path, F_OK)) {
+ /*
+ *File does not exist
+ **/
+ fp = fopen(dmmap_file_path, "w"); // new empty file
+ fclose(fp);
+ }
+
+ uci_foreach_option_eq(package, section_type, option_name, option_value, s) {
+ found = true;
+ dmuci_get_value_by_section_string(s, opt_diff_name, &optval);
+ if (strcmp(optval, opt_diff_value) != 0) {
+ /*
+ * create/update corresponding dmmap section that have same config_section link and using param_value_array
+ */
+ if ((dmmap_sect = get_dup_section_in_dmmap(dmmap_package, dmmap_section, section_name(s))) == NULL) {
+ dmuci_add_section_icwmpd(dmmap_package, dmmap_section, &dmmap_sect, &v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(s));
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "package", package);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section", section_type);
+ }
+
+ /*
+ * Add system and dmmap sections to the list
+ */
+ add_sectons_list_paramameter(dup_list, s, dmmap_sect, additional_attribute);
+ }
+ }
+
+ /*
+ * Delete unused dmmap sections
+ */
+ uci_path_foreach_sections_safe(icwmpd, dmmap_package, dmmap_section, stmp, s) {
+ dmuci_get_value_by_section_string(s, "section_name", &v);
+ dmuci_get_value_by_section_string(s, "package", &pack);
+ dmuci_get_value_by_section_string(s, "section", §);
+ if(v!=NULL && strlen(v)>0 && strcmp(package, pack)==0 && strcmp(section_type, sect)== 0){
+ if(get_origin_section_from_config(package, section_type, v) == NULL){
+ dmuci_delete_by_section(s, NULL, NULL);
+ }
+ }
+ }
+
+ return found;
+}
+
+void get_dmmap_section_of_config_section(char* dmmap_package, char* section_type, char *section_name, struct uci_section **dmmap_section)
+{
+ struct uci_section* s;
+
+ uci_path_foreach_option_eq(icwmpd, dmmap_package, section_type, "section_name", section_name, s){
+ *dmmap_section= s;
+ return;
+ }
+ *dmmap_section= NULL;
+}
+
+void get_dmmap_section_of_config_section_eq(char* dmmap_package, char* section_type, char *opt, char* value, struct uci_section **dmmap_section)
+{
+ struct uci_section* s;
+
+ uci_path_foreach_option_eq(icwmpd, dmmap_package, section_type, opt, value, s){
+ *dmmap_section= s;
+ return;
+ }
+ *dmmap_section= NULL;
+}
+
+void get_config_section_of_dmmap_section(char* package, char* section_type, char *section_name, struct uci_section **config_section)
+{
+ struct uci_section* s;
+
+ uci_foreach_sections(package, section_type, s){
+ if(strcmp(section_name(s), section_name)==0){
+ *config_section= s;
+ return;
+ }
+ }
+ *config_section= NULL;
+}
+
+void check_create_dmmap_package(char *dmmap_package)
+{
+ FILE *fp;
+ char *dmmap_file_path;
+
+ dmasprintf(&dmmap_file_path, "/etc/icwmpd/%s", dmmap_package);
+ if (access(dmmap_file_path, F_OK)) {
+ /*
+ *File does not exist
+ **/
+ fp = fopen(dmmap_file_path, "w"); // new empty file
+ fclose(fp);
+ }
+ dmfree(dmmap_file_path);
+}
+
+int is_section_unnamed(char *section_name)
+{
+ int i;
+
+ if(strlen(section_name)!=9)
+ return 0;
+ if(strstr(section_name, "cfg") != section_name)
+ return 0;
+ for(i=3; i<9; i++){
+ if(!isxdigit(section_name[i]))
+ return 0;
+ }
+ return 1;
+}
+
+
+void add_dmmap_list_section(struct list_head *dup_list, char* section_name, char* instance)
+{
+ struct dmmap_sect *dmsect;
+
+ dmsect = dmcalloc(1, sizeof(struct dmmap_sect));
+ list_add_tail(&dmsect->list, dup_list);
+ dmasprintf(&dmsect->section_name, "%s", section_name);
+ dmasprintf(&dmsect->instance, "%s", instance);
+}
+
+void delete_sections_save_next_sections(char* dmmap_package, char *section_type, char *instancename, char *section_name, int instance, struct list_head *dup_list)
+{
+ struct uci_section *s, *stmp;
+ char *v=NULL, *lsectname= NULL, *tmp= NULL;
+ int inst;
+
+ asprintf(&lsectname, "%s", section_name);
+
+ uci_path_foreach_sections(icwmpd, dmmap_package, section_type, s) {
+ dmuci_get_value_by_section_string(s, instancename, &v);
+ inst= atoi(v);
+ if(inst>instance){
+ dmuci_get_value_by_section_string(s, "section_name", &tmp);
+ add_dmmap_list_section(dup_list, lsectname, v);
+ free(lsectname);
+ lsectname= NULL;
+ asprintf(&lsectname, "%s", tmp);
+ free(tmp);
+ tmp= NULL;
+ }
+ }
+
+ if(lsectname != NULL) free(lsectname);
+
+
+ uci_path_foreach_sections_safe(icwmpd, dmmap_package, section_type, stmp, s) {
+ dmuci_get_value_by_section_string(s, instancename, &v);
+ inst= atoi(v);
+ if(inst>=instance)
+ dmuci_delete_by_section_unnamed_icwmpd(s, NULL, NULL);
+ }
+}
+
+void update_dmmap_sections(struct list_head *dup_list, char *instancename, char* dmmap_package, char *section_type)
+{
+ struct uci_section *dm_sect;
+ char *v;
+ struct dmmap_sect *p;
+
+ list_for_each_entry(p, dup_list, list) {
+ dmuci_add_section_icwmpd(dmmap_package, section_type, &dm_sect, &v);
+ dmuci_set_value_by_section(dm_sect, "section_name", p->section_name);
+ dmuci_set_value_by_section(dm_sect, instancename, p->instance);
+ }
+}
+
+struct uci_section *is_dmmap_section_exist(char* package, char* section)
+{
+ struct uci_section *s;
+
+ uci_path_foreach_sections(icwmpd, package, section, s) {
+ return s;
+ }
+ return NULL;
+}
+
+struct uci_section *is_dmmap_section_exist_eq(char* package, char* section, char* opt, char* value)
+{
+ struct uci_section *s;
+
+ uci_path_foreach_option_eq(icwmpd, package, section, opt, value, s) {
+ return s;
+ }
+ return NULL;
+}
+
+unsigned char isdigit_str(char *str)
+{
+ if (!(*str)) return 0;
+ while(isdigit(*str++));
+ return ((*(str-1)) ? 0 : 1);
+}
+
+static inline int isword_delim(char c)
+{
+ if (c == ' ' ||
+ c == ',' ||
+ c == '\t' ||
+ c == '\v' ||
+ c == '\r' ||
+ c == '\n' ||
+ c == '\0')
+ return 1;
+ return 0;
+}
+
+char *dm_strword(char *src, char *str)
+{
+ char *ret = src;
+ int len;
+ if (src[0] == '\0')
+ return NULL;
+ len = strlen(str);
+ while ((ret = strstr(ret, str)) != NULL) {
+ if ((ret == src && isword_delim(ret[len])) ||
+ (ret != src && isword_delim(ret[len]) && isword_delim(*(ret - 1))))
+ return ret;
+ ret++;
+ }
+ return NULL;
+}
+
+char **strsplit(const char* str, const char* delim, size_t* numtokens)
+{
+ // copy the original string so that we don't overwrite parts of it
+ // (don't do this if you don't need to keep the old line,
+ // as this is less efficient)
+ char *s = strdup(str);
+ // these three variables are part of a very common idiom to
+ // implement a dynamically-growing array
+ size_t tokens_alloc = 1;
+ size_t tokens_used = 0;
+ char **tokens = calloc(tokens_alloc, sizeof(char*));
+ char *token, *strtok_ctx;
+ for (token = strtok_r(s, delim, &strtok_ctx);
+ token != NULL;
+ token = strtok_r(NULL, delim, &strtok_ctx)) {
+ // check if we need to allocate more space for tokens
+ if (tokens_used == tokens_alloc) {
+ tokens_alloc *= 2;
+ tokens = realloc(tokens, tokens_alloc * sizeof(char*));
+ }
+ tokens[tokens_used++] = strdup(token);
+ }
+ // cleanup
+ if (tokens_used == 0) {
+ free(tokens);
+ tokens = NULL;
+ } else {
+ tokens = realloc(tokens, tokens_used * sizeof(char*));
+ }
+ *numtokens = tokens_used;
+ free(s);
+ return tokens;
+}
+
+char *get_macaddr(char *interface_name)
+{
+ json_object *res;
+ char *device, *mac = "";
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface_name, String}}, 1, &res);
+ device = dmjson_get_value(res, 1, "device");
+ if(device[0] == '\0')
+ return "";
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", device, String}}, 1, &res);
+ mac = dmjson_get_value(res, 1, "macaddr");
+ return mac;
+}
+
+char *get_device(char *interface_name)
+{
+ json_object *res;
+ char *device = "";
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface_name, String}}, 1, &res);
+ device = dmjson_get_value(res, 1, "device");
+ return device;
+}
+
+/*
+ * Manage string lists
+ */
+
+int is_elt_exit_in_str_list(char *str_list, char *elt)
+{
+ char *pch, *spch, *list;
+ list= dmstrdup(str_list);
+ for (pch = strtok_r(list, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) {
+ if(strcmp(pch, elt) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+void add_elt_to_str_list(char **str_list, char *elt)
+{
+ char *list= NULL;
+ if(*str_list == NULL || strlen(*str_list) == 0){
+ dmasprintf(str_list, "%s", elt);
+ return;
+ }
+ list= dmstrdup(*str_list);
+ dmfree(*str_list);
+ *str_list= NULL;
+ dmasprintf(str_list, "%s %s", list, elt);
+}
+
+void remove_elt_from_str_list(char **iface_list, char *ifname)
+{
+ char *list= NULL, *tmp=NULL;
+ char *pch, *spch;
+ if (*iface_list == NULL || strlen(*iface_list) == 0)
+ return;
+ list= dmstrdup(*iface_list);
+ dmfree(*iface_list);
+ *iface_list= NULL;
+ for (pch = strtok_r(list, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) {
+ if(strcmp(pch, ifname) == 0)
+ continue;
+ if(tmp == NULL)
+ dmasprintf(iface_list, "%s", pch);
+ else
+ dmasprintf(iface_list, "%s %s", tmp, pch);
+ if(tmp){
+ dmfree(tmp);
+ tmp= NULL;
+ }
+ if(*iface_list){
+ tmp= dmstrdup(*iface_list);
+ dmfree(*iface_list);
+ *iface_list= NULL;
+ }
+ }
+ dmasprintf(iface_list, "%s", tmp);
+}
+
+int is_array_elt_exist(char **str_array, char *str, int length)
+{
+ int i;
+
+ for(i=0; i
+ * Author: Feten Besbes
+ */
+
+#ifndef __DM_COMMON_H
+#define __DM_COMMON_H
+#include
+#include
+#include
+#include
+#include "dmcwmp.h"
+#define NVRAM_FILE "/proc/nvram/WpaKey"
+#define MAX_DHCP_LEASES 256
+#define MAX_PROC_ROUTING 256
+#define ROUTING_FILE "/proc/net/route"
+#define ARP_FILE "/proc/net/arp"
+#define DHCP_LEASES_FILE "/tmp/dhcp.leases"
+#define DMMAP "dmmap"
+#define DHCPSTATICADDRESS_DISABLED_CHADDR "00:00:00:00:00:01"
+#define DM_ASSERT(X, Y) \
+do { \
+ if(!(X)) { \
+ Y; \
+ return -1; \
+ } \
+} while(0)
+
+#define dmstrappendstr(dest, src) \
+do { \
+ int len = strlen(src); \
+ memcpy(dest, src, len); \
+ dest += len; \
+} while(0)
+
+#define dmstrappendchr(dest, c) \
+do { \
+ *dest = c; \
+ dest += 1; \
+} while(0)
+
+#define dmstrappendend(dest) \
+do { \
+ *dest = '\0'; \
+} while(0)
+
+
+#define DMCMD(CMD, N, ...) \
+do { \
+ int mpp = dmcmd(CMD, N, ## __VA_ARGS__); \
+ if (mpp) close (mpp); \
+} while (0)
+
+#define IPPING_PATH "/usr/share/icwmp/functions/ipping_launch"
+#define IPPING_STOP DMCMD("/bin/sh", 2, IPPING_PATH, "stop");
+#define DOWNLOAD_DIAGNOSTIC_PATH "/usr/share/icwmp/functions/download_launch"
+#define DOWNLOAD_DUMP_FILE "/tmp/download_dump"
+#define DOWNLOAD_DIAGNOSTIC_STOP DMCMD("/bin/sh", 2, DOWNLOAD_DIAGNOSTIC_PATH, "stop");
+#define UPLOAD_DIAGNOSTIC_PATH "/usr/share/icwmp/functions/upload_launch"
+#define UPLOAD_DUMP_FILE "/tmp/upload_dump"
+#define UPLOAD_DIAGNOSTIC_STOP DMCMD("/bin/sh", 2, UPLOAD_DIAGNOSTIC_PATH, "stop");
+#define NSLOOKUP_PATH "/usr/share/icwmp/functions/nslookup_launch"
+#define NSLOOKUP_LOG_FILE "/tmp/nslookup.log"
+#define NSLOOKUP_STOP DMCMD("/bin/sh", 2, NSLOOKUP_PATH, "stop");
+#define TRACEROUTE_PATH "/usr/share/icwmp/functions/traceroute_launch"
+#define TRACEROUTE_STOP DMCMD("/bin/sh", 2, TRACEROUTE_PATH, "stop");
+#define UDPECHO_PATH "/usr/share/icwmp/functions/udpecho_launch"
+#define UDPECHO_STOP DMCMD("/bin/sh", 2, UDPECHO_PATH, "stop");
+#define SERVERSELECTION_PATH "/usr/share/icwmp/functions/serverselection_launch"
+#define SERVERSELECTION_STOP DMCMD("/bin/sh", 2, SERVERSELECTION_PATH, "stop");
+
+enum notification_enum {
+ notification_none,
+ notification_passive,
+ notification_active,
+ notification_passive_lw,
+ notification_ppassive_passive_lw,
+ notification_aactive_lw,
+ notification_passive_active_lw,
+ __MAX_notification
+};
+
+enum strstructered_enum {
+ STRUCTERED_SAME,
+ STRUCTERED_PART,
+ STRUCTERED_NULL
+};
+
+struct proc_routing {
+ char *iface;
+ char *flags;
+ char *refcnt;
+ char *use;
+ char *metric;
+ char *mtu;
+ char *window;
+ char *irtt;
+ char destination[16];
+ char gateway[16];
+ char mask[16];
+};
+
+struct routingfwdargs
+{
+ char *permission;
+ struct uci_section *routefwdsection;
+ struct proc_routing *proute;
+ int type;
+};
+
+struct dmmap_dup
+{
+ struct list_head list;
+ struct uci_section *config_section;
+ struct uci_section *dmmap_section;
+ void* additional_attribute;
+};
+
+struct dmmap_sect {
+ struct list_head list;
+ char *section_name;
+ char *instance;
+};
+
+struct dm_args
+{
+ struct uci_section *section;
+ struct uci_section *dmmap_section;
+ char *name;
+};
+
+void compress_spaces(char *str);
+char *cut_fx(char *str, char *delimiter, int occurence);
+pid_t get_pid(char *pname);
+int check_file(char *path);
+char *cidr2netmask(int bits);
+void remove_substring(char *s, const char *str_remove);
+bool is_strword_in_optionvalue(char *optionvalue, char *str);
+int get_interface_enable_ubus(char *iface, char *refparam, struct dmctx *ctx, char **value);
+int set_interface_enable_ubus(char *iface, char *refparam, struct dmctx *ctx, int action, char *value);
+int get_interface_firewall_enabled(char *iface, char *refparam, struct dmctx *ctx, char **value);
+struct uci_section *create_firewall_zone_config(char *fwl, char *iface, char *input, char *forward, char *output);
+int set_interface_firewall_enabled(char *iface, char *refparam, struct dmctx *ctx, int action, char *value);
+int dmcmd(char *cmd, int n, ...);
+int dmcmd_read(int pipe, char *buffer, int size);
+void dmcmd_read_alloc(int pipe, char **value);
+int dmcmd_no_wait(char *cmd, int n, ...);
+int ipcalc(char *ip_str, char *mask_str, char *start_str, char *end_str, char *ipstart_str, char *ipend_str);
+int ipcalc_rev_start(char *ip_str, char *mask_str, char *ipstart_str, char *start_str);
+int ipcalc_rev_end(char *ip_str, char *mask_str, char *start_str, char *ipend_str, char *end_str);
+int network_get_ipaddr(char **value, char *iface);
+void remove_vid_interfaces_from_ifname(char *vid, char *ifname, char *new_ifname);
+void update_section_option_list(char *config, char *section, char *option, char *option_2,char *val, char *val_2, char *name);
+void update_section_list_icwmpd(char *config, char *section, char *option, int number, char *filter, char *option1, char *val1, char *option2, char *val2);
+void update_section_list(char *config, char *section, char *option, int number, char *filter, char *option1, char *val1, char *option2, char *val2);
+char *get_nvram_wpakey();
+int reset_wlan(struct uci_section *s);
+int get_cfg_layer2idx(char *pack, char *section_type, char *option, int shift);
+int wan_remove_dev_interface(struct uci_section *interface_setion, char *dev);
+int filter_lan_device_interface(struct uci_section *s);
+void remove_vlan_from_bridge_interface(char *bridge_key, struct uci_section *vb);
+void update_remove_vlan_from_bridge_interface(char *bridge_key, struct uci_section *vb);
+int filter_lan_ip_interface(struct uci_section *ss, void *v);
+void remove_interface_from_ifname(char *iface, char *ifname, char *new_ifname);
+int max_array(int a[], int size);
+int check_ifname_is_vlan(char *ifname);
+int set_uci_dhcpserver_option(struct dmctx *ctx, struct uci_section *s, char *option, char *value);
+int update_uci_dhcpserver_option(struct dmctx *ctx, struct uci_section *s, char *option, char * new_option, char *value);
+void parse_proc_route_line(char *line, struct proc_routing *proute);
+int strstructered(char *str1, char *str2);
+int dmcommon_check_notification_value(char *value);
+void hex_to_ip(char *address, char *ret);
+void ip_to_hex(char *address, char *ret);
+void free_dmmap_config_dup_list(struct list_head *dup_list);
+void synchronize_specific_config_sections_with_dmmap(char *package, char *section_type, char *dmmap_package, struct list_head *dup_list);
+void synchronize_specific_config_sections_with_dmmap_eq(char *package, char *section_type, char *dmmap_package,char* option_name, char* option_value, struct list_head *dup_list);
+void synchronize_specific_config_sections_with_dmmap_eq_no_delete(char *package, char *section_type, char *dmmap_package,char* option_name, char* option_value, struct list_head *dup_list);
+void synchronize_specific_config_sections_with_dmmap_cont(char *package, char *section_type, char *dmmap_package,char* option_name, char* option_value, struct list_head *dup_list);
+bool synchronize_multi_config_sections_with_dmmap_eq(char *package, char *section_type, char *dmmap_package, char* dmmap_section, char* option_name, char* option_value, void* additional_attribute, struct list_head *dup_list);
+bool synchronize_multi_config_sections_with_dmmap_eq_diff(char *package, char *section_type, char *dmmap_package, char* dmmap_section, char* option_name, char* option_value, char* opt_diff_name, char* opt_diff_value, void* additional_attribute, struct list_head *dup_list);
+void get_dmmap_section_of_config_section(char* dmmap_package, char* section_type, char *section_name, struct uci_section **dmmap_section);
+void get_dmmap_section_of_config_section_eq(char* dmmap_package, char* section_type, char *opt, char* value, struct uci_section **dmmap_section);
+void get_config_section_of_dmmap_section(char* package, char* section_type, char *section_name, struct uci_section **config_section);
+void check_create_dmmap_package(char *dmmap_package);
+int is_section_unnamed(char *section_name);
+void delete_sections_save_next_sections(char* dmmap_package, char *section_type, char *instancename, char *section_name, int instance, struct list_head *dup_list);
+void update_dmmap_sections(struct list_head *dup_list, char *instancename, char* dmmap_package, char *section_type);
+unsigned char isdigit_str(char *str);
+char *dm_strword(char *src, char *str);
+char **strsplit(const char* str, const char* delim, size_t* numtokens);
+char *get_macaddr(char *ifname);
+char *get_device(char *ifname);
+int is_elt_exit_in_str_list(char *str_list, char *elt);
+void add_elt_to_str_list(char **str_list, char *elt);
+void remove_elt_from_str_list(char **iface_list, char *ifname);
+struct uci_section *get_dup_section_in_dmmap_eq(char *dmmap_package, char* section_type, char*sect_name, char *opt_name, char* opt_value);
+int is_array_elt_exist(char **str_array, char *str, int length);
+int get_shift_time_time(int shift_time, char *local_time, int size);
+int get_shift_time_shift(char *local_time, char *shift);
+int get_stats_from_ifconfig_command(char *device, char *direction, char *option);
+int command_exec_output_to_array(char *cmd, char **output, int *length);
+char* int_period_to_date_time_format(int time);
+int copy_temporary_file_to_original_file(char *f1, char *f2);
+struct uci_section *is_dmmap_section_exist(char* package, char* section);
+struct uci_section *is_dmmap_section_exist_eq(char* package, char* section, char* opt, char* value);
+
+#endif
diff --git a/dmcwmp.c b/dmcwmp.c
new file mode 100644
index 00000000..3a1fe1da
--- /dev/null
+++ b/dmcwmp.c
@@ -0,0 +1,3169 @@
+/*
+ *
+ * Copyright (C) 2015 Inteno Broadband Technology AB
+ * Author MOHAMED Kallel
+ * Author Imen Bhiri
+ * Author Feten Besbes
+ * Author Omar Kallel
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include "dmuci.h"
+#include "dmcwmp.h"
+#include "dmmem.h"
+#include "device.h"
+#include "times.h"
+#include "upnp.h"
+#include "deviceinfo.h"
+#include "managementserver.h"
+#include "x_iopsys_eu_igmp.h"
+#include "x_iopsys_eu_ice.h"
+#include "x_iopsys_eu_power_mgmt.h"
+#include "x_iopsys_eu_ipacccfg.h"
+#include "x_iopsys_eu_logincfg.h"
+#include "x_iopsys_eu_syslog.h"
+#include "dmcommon.h"
+#include "wifi.h"
+#include "ethernet.h"
+#include "atm.h"
+#include "ptm.h"
+#include "bridging.h"
+#include "hosts.h"
+#include "dhcpv4.h"
+#include "ip.h"
+#include "ppp.h"
+#include "softwaremodules.h"
+#include "routing.h"
+#include "nat.h"
+#include "xmpp.h"
+#include "dmcwmp.h"
+#include "dmjson.h"
+#ifdef BBF_TR104
+#include "voice_services.h"
+#endif
+
+static char *get_parameter_notification(struct dmctx *ctx, char *param);
+static int remove_parameter_notification(char *param);
+static int set_parameter_notification(struct dmctx *ctx, char *param,char *value);
+static int get_value_obj(DMOBJECT_ARGS);
+static int get_value_param(DMPARAM_ARGS);
+static int mobj_get_value_in_param(DMOBJECT_ARGS);
+static int mparam_get_value_in_param(DMPARAM_ARGS);
+static int mparam_get_name(DMPARAM_ARGS);
+static int mobj_get_name(DMOBJECT_ARGS);
+static int mparam_get_name_in_param(DMPARAM_ARGS);
+static int mobj_get_name_in_param(DMOBJECT_ARGS);
+static int mparam_get_name_in_obj(DMPARAM_ARGS);
+static int mobj_get_name_in_obj(DMOBJECT_ARGS);
+static int inform_check_obj(DMOBJECT_ARGS);
+static int inform_check_param(DMPARAM_ARGS);
+static int mparam_add_object(DMPARAM_ARGS);
+static int mobj_add_object(DMOBJECT_ARGS);
+static int delete_object_obj(DMOBJECT_ARGS);
+static int delete_object_param(DMPARAM_ARGS);
+static int mobj_set_value(DMOBJECT_ARGS);
+static int mparam_set_value(DMPARAM_ARGS);
+static int mobj_get_notification_in_param(DMOBJECT_ARGS);
+static int mobj_get_notification(DMOBJECT_ARGS);
+static int mparam_get_notification(DMPARAM_ARGS);
+static int mparam_get_notification_in_param(DMPARAM_ARGS);
+static int mparam_set_notification_in_obj(DMPARAM_ARGS);
+static int mobj_set_notification_in_param(DMOBJECT_ARGS);
+static int mparam_set_notification_in_param(DMPARAM_ARGS);
+static int mobj_set_notification_in_obj(DMOBJECT_ARGS);
+#ifdef BBF_TR064
+static int mparam_upnp_get_instances(DMPARAM_ARGS);
+static int mobj_upnp_get_instances(DMOBJECT_ARGS);
+static int mparam_upnp_structured_get_value_in_param(DMPARAM_ARGS);
+static int mparam_upnp_get_supportedparams(DMPARAM_ARGS);
+static int mparam_upnp_set_attributes(DMPARAM_ARGS);
+static int mobj_upnp_set_attributes(DMOBJECT_ARGS);
+static int mobj_upnp_get_supportedparams(DMOBJECT_ARGS);
+static int mparam_upnp_get_attributes(DMPARAM_ARGS);
+static int mobj_upnp_get_attributes(DMOBJECT_ARGS);
+static int upnp_get_value_obj(DMOBJECT_ARGS);
+static int upnp_get_value_param(DMPARAM_ARGS);
+static int mobj_upnp_get_value_in_param(DMOBJECT_ARGS);
+static int mparam_upnp_get_value_in_param(DMPARAM_ARGS);
+static int mobj_upnp_set_value(DMOBJECT_ARGS);
+static int mparam_upnp_set_value(DMPARAM_ARGS);
+static int upnp_delete_instance_param(DMPARAM_ARGS);
+static int upnp_delete_instance_obj(DMOBJECT_ARGS);
+static int mparam_upnp_add_instance(DMPARAM_ARGS);
+static int mobj_upnp_add_instance(DMOBJECT_ARGS);
+static int mparam_upnp_get_acldata(DMPARAM_ARGS);
+static int mobj_upnp_get_acldata(DMOBJECT_ARGS);
+static int mparam_upnp_get_instance_numbers(DMPARAM_ARGS);
+static int mobj_upnp_get_instance_numbers(DMOBJECT_ARGS);
+static int enabled_tracked_param_check_obj(DMOBJECT_ARGS);
+static int enabled_tracked_param_check_param(DMPARAM_ARGS);
+#endif
+static int enabled_notify_check_obj(DMOBJECT_ARGS);
+static int enabled_notify_check_param(DMPARAM_ARGS);
+static int enabled_notify_check_value_change_param(DMPARAM_ARGS);
+static int enabled_notify_check_value_change_obj(DMOBJECT_ARGS);
+static int get_linker_check_obj(DMOBJECT_ARGS);
+static int get_linker_check_param(DMPARAM_ARGS);
+static int get_linker_value_check_obj(DMOBJECT_ARGS);
+static int get_linker_value_check_param(DMPARAM_ARGS);
+
+
+LIST_HEAD(list_enabled_notify);
+LIST_HEAD(list_enabled_lw_notify);
+#ifdef BBF_TR064
+LIST_HEAD(list_upnp_enabled_onevent);
+LIST_HEAD(list_upnp_enabled_onalarm);
+LIST_HEAD(list_upnp_enabled_version);
+LIST_HEAD(list_upnp_changed_onevent);
+LIST_HEAD(list_upnp_changed_onalarm);
+LIST_HEAD(list_upnp_changed_version);
+#endif
+
+LIST_HEAD(list_execute_end_session);
+int end_session_flag = 0;
+int ip_version = 4;
+char dm_delim = DMDELIM_CWMP;
+char dmroot[64] = "Device";
+int bbfdatamodel_type = BBFDM_BOTH;
+unsigned int upnp_in_user_mask = DM_SUPERADMIN_MASK;
+
+
+struct notification notifications[] = {
+ [0] = {"0", "disabled"},
+ [1] = {"1", "passive"},
+ [2] = {"2", "active"},
+ [3] = {"3", "passive_lw"},
+ [4] = {"4", "passive_passive_lw"},
+ [5] = {"5", "active_lw"},
+ [6] = {"6", "passive_active_lw"}
+};
+
+struct dm_acl dm_acl[] = {
+ [0] = {DM_PUBLIC_LIST, "public_list"},
+ [1] = {DM_PUBLIC_READ, "public_read"},
+ [2] = {DM_PUBLIC_WRITE, "public_write"},
+ [3] = {DM_BASIC_LIST, "basic_list"},
+ [4] = {DM_BASIC_READ, "basic_read"},
+ [5] = {DM_BASIC_WRITE, "basic_write"},
+ [6] = {DM_XXXADMIN_LIST, "xxxadmin_list"},
+ [7] = {DM_XXXADMIN_READ, "xxxadmin_read"},
+ [8] = {DM_XXXADMIN_WRITE, "xxxadmin_write"},
+};
+
+char *DMT_TYPE[] = {
+[DMT_STRING] = "xsd:string",
+[DMT_UNINT] = "xsd:unsignedInt",
+[DMT_INT] = "xsd:int",
+[DMT_LONG] = "xsd:long",
+[DMT_BOOL] = "xsd:boolean",
+[DMT_TIME] = "xsd:dateTime",
+[DMT_HEXBIN] = "xsd:hexbin",
+};
+
+#ifdef BBF_TR064
+unsigned int UPNP_DMT_TYPE[] = {
+[DMT_STRING] = NODE_DATA_ATTRIBUTE_TYPESTRING,
+[DMT_UNINT] = NODE_DATA_ATTRIBUTE_TYPEINT,
+[DMT_INT] = NODE_DATA_ATTRIBUTE_TYPEINT,
+[DMT_LONG] = NODE_DATA_ATTRIBUTE_TYPELONG,
+[DMT_BOOL] = NODE_DATA_ATTRIBUTE_TYPEBOOL,
+[DMT_TIME] = NODE_DATA_ATTRIBUTE_TYPEDATETIME,
+[DMT_HEXBIN] = NODE_DATA_ATTRIBUTE_TYPEBIN,
+};
+#endif
+
+struct dm_permession_s DMREAD = {"0", NULL};
+struct dm_permession_s DMWRITE = {"1", NULL};
+struct dm_forced_inform_s DMFINFRM = {1, NULL};
+struct dm_notif_s DMNONE = { "0", NULL };
+struct dm_notif_s DMPASSIVE = { "1", NULL };
+struct dm_notif_s DMACTIVE = { "2", NULL };
+
+int plugin_obj_match(DMOBJECT_ARGS)
+{
+ if (node->matched)
+ return 0;
+ if (!dmctx->inparam_isparam && strstr(node->current_object, dmctx->in_param) == node->current_object) {
+ node->matched++;
+ dmctx->findparam = 1;
+ return 0;
+ }
+ if (strstr(dmctx->in_param, node->current_object) == dmctx->in_param) {
+ return 0;
+ }
+ return FAULT_9005;
+}
+
+int plugin_leaf_match(DMOBJECT_ARGS)
+{
+ char *str;
+ if (node->matched)
+ return 0;
+ if (!dmctx->inparam_isparam)
+ return FAULT_9005;
+ str = dmctx->in_param + strlen(node->current_object);
+ if (!strchr(str, dm_delim))
+ return 0;
+ return FAULT_9005;
+}
+
+int plugin_obj_forcedinform_match(DMOBJECT_ARGS)
+{
+ unsigned char fi;
+ if (forced_inform) {
+ if (forced_inform->get_forced_inform)
+ fi = forced_inform->get_forced_inform(node->current_object, dmctx, data, instance);
+ else
+ fi = forced_inform->val;
+ if (fi)
+ return 0;
+ }
+ return FAULT_9005;
+}
+
+int plugin_leaf_onlyobj_match(DMOBJECT_ARGS)
+{
+ return FAULT_9005;
+}
+
+int plugin_obj_nextlevel_match(DMOBJECT_ARGS)
+{
+ if (node->matched > 1)
+ return FAULT_9005;
+ if (node->matched) {
+ node->matched++;
+ return 0;
+ }
+ if (!dmctx->inparam_isparam && strstr(node->current_object, dmctx->in_param) == node->current_object) {
+ node->matched++;
+ dmctx->findparam = 1;
+ return 0;
+ }
+ if (strstr(dmctx->in_param, node->current_object) == dmctx->in_param) {
+ return 0;
+ }
+ return FAULT_9005;
+}
+
+int plugin_leaf_nextlevel_match(DMOBJECT_ARGS)
+{
+ char *str;
+ if (node->matched > 1)
+ return FAULT_9005;
+ if (node->matched)
+ return 0;
+ if (!dmctx->inparam_isparam)
+ return FAULT_9005;
+ str = dmctx->in_param + strlen(node->current_object);
+ if (!strchr(str, dm_delim))
+ return 0;
+ return FAULT_9005;
+}
+
+int dm_browse_leaf(struct dmctx *dmctx, DMNODE *parent_node, DMLEAF *leaf, void *data, char *instance)
+{
+ int err = 0;
+ if (!leaf)
+ return 0;
+
+ for (; leaf->parameter; leaf++) {
+ if (leaf->bbfdm_type != bbfdatamodel_type && leaf->bbfdm_type != BBFDM_BOTH)
+ continue;
+ err = dmctx->method_param(dmctx, parent_node, leaf->parameter, leaf->permission, leaf->type, leaf->getvalue, leaf->setvalue, leaf->forced_inform, leaf->notification, data, instance);
+ if (dmctx->stop)
+ return err;
+ }
+ return err;
+}
+
+int dm_browse(struct dmctx *dmctx, DMNODE *parent_node, DMOBJ *entryobj, void *data, char *instance)
+{
+ int err = 0;
+ if (!entryobj)
+ return 0;
+ char *parent_obj = parent_node->current_object;
+ for (; entryobj->obj; entryobj++) {
+ DMNODE node = {0};
+ node.obj = entryobj;
+ node.parent = parent_node;
+ node.instance_level = parent_node->instance_level;
+ node.matched = parent_node->matched;
+ dmasprintf(&(node.current_object), "%s%s%c", parent_obj, entryobj->obj, dm_delim);
+ if (entryobj->bbfdm_type != bbfdatamodel_type && entryobj->bbfdm_type != BBFDM_BOTH)
+ continue;
+ if (dmctx->checkobj) {
+ err = dmctx->checkobj(dmctx, &node, entryobj->permission, entryobj->addobj, entryobj->delobj, entryobj->forced_inform, entryobj->notification, entryobj->get_linker, data, instance);
+ if (err)
+ continue;
+ }
+ err = dmctx->method_obj(dmctx, &node, entryobj->permission, entryobj->addobj, entryobj->delobj, entryobj->forced_inform, entryobj->notification, entryobj->get_linker, data, instance);
+ if (dmctx->stop)
+ return err;
+ if (entryobj->checkobj && ((entryobj->checkobj)(dmctx, data) == false) ){
+ continue;
+ }
+ if (entryobj->browseinstobj) {
+ if (dmctx->instance_wildchar) {
+ dm_link_inst_obj(dmctx, &node, data, dmctx->instance_wildchar);
+ continue;
+ }
+ else {
+ entryobj->browseinstobj(dmctx, &node, data, instance);
+ err = dmctx->faultcode;
+ if (dmctx->stop)
+ return err;
+ continue;
+ }
+ }
+ if (entryobj->leaf) {
+ if (dmctx->checkleaf) {
+ err = dmctx->checkleaf(dmctx, &node, entryobj->permission, entryobj->addobj, entryobj->delobj, entryobj->forced_inform, entryobj->notification, entryobj->get_linker, data, instance);
+ if (!err) {
+ err = dm_browse_leaf(dmctx, &node, entryobj->leaf, data, instance);
+ if (dmctx->stop)
+ return err;
+ }
+ } else {
+ err = dm_browse_leaf(dmctx, &node, entryobj->leaf, data, instance);
+ if (dmctx->stop)
+ return err;
+ }
+ }
+ if (entryobj->nextobj) {
+ err = dm_browse(dmctx, &node, entryobj->nextobj, data, instance);
+ if (dmctx->stop)
+ return err;
+ }
+ }
+ return err;
+}
+
+int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char *instance)
+{
+ int err = 0;
+ char *parent_obj;
+ DMOBJ *prevobj = parent_node->obj;
+ DMOBJ *nextobj = prevobj->nextobj;
+ DMLEAF *nextleaf = prevobj->leaf;
+
+ DMNODE node = {0};
+ node.obj = prevobj;
+ node.parent = parent_node;
+ node.instance_level = parent_node->instance_level + 1;
+ node.is_instanceobj = 1;
+ node.matched = parent_node->matched;
+
+ parent_obj = parent_node->current_object;
+ if (instance == NULL)
+ return -1;
+ dmasprintf(&node.current_object, "%s%s%c", parent_obj, instance, dm_delim);
+ if (dmctx->checkobj) {
+ err = dmctx->checkobj(dmctx, &node, prevobj->permission, prevobj->addobj, prevobj->delobj, prevobj->forced_inform, prevobj->notification, prevobj->get_linker, data, instance);
+ if (err)
+ return err;
+ }
+ err = dmctx->method_obj(dmctx, &node, prevobj->permission, prevobj->addobj, prevobj->delobj, prevobj->forced_inform, prevobj->notification, prevobj->get_linker, data, instance);
+ if (dmctx->stop)
+ return err;
+ if (nextleaf) {
+ if (dmctx->checkleaf) {
+ err = dmctx->checkleaf(dmctx, &node, prevobj->permission, prevobj->addobj, prevobj->delobj, prevobj->forced_inform, prevobj->notification, prevobj->get_linker, data, instance);
+ if (!err) {
+ err = dm_browse_leaf(dmctx, &node, nextleaf, data, instance);
+ if (dmctx->stop)
+ return err;
+ }
+ } else {
+ err = dm_browse_leaf(dmctx, &node, nextleaf, data, instance);
+ if (dmctx->stop)
+ return err;
+ }
+ }
+ if (nextobj) {
+ err = dm_browse(dmctx, &node, nextobj, data, instance);
+ if (dmctx->stop)
+ return err;
+ }
+ return err;
+}
+
+int rootcmp(char *inparam, char *rootobj)
+{
+ int cmp = -1;
+ char buf[32];
+ sprintf(buf, "%s%c", rootobj, dm_delim);
+ cmp = strcmp(inparam, buf);
+ return cmp;
+}
+
+//END//
+/***************************
+ * update instance & alias
+ ***************************/
+char *handle_update_instance(int instance_ranck, struct dmctx *ctx, char **last_inst, char * (*up_instance)(int action, char **last_inst, void *argv[]), int argc, ...)
+{
+ va_list arg;
+ char *instance, *inst_mode;
+ char *alias;
+ int i = 0;
+ unsigned int pos = instance_ranck - 1;
+ unsigned int alias_resister = 0, max, action;
+ void *argv[argc];
+ char *str;
+
+ va_start(arg, argc);
+ for (i = 0; i < argc; i++) {
+ argv[i] = va_arg(arg, void*);
+ }
+ va_end(arg);
+ if (ctx->amd_version >= AMD_4) {
+ if(pos < ctx->nbrof_instance) {
+ action = (ctx->alias_register & (1 << pos)) ? INSTANCE_UPDATE_ALIAS : INSTANCE_UPDATE_NUMBER;
+ } else {
+ action = (ctx->instance_mode == INSTANCE_MODE_ALIAS) ? INSTANCE_UPDATE_ALIAS : INSTANCE_UPDATE_NUMBER;
+ }
+ } else {
+ action = INSTANCE_UPDATE_NUMBER;
+ }
+
+ instance = up_instance(action, last_inst, argv);
+ if(*last_inst)
+ ctx->inst_buf[pos] = dmstrdup(*last_inst);
+
+ return instance;
+}
+char *update_instance(struct uci_section *s, char *last_inst, char *inst_opt)
+{
+ char *instance;
+ void *argv[3];
+
+ argv[0] = s;
+ argv[1] = inst_opt;
+ argv[2] = "";
+
+ instance = update_instance_alias_icwmpd(0, &last_inst, argv);
+ return instance;
+}
+
+char *update_instance_icwmpd(struct uci_section *s, char *last_inst, char *inst_opt)
+{
+ char *instance;
+ void *argv[3];
+
+ argv[0]= s;
+ argv[1]= inst_opt;
+ argv[2]= "";
+ instance = update_instance_alias_icwmpd(0, &last_inst, argv);
+ return instance;
+}
+
+char *update_instance_alias_icwmpd(int action, char **last_inst , void *argv[])
+{
+ char *instance;
+ char *alias;
+ char buf[64] = {0};
+ struct uci_section *s = (struct uci_section *) argv[0];
+ char *inst_opt = (char *) argv[1];
+ char *alias_opt = (char *) argv[2];
+ dmuci_get_value_by_section_string(s, inst_opt, &instance);
+ if (instance[0] == '\0') {
+ if (*last_inst == NULL)
+ sprintf(buf, "%d", 1);
+ else
+ sprintf(buf, "%d", atoi(*last_inst)+1);
+ instance = DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, inst_opt, buf);
+ }
+ *last_inst = instance;
+ if (action == INSTANCE_MODE_ALIAS) {
+ dmuci_get_value_by_section_string(s, alias_opt, &alias);
+ if (alias[0] == '\0') {
+ sprintf(buf, "cpe-%s", instance);
+ alias = DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, alias_opt, buf);
+ }
+ sprintf(buf, "[%s]", alias);
+ instance = dmstrdup(buf);
+ }
+ return instance;
+}
+
+char *update_instance_alias(int action, char **last_inst, void *argv[])
+{
+ char *instance;
+ char *alias;
+ char buf[64] = {0};
+
+ struct uci_section *s = (struct uci_section *) argv[0];
+ char *inst_opt = (char *) argv[1];
+ char *alias_opt = (char *) argv[2];
+
+ dmuci_get_value_by_section_string(s, inst_opt, &instance);
+ if (instance[0] == '\0') {
+ if (*last_inst == NULL)
+ sprintf(buf, "%d", 1);
+ else
+ sprintf(buf, "%d", atoi(*last_inst) + 1);
+ instance = dmuci_set_value_by_section(s, inst_opt, buf);
+ }
+ *last_inst = instance;
+ if (action == INSTANCE_MODE_ALIAS) {
+ dmuci_get_value_by_section_string(s, alias_opt, &alias);
+ if (alias[0] == '\0') {
+ sprintf(buf, "cpe-%s", instance);
+ alias = dmuci_set_value_by_section(s, alias_opt, buf);
+ }
+ sprintf(buf, "[%s]", alias);
+ instance = dmstrdup(buf);
+ }
+ return instance;
+}
+
+char *update_instance_without_section(int action, char **last_inst, void *argv[])
+{
+ char *instance;
+ char *alias;
+ char buf[64] = {0};
+
+ int instnbr = (int) argv[0];
+
+ if (action == INSTANCE_MODE_ALIAS) {
+ sprintf(buf, "[cpe-%d]", instnbr);
+ instance = dmstrdup(buf);
+ } else {
+ sprintf(buf, "%d", instnbr);
+ instance = dmstrdup(buf);
+ }
+ return instance;
+}
+
+char *get_vlan_last_instance_icwmpd(char *package, char *section, char *opt_inst, char *vlan_method)
+{
+ struct uci_section *s, *confsect;
+ char *inst = NULL, *last_inst = NULL, *type, *sect_name;
+
+ uci_path_foreach_sections(icwmpd, package, section, s) {
+ dmuci_get_value_by_section_string(s, "section_name", §_name);
+ get_config_section_of_dmmap_section("network", "device", sect_name, &confsect);
+ dmuci_get_value_by_section_string(confsect, "type", &type);
+ if ((strcmp(vlan_method, "2") != 0 && strcmp(vlan_method, "1") != 0) || (strcmp(vlan_method, "1") == 0 && strcmp(type, "untagged") == 0) )
+ continue;
+ inst = update_instance_icwmpd(s, last_inst, opt_inst);
+ if(last_inst)
+ dmfree(last_inst);
+ last_inst = dmstrdup(inst);
+ }
+ return inst;
+}
+
+char *get_last_instance_icwmpd(char *package, char *section, char *opt_inst)
+{
+ struct uci_section *s;
+ char *inst = NULL;
+ char *last_inst = NULL;
+
+ uci_path_foreach_sections(icwmpd, package, section, s) {
+ inst = update_instance_icwmpd(s, last_inst, opt_inst);
+ if(last_inst)
+ dmfree(last_inst);
+ last_inst = dmstrdup(inst);
+ }
+ return inst;
+}
+
+char *get_last_instance_icwmpd_without_update(char *package, char *section, char *opt_inst)
+{
+ struct uci_section *s;
+ char *inst = NULL;
+ char *last_inst = NULL;
+
+ uci_path_foreach_sections(icwmpd, package, section, s) {
+ dmuci_get_value_by_section_string(s, opt_inst, &inst);
+ if(last_inst)
+ dmfree(last_inst);
+ last_inst = dmstrdup(inst);
+ }
+ return inst;
+}
+
+char *get_last_instance(char *package, char *section, char *opt_inst)
+{
+ struct uci_section *s;
+ char *inst = NULL;
+ char *last_inst = NULL;
+ if (package == DMMAP)
+ {
+ uci_path_foreach_sections(icwmpd, "dmmap", section, s) {
+ inst = update_instance_icwmpd(s, last_inst, opt_inst);
+ if(last_inst)
+ dmfree(last_inst);
+ last_inst = dmstrdup(inst);
+ }
+ }
+ else
+ {
+ uci_foreach_sections(package, section, s) {
+ inst = update_instance(s, inst, opt_inst);
+ }
+ }
+ return inst;
+}
+
+char *get_last_instance_lev2_icwmpd_dmmap_opt(char* dmmap_package, char *section, char *opt_inst, char *opt_check, char *value_check)
+{
+ struct uci_section *s;
+ char *instance = NULL, *section_name= NULL;
+ char *last_inst = NULL;
+
+ uci_path_foreach_option_eq(icwmpd, dmmap_package, section, opt_check, value_check, s) {
+ dmuci_get_value_by_section_string(s, "section_name", §ion_name);
+ instance = update_instance_icwmpd(s, last_inst, opt_inst);
+ if(last_inst)
+ dmfree(last_inst);
+ last_inst = dmstrdup(instance);
+ }
+ return instance;
+}
+char *get_last_instance_lev2_icwmpd(char *package, char *section, char* dmmap_package, char *opt_inst, char *opt_check, char *value_check)
+{
+ struct uci_section *s, *dmmap_section;
+ char *instance = NULL;
+ char *last_inst = NULL, *v= NULL;
+
+ check_create_dmmap_package(dmmap_package);
+ uci_foreach_option_cont(package, section, opt_check, value_check, s) {
+ get_dmmap_section_of_config_section(dmmap_package, section, section_name(s), &dmmap_section);
+ if(dmmap_section == NULL){
+ dmuci_add_section_icwmpd(dmmap_package, section, &dmmap_section, &v);
+ dmuci_set_value_by_section(dmmap_section, "section_name", section_name(s));
+ }
+ instance = update_instance_icwmpd(dmmap_section, last_inst, opt_inst);
+ if(last_inst)
+ dmfree(last_inst);
+ last_inst = dmstrdup(instance);
+ }
+ return instance;
+}
+
+char *get_last_instance_lev2(char *package, char *section, char *opt_inst, char *opt_check, char *value_check)
+{
+ struct uci_section *s;
+ char *instance = NULL;
+ char *last_inst = NULL;
+
+ if (package == DMMAP)
+ {
+ uci_path_foreach_option_cont(icwmpd, package, section, opt_check, value_check, s) {
+ instance = update_instance_icwmpd(s, last_inst, opt_inst);
+ if(last_inst)
+ dmfree(last_inst);
+ last_inst = dmstrdup(instance);
+ }
+ }
+ else
+ {
+ uci_foreach_option_cont(package, section, opt_check, value_check, s) {
+ instance = update_instance(s, instance, opt_inst);
+ }
+ }
+ return instance;
+}
+
+int get_empty(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "";
+ return 0;
+}
+
+void add_list_paramameter(struct dmctx *ctx, char *param_name, char *param_data, char *param_type, char *param_version, unsigned int flags)
+{
+ struct dm_parameter *dm_parameter;
+ struct list_head *ilist;
+ list_for_each(ilist, &ctx->list_parameter)
+ {
+ dm_parameter = list_entry(ilist, struct dm_parameter, list);
+ int cmp = strcmp(dm_parameter->name, param_name);
+ if (cmp == 0) {
+ return;
+ } else if (cmp > 0) {
+ break;
+ }
+ }
+ dm_parameter = dmcalloc(1, sizeof(struct dm_parameter));
+ _list_add(&dm_parameter->list, ilist->prev, ilist);
+ dm_parameter->name = param_name;
+ dm_parameter->data = param_data ? param_data : ""; //allocate memory in function
+ dm_parameter->type = param_type;
+ dm_parameter->version = param_version;
+ dm_parameter->flags = flags;
+}
+
+void del_list_parameter(struct dm_parameter *dm_parameter)
+{
+ list_del(&dm_parameter->list);
+ dmfree(dm_parameter->name);
+ dmfree(dm_parameter);
+}
+
+void free_all_list_parameter(struct dmctx *ctx)
+{
+ struct dm_parameter *dm_parameter;
+ while (ctx->list_parameter.next != &ctx->list_parameter) {
+ dm_parameter = list_entry(ctx->list_parameter.next, struct dm_parameter, list);
+ del_list_parameter(dm_parameter);
+ }
+}
+
+void add_set_list_tmp(struct dmctx *ctx, char *param, char *value, unsigned int flags)
+{
+ struct set_tmp *set_tmp;
+ set_tmp = dmcalloc(1, sizeof(struct set_tmp));
+ list_add_tail(&set_tmp->list, &ctx->set_list_tmp);
+ set_tmp->name = dmstrdup(param);
+ set_tmp->value = value ? dmstrdup(value) : NULL;
+ set_tmp->flags = flags;
+}
+
+void del_set_list_tmp(struct set_tmp *set_tmp)
+{
+ list_del(&set_tmp->list);
+ dmfree(set_tmp->name);
+ dmfree(set_tmp->value);
+ dmfree(set_tmp);
+}
+
+void free_all_set_list_tmp(struct dmctx *ctx)
+{
+ struct set_tmp *set_tmp;
+ while (ctx->set_list_tmp.next != &ctx->set_list_tmp) {
+ set_tmp = list_entry(ctx->set_list_tmp.next, struct set_tmp, list);
+ del_set_list_tmp(set_tmp);
+ }
+}
+
+void add_list_fault_param(struct dmctx *ctx, char *param, int fault)
+{
+ struct param_fault *param_fault;
+ if (param == NULL) param = "";
+
+ param_fault = dmcalloc(1, sizeof(struct param_fault));
+ list_add_tail(¶m_fault->list, &ctx->list_fault_param);
+ param_fault->name = dmstrdup(param);
+ param_fault->fault = fault;
+}
+
+void del_list_fault_param(struct param_fault *param_fault)
+{
+ list_del(¶m_fault->list);
+ dmfree(param_fault->name);
+ dmfree(param_fault);
+}
+
+void free_all_list_fault_param(struct dmctx *ctx)
+{
+ struct param_fault *param_fault;
+ while (ctx->list_fault_param.next != &ctx->list_fault_param) {
+ param_fault = list_entry(ctx->list_fault_param.next, struct param_fault, list);
+ del_list_fault_param(param_fault);
+ }
+}
+
+void add_list_enabled_lwnotify(struct dmctx *dmctx, char *param, char *notification, char *value)
+{
+ struct dm_enabled_notify *dm_enabled_notify;
+
+ dm_enabled_notify = calloc(1, sizeof(struct dm_enabled_notify)); // Should be calloc and not dmcalloc
+ list_add_tail(&dm_enabled_notify->list, &list_enabled_lw_notify);
+ dm_enabled_notify->name = strdup(param); // Should be strdup and not dmstrdup
+ dm_enabled_notify->value = value ? strdup(value) : strdup(""); // Should be strdup and not dmstrdup
+ dm_enabled_notify->notification = strdup(notification); // Should be strdup and not dmstrdup
+}
+
+void del_list_enabled_notify(struct dm_enabled_notify *dm_enabled_notify)
+{
+ list_del(&dm_enabled_notify->list); // Should be free and not dmfree
+ free(dm_enabled_notify->name);
+ free(dm_enabled_notify->value);
+ free(dm_enabled_notify->notification);
+ free(dm_enabled_notify);
+}
+
+void free_all_list_enabled_lwnotify()
+{
+ struct dm_enabled_notify *dm_enabled_notify;
+ while (list_enabled_lw_notify.next != &list_enabled_lw_notify) {
+ dm_enabled_notify = list_entry(list_enabled_lw_notify.next, struct dm_enabled_notify, list);
+ del_list_enabled_notify(dm_enabled_notify);
+ }
+}
+
+int dm_update_file_enabled_notify(char *param, char *new_value)
+{
+ FILE *fp, *ftmp;
+ char buf[512];
+ char *parameter, *notification, *value, *type, *jval;
+
+ fp = fopen(DM_ENABLED_NOTIFY, "r");
+ if (fp == NULL)
+ return 0;
+
+ ftmp = fopen(DM_ENABLED_NOTIFY_TEMPORARY, "a");
+ if (ftmp == NULL) {
+ fclose(fp);
+ return 0;
+ }
+
+ while (fgets(buf, 512, fp) != NULL) {
+ int len = strlen(buf);
+ if (len)
+ buf[len-1] = '\0';
+ dmjson_parse_init(buf);
+ dmjson_get_var("parameter", &jval);
+ parameter = dmstrdup(jval);
+ dmjson_get_var("value", &jval);
+ value = dmstrdup(jval);
+ dmjson_get_var("notification", &jval);
+ notification = dmstrdup(jval);
+ dmjson_get_var("type", &jval);
+ type = dmstrdup(jval);
+ dmjson_parse_fini();
+ if (strcmp(parameter, param) == 0)
+ dmjson_fprintf(ftmp, 4, DMJSON_ARGS{{"parameter", parameter}, {"notification", notification}, {"value", new_value}, {"type", type}});
+ else
+ dmjson_fprintf(ftmp, 4, DMJSON_ARGS{{"parameter", parameter}, {"notification", notification}, {"value", value}, {"type", type}});
+ }
+ fclose(fp);
+ fclose(ftmp);
+
+ return 0;
+}
+
+void dm_update_enabled_notify(struct dm_enabled_notify *p, char *new_value)
+{
+ free(p->value); // Should be free and not dmfree
+ p->value = strdup(new_value);
+}
+
+void dm_update_enabled_notify_byname(char *name, char *new_value)
+{
+ int iscopy;
+ dm_update_file_enabled_notify(name, new_value);
+ remove(DM_ENABLED_NOTIFY);
+ iscopy = copy_temporary_file_to_original_file(DM_ENABLED_NOTIFY, DM_ENABLED_NOTIFY_TEMPORARY);
+ if(iscopy)
+ remove(DM_ENABLED_NOTIFY_TEMPORARY);
+
+}
+
+int update_param_instance_alias(struct dmctx *ctx, char *param, char **new_param)
+{
+ char *pch, *spch, *p;
+ char buf[512];
+ int i = 0, j = 0;
+ char pat[2] = {0};
+
+ char *dup = dmstrdup(param);
+ *pat = dm_delim;
+ p = buf;
+ for (pch = strtok_r(dup, pat, &spch); pch != NULL; pch = strtok_r(NULL, pat, &spch)) {
+ if (isdigit(pch[0])) {
+ dmstrappendchr(p, dm_delim);
+ dmstrappendstr(p, pch);
+ i++;
+ } else if (pch[0]== '[') {
+ dmstrappendchr(p, dm_delim);
+ dmstrappendstr(p, ctx->inst_buf[i]);
+ i++;
+ } else {
+ if (j > 0) {
+ dmstrappendchr(p, dm_delim);
+ dmstrappendstr(p, pch);
+ }
+ if (j == 0) {
+ dmstrappendstr(p, pch);
+ j++;
+ }
+ }
+ }
+ if (param[strlen(param) - 1] == dm_delim)
+ dmstrappendchr(p, dm_delim);
+ dmstrappendend(p);
+ *new_param = dmstrdup(buf);
+ dmfree(dup);
+ return 0;
+}
+
+static char *get_parameter_notification(struct dmctx *ctx, char *param)
+{
+ int i, maxlen = 0, len;
+ struct uci_list *list_notif;
+ char *pch, *new_param;
+ char *notification = "0";
+ struct uci_element *e;
+
+ update_param_instance_alias(ctx, param, &new_param);
+ for (i = (ARRAY_SIZE(notifications) - 1); i >= 0; i--) {
+ dmuci_get_option_value_list("cwmp", "@notifications[0]", notifications[i].type, &list_notif);
+ if (list_notif) {
+ uci_foreach_element(list_notif, e) {
+ pch = e->name;
+ if (strcmp(pch, new_param) == 0) {
+ notification = notifications[i].value;
+ return notification;
+ }
+ len = strlen(pch);
+ if (pch[len-1] == dm_delim) {
+ if (strstr(new_param, pch)) {
+ if (len > maxlen )
+ {
+ notification = notifications[i].value;
+ maxlen = len;
+ }
+ }
+ }
+ }
+ }
+ }
+ dmfree(new_param);
+ return notification;
+}
+
+static int remove_parameter_notification(char *param)
+{
+ int i;
+ struct uci_list *list_notif;
+ struct uci_element *e, *tmp;
+ char *pch;
+ for (i = (ARRAY_SIZE(notifications) - 1); i >= 0; i--) {
+ if (param[strlen(param)-1] == dm_delim) {
+ dmuci_get_option_value_list("cwmp", "@notifications[0]", notifications[i].type, &list_notif);
+ if (list_notif) {
+ uci_foreach_element_safe(list_notif, e, tmp) {
+ pch = tmp->name;
+ if (strstr(pch, param)) {
+ dmuci_del_list_value("cwmp", "@notifications[0]", notifications[i].type, pch);
+ }
+ }
+ }
+ } else {
+ dmuci_del_list_value("cwmp", "@notifications[0]", notifications[i].type, param);
+ }
+ }
+ return 0;
+}
+
+static int set_parameter_notification(struct dmctx *ctx, char *param, char *value)
+{
+ char *tmp = NULL, *buf = NULL, *pch, *new_param;
+ char *notification = NULL;
+ struct uci_section *s;
+ dmuci_get_section_type("cwmp", "@notifications[0]", &tmp);
+ update_param_instance_alias(ctx, param, &new_param);
+ if (!tmp || tmp[0] == '\0') {
+ dmuci_add_section("cwmp", "notifications", &s, &buf);
+ } else {
+ remove_parameter_notification(new_param);
+ }
+
+ notification = get_parameter_notification(ctx, new_param);
+ if (strcmp(notification, value) == 0) {
+ goto end;
+ }
+ if (strcmp(value, "1") == 0) {
+ dmuci_add_list_value("cwmp", "@notifications[0]", "passive", new_param);
+ } else if (strcmp(value, "2") == 0) {
+ dmuci_add_list_value("cwmp", "@notifications[0]", "active", new_param);
+ } else if (strcmp(value, "3") == 0) {
+ dmuci_add_list_value("cwmp", "@notifications[0]", "passive_lw", new_param);
+ } else if (strcmp(value, "4") == 0) {
+ dmuci_add_list_value("cwmp", "@notifications[0]", "passive_passive_lw", new_param);
+ } else if (strcmp(value, "5") == 0) {
+ dmuci_add_list_value("cwmp", "@notifications[0]", "active_lw", new_param);
+ } else if (strcmp(value, "6") == 0) {
+ dmuci_add_list_value("cwmp", "@notifications[0]", "passive_active_lw", new_param);
+ } else if (strcmp(value, "0") == 0) {
+ struct uci_list *list_notif;
+ struct uci_element *e;
+ int i, len;
+ for (i = (ARRAY_SIZE(notifications) - 1); i >= 1; i--) {
+ dmuci_get_option_value_list("cwmp", "@notifications[0]", notifications[i].type, &list_notif);
+ if (list_notif) {
+ uci_foreach_element(list_notif, e) {
+ pch = e->name;
+ len = strlen(pch);
+ if (pch[len-1] == dm_delim && strstr(new_param, pch)) {
+ dmuci_add_list_value("cwmp", "@notifications[0]", "disabled", new_param);
+ goto end;
+ }
+ }
+ }
+ }
+
+ } else {
+ return -1;
+ }
+end:
+ dmfree(new_param);
+ return 0;
+}
+
+int string_to_bool(char *v, bool *b)
+{
+ if (v[0] == '1' && v[1] == '\0') {
+ *b = true;
+ return 0;
+ }
+ if (v[0] == '0' && v[1] == '\0') {
+ *b = false;
+ return 0;
+ }
+ if (strcasecmp(v, "true") == 0) {
+ *b = true;
+ return 0;
+ }
+ if (strcasecmp(v, "false") == 0) {
+ *b = false;
+ return 0;
+ }
+ *b = false;
+ return -1;
+}
+
+/******************
+ * operate commands
+ *****************/
+int dm_entry_operate(struct dmctx *dmctx)
+{
+ int res;
+
+ res = operate_on_node(dmctx, dmctx->in_param, dmctx->in_value);
+ return res;
+}
+
+/* **********
+ * get value
+ * **********/
+int dm_entry_get_value(struct dmctx *dmctx)
+{
+ int i;
+ int err = 0;
+ unsigned char findparam_check = 0;
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = {.current_object = ""};
+
+ if (dmctx->in_param[0] == '\0' || rootcmp(dmctx->in_param, root->obj) == 0) {
+ dmctx->inparam_isparam = 0;
+ dmctx->method_obj = get_value_obj;
+ dmctx->method_param = get_value_param;
+ dmctx->checkobj = NULL;
+ dmctx->checkleaf = NULL;
+ dmctx->findparam = 1;
+ dmctx->stop = 0;
+ findparam_check = 1;
+ } else if (dmctx->in_param[strlen(dmctx->in_param) - 1] == dm_delim) {
+ dmctx->inparam_isparam = 0;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = get_value_obj;
+ dmctx->method_param = get_value_param;
+ findparam_check = 1;
+ } else {
+ dmctx->inparam_isparam = 1;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_get_value_in_param;
+ dmctx->method_param = mparam_get_value_in_param;
+ }
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (findparam_check && dmctx->findparam)
+ return 0;
+ else
+ return err;
+}
+
+static int get_value_obj(DMOBJECT_ARGS)
+{
+ return 0;
+}
+
+static int get_value_param(DMPARAM_ARGS)
+{
+ char *full_param;
+ char *value = "";
+
+ dmastrcat(&full_param, node->current_object, lastname);
+ (get_cmd)(full_param, dmctx, data, instance, &value);
+ add_list_paramameter(dmctx, full_param, value, DMT_TYPE[type], NULL, 0);
+ return 0;
+}
+
+static int mobj_get_value_in_param(DMOBJECT_ARGS)
+{
+ return 0;
+}
+static int mparam_get_value_in_param(DMPARAM_ARGS)
+{
+ char *full_param;
+ char *value = "";
+
+ dmastrcat(&full_param, node->current_object, lastname);
+ if (strcmp(dmctx->in_param, full_param) != 0) {
+ dmfree(full_param);
+ return FAULT_9005;
+ }
+
+ (get_cmd)(full_param, dmctx, data, instance, &value);
+ add_list_paramameter(dmctx, full_param, value, DMT_TYPE[type], NULL, 0);
+ dmctx->stop = true;
+ return 0;
+}
+
+/* **********
+ * get name
+ * **********/
+
+int dm_entry_get_name(struct dmctx *ctx)
+{
+ DMOBJ *root = ctx->dm_entryobj;
+ DMNODE node = {.current_object = ""};
+ unsigned char findparam_check = 0;
+ int err;
+ if (ctx->nextlevel == 0 && (ctx->in_param[0] == '\0' || rootcmp(ctx->in_param, root->obj) == 0)) {
+ ctx->inparam_isparam = 0;
+ ctx->findparam = 1;
+ ctx->stop = 0;
+ ctx->checkobj = NULL;
+ ctx->checkleaf = NULL;
+ ctx->method_obj = mobj_get_name;
+ ctx->method_param = mparam_get_name;
+ } else if (ctx->nextlevel && (ctx->in_param[0] == '\0')) {
+ ctx->inparam_isparam = 0;
+ ctx->findparam = 1;
+ ctx->stop = 0;
+ ctx->checkobj = plugin_obj_nextlevel_match;
+ ctx->checkleaf = plugin_leaf_nextlevel_match;
+ ctx->method_obj = mobj_get_name;
+ ctx->method_param = mparam_get_name;
+ ctx->in_param = root->obj;
+ node.matched = 1;
+ findparam_check = 1;
+ } else if (*(ctx->in_param + strlen(ctx->in_param) - 1) == dm_delim) {
+ ctx->inparam_isparam = 0;
+ ctx->findparam = 0;
+ ctx->stop = 0;
+ ctx->method_obj = mobj_get_name_in_obj;
+ ctx->method_param = mparam_get_name_in_obj;
+ ctx->checkobj = (ctx->nextlevel) ? plugin_obj_nextlevel_match : plugin_obj_match;
+ ctx->checkleaf = (ctx->nextlevel) ? plugin_leaf_nextlevel_match : plugin_leaf_match;
+ findparam_check = 1;
+ } else {
+ ctx->inparam_isparam = 1;
+ ctx->findparam = 0;
+ ctx->stop = 0;
+ ctx->checkobj = plugin_obj_match;
+ ctx->checkleaf = plugin_leaf_match;
+ ctx->method_obj = mobj_get_name_in_param;
+ ctx->method_param = mparam_get_name_in_param;
+ }
+ err = dm_browse(ctx, &node, root, NULL, NULL);
+ if (findparam_check && ctx->findparam)
+ return 0;
+ else
+ return err;
+}
+
+static int mparam_get_name(DMPARAM_ARGS)
+{
+ char *refparam;
+ char *perm = permission->val;
+ dmastrcat(&refparam, node->current_object, lastname);
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ add_list_paramameter(dmctx, refparam, perm, NULL, NULL, 0);
+ return 0;
+}
+
+static int mobj_get_name(DMOBJECT_ARGS)
+{
+ char *refparam;
+ char *perm = permission->val;
+ refparam = node->current_object;
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ add_list_paramameter(dmctx, refparam, perm, NULL, NULL, 0);
+ return 0;
+}
+
+static int mparam_get_name_in_param(DMPARAM_ARGS)
+{
+ char *refparam;
+ char *perm = permission->val;
+ dmastrcat(&refparam, node->current_object, lastname);
+ if (strcmp(refparam, dmctx->in_param) != 0) {
+ dmfree(refparam);
+ return FAULT_9005;
+ }
+ dmctx->stop = 1;
+ if (dmctx->nextlevel == 1) {
+ dmfree(refparam);
+ return FAULT_9003;
+ }
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ add_list_paramameter(dmctx, refparam, perm, NULL, NULL, 0);
+ return 0;
+}
+
+static int mobj_get_name_in_param(DMOBJECT_ARGS)
+{
+ return 0;
+}
+
+static int mparam_get_name_in_obj(DMPARAM_ARGS)
+{
+ char *refparam;
+ char *perm = permission->val;
+
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ dmastrcat(&refparam, node->current_object, lastname);
+ add_list_paramameter(dmctx, refparam, perm, NULL, NULL, 0);
+ return 0;
+}
+
+static int mobj_get_name_in_obj(DMOBJECT_ARGS)
+{
+ char *refparam;
+ char *perm = permission->val;
+
+ if (!node->matched) {
+ return FAULT_9005;
+ }
+
+ if (dmctx->nextlevel && strcmp(node->current_object, dmctx->in_param) == 0)
+ return 0;
+
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ refparam = node->current_object;
+ add_list_paramameter(dmctx, refparam, perm, NULL, NULL, 0);
+ return 0;
+}
+
+/* ********************
+ * get notification
+ * ********************/
+int dm_entry_get_notification(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ unsigned char findparam_check = 0;
+ int err;
+
+ if (dmctx->in_param[0] == '\0'
+ || rootcmp(dmctx->in_param, root->obj) == 0) {
+ dmctx->inparam_isparam = 0;
+ dmctx->findparam = 1;
+ dmctx->stop = 0;
+ dmctx->checkobj = NULL;
+ dmctx->checkleaf = NULL;
+ dmctx->method_obj = mobj_get_notification;
+ dmctx->method_param = mparam_get_notification;
+ findparam_check = 1;
+ } else if (*(dmctx->in_param + strlen(dmctx->in_param) - 1) == dm_delim) {
+ dmctx->inparam_isparam = 0;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_get_notification;
+ dmctx->method_param = mparam_get_notification;
+ findparam_check = 1;
+ } else {
+ dmctx->inparam_isparam = 1;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_get_notification_in_param;
+ dmctx->method_param = mparam_get_notification_in_param;
+ }
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (findparam_check && dmctx->findparam)
+ return 0;
+ else
+ return err;
+}
+
+static int mparam_get_notification(DMPARAM_ARGS)
+{
+ char *value;
+ char *refparam;
+
+ dmastrcat(&refparam, node->current_object, lastname);
+
+ if (notification == NULL) {
+ value = get_parameter_notification(dmctx, refparam);
+ } else {
+ value = notification->val;
+ if (notification->get_notif)
+ value = notification->get_notif(refparam, dmctx, data, instance);
+ }
+ add_list_paramameter(dmctx, refparam, value, NULL, NULL, 0);
+ return 0;
+}
+
+static int mobj_get_notification(DMOBJECT_ARGS)
+{
+ return 0;
+}
+
+static int mparam_get_notification_in_param(DMPARAM_ARGS)
+{
+ char *value = NULL;
+ char *refparam;
+
+ dmastrcat(&refparam, node->current_object, lastname);
+ if (strcmp(refparam, dmctx->in_param) != 0) {
+ dmfree(refparam);
+ return FAULT_9005;
+ }
+ if (notification == NULL) {
+ value = get_parameter_notification(dmctx, refparam);
+ } else {
+ value = notification->val;
+ if (notification->get_notif)
+ value = notification->get_notif(refparam, dmctx, data, instance);
+ }
+ add_list_paramameter(dmctx, refparam, value, NULL, NULL, 0);
+ dmctx->stop = 1;
+ return 0;
+}
+
+static int mobj_get_notification_in_param(DMOBJECT_ARGS)
+{
+ return 0;
+}
+
+/***************
+ * inform
+ ***************/
+int dm_entry_inform(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = {.current_object = ""};
+ int err;
+
+ dmctx->inparam_isparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_forcedinform_match;
+ dmctx->checkleaf = NULL;
+ dmctx->method_obj = &inform_check_obj;
+ dmctx->method_param = &inform_check_param;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->stop)
+ return err;
+ else
+ return FAULT_9005;
+}
+
+static int inform_check_obj(DMOBJECT_ARGS)
+{
+ return 0;
+}
+
+static int inform_check_param(DMPARAM_ARGS)
+{
+ char *value = "";
+ char *full_param;
+ unsigned char fi;
+
+ if (!forced_inform)
+ return FAULT_9005;
+
+ if (forced_inform->get_forced_inform)
+ fi = forced_inform->get_forced_inform(node->current_object, dmctx, data,
+ instance);
+ else
+ fi = forced_inform->val;
+
+ if (!fi)
+ return FAULT_9005;
+
+ dmastrcat(&full_param, node->current_object, lastname);
+ (get_cmd)(full_param, dmctx, data, instance, &value);
+ add_list_paramameter(dmctx, full_param, value, DMT_TYPE[type], NULL, 0);
+ return 0;
+}
+
+/* **************
+ * add object
+ * **************/
+int dm_entry_add_object(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ int err;
+
+ if (dmctx->in_param == NULL || dmctx->in_param[0] == '\0'
+ || (*(dmctx->in_param + strlen(dmctx->in_param) - 1) != dm_delim))
+ return FAULT_9005;
+
+ dmctx->inparam_isparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_onlyobj_match;
+ dmctx->method_obj = mobj_add_object;
+ dmctx->method_param = mparam_add_object;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->stop)
+ return err;
+ else
+ return FAULT_9005;
+}
+
+static int mparam_add_object(DMPARAM_ARGS)
+{
+ return FAULT_9005;
+}
+
+static int mobj_add_object(DMOBJECT_ARGS)
+{
+ char *addinst;
+ char newparam[256];
+ char *refparam = node->current_object;
+ char *perm = permission->val;
+ char *objinst;
+
+ if (strcmp(refparam, dmctx->in_param) != 0)
+ return FAULT_9005;
+
+ dmctx->stop = 1;
+ if (node->is_instanceobj)
+ return FAULT_9005;
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ if (perm[0] == '0' || addobj == NULL)
+ return FAULT_9005;
+
+ int fault = (addobj)(refparam, dmctx, data, &instance);
+ if (fault)
+ return fault;
+ dmctx->addobj_instance = instance;
+ dmasprintf(&objinst, "%s%s%c", node->current_object, instance, dm_delim);
+ set_parameter_notification(dmctx, objinst, "0");
+ dmfree(objinst);
+ return 0;
+}
+/* **************
+ * del object
+ * **************/
+int dm_entry_delete_object(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ int err;
+
+ if (dmctx->in_param == NULL || dmctx->in_param[0] == '\0'
+ || (*(dmctx->in_param + strlen(dmctx->in_param) - 1) != dm_delim))
+ return FAULT_9005;
+
+ dmctx->inparam_isparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_onlyobj_match;
+ dmctx->method_obj = delete_object_obj;
+ dmctx->method_param = delete_object_param;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->stop)
+ return err;
+ else
+ return FAULT_9005;
+}
+
+static int delete_object_obj(DMOBJECT_ARGS)
+{
+ char *refparam = node->current_object;
+ char *perm = permission->val;
+ unsigned char del_action = DEL_INST;
+ if (strcmp(refparam, dmctx->in_param) != 0)
+ return FAULT_9005;
+
+ dmctx->stop = 1;
+
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ if (perm[0] == '0' || delobj == NULL)
+ return FAULT_9005;
+
+ if (!node->is_instanceobj)
+ del_action = DEL_ALL;
+ int fault = (delobj)(refparam, dmctx, data, instance, del_action);
+ return fault;
+}
+
+static int delete_object_param(DMPARAM_ARGS)
+{
+ return FAULT_9005;
+}
+
+/* **************
+ * set value
+ * **************/
+int dm_entry_set_value(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ int err;
+
+ if (dmctx->in_param == NULL || dmctx->in_param[0] == '\0'
+ || (*(dmctx->in_param + strlen(dmctx->in_param) - 1) == dm_delim))
+ return FAULT_9005;
+
+ dmctx->inparam_isparam = 1;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_set_value;
+ dmctx->method_param = mparam_set_value;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->stop)
+ return err;
+ else
+ return FAULT_9005;
+}
+
+static int mobj_set_value(DMOBJECT_ARGS)
+{
+ return FAULT_9005;
+}
+
+static int mparam_set_value(DMPARAM_ARGS)
+{
+ int err;
+ char *refparam;
+ char *perm;
+ char *v = "";
+
+ dmastrcat(&refparam, node->current_object, lastname);
+ if (strcmp(refparam, dmctx->in_param) != 0) {
+ dmfree(refparam);
+ return FAULT_9005;
+ }
+ dmctx->stop = 1;
+
+ if (dmctx->setaction == VALUECHECK) {
+ perm = permission->val;
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ if (perm[0] == '0' || !set_cmd) {
+ dmfree(refparam);
+ return FAULT_9008;
+ }
+ int fault = (set_cmd)(refparam, dmctx, data, instance, dmctx->in_value, VALUECHECK);
+ if (fault) {
+ dmfree(refparam);
+ return fault;
+ }
+ add_set_list_tmp(dmctx, dmctx->in_param, dmctx->in_value, 0);
+ }
+ else if (dmctx->setaction == VALUESET) {
+ (set_cmd)(refparam, dmctx, data, instance, dmctx->in_value, VALUESET);
+ //(get_cmd)(refparam, dmctx, data, instance, &v);
+ dm_update_enabled_notify_byname(refparam, dmctx->in_value);
+ }
+ dmfree(refparam);
+ return 0;
+}
+
+/* ****************
+ * set notification
+ * ****************/
+int dm_entry_set_notification(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ unsigned char findparam_check = 0;
+ int err;
+
+ if (dmcommon_check_notification_value(dmctx->in_notification) < 0)
+ return FAULT_9003;
+
+ if (dmctx->in_param[0] == '\0' || rootcmp(dmctx->in_param, root->obj) == 0) {
+ return FAULT_9009;
+ } else if (*(dmctx->in_param + strlen(dmctx->in_param) - 1) == dm_delim) {
+ dmctx->inparam_isparam = 0;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_set_notification_in_obj;
+ dmctx->method_param = mparam_set_notification_in_obj;
+ } else {
+ dmctx->inparam_isparam = 1;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_set_notification_in_param;
+ dmctx->method_param = mparam_set_notification_in_param;
+ }
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->stop)
+ return err;
+ else
+ return FAULT_9005;
+}
+
+/* SET Notification*/
+
+static int mparam_set_notification_in_obj(DMPARAM_ARGS)
+{
+ return FAULT_9005;
+}
+
+static int mobj_set_notification_in_obj(DMOBJECT_ARGS)
+{
+ int err;
+ char *refparam;
+ char *perm;
+ char tparam[256];
+
+ refparam = node->current_object;
+ if (strcmp(refparam, dmctx->in_param) != 0) {
+ return FAULT_9005;
+ }
+ dmctx->stop = 1;
+ if (!dmctx->notification_change) {
+ return 0;
+ }
+ if (dmctx->setaction == VALUECHECK) {
+ if (notification)
+ return FAULT_9009;
+
+ add_set_list_tmp(dmctx, dmctx->in_param, dmctx->in_notification, 0);
+ }
+ else if (dmctx->setaction == VALUESET) {
+ set_parameter_notification(dmctx, dmctx->in_param, dmctx->in_notification);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ }
+ return 0;
+}
+
+static int mparam_set_notification_in_param(DMPARAM_ARGS)
+{
+ int err;
+ char *refparam;
+ char tparam[256];
+
+ dmastrcat(&refparam, node->current_object, lastname);
+ if (strcmp(refparam, dmctx->in_param) != 0) {
+ dmfree(refparam);
+ return FAULT_9005;
+ }
+
+ dmctx->stop = 1;
+ if (!dmctx->notification_change) {
+ return 0;
+ }
+ if (dmctx->setaction == VALUECHECK) {
+ if (notification) {
+ dmfree(refparam);
+ return FAULT_9009;
+ }
+ add_set_list_tmp(dmctx, dmctx->in_param, dmctx->in_notification, 0);
+ } else if (dmctx->setaction == VALUESET) {
+ set_parameter_notification(dmctx, dmctx->in_param, dmctx->in_notification);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ }
+ dmfree(refparam);
+ return 0;
+}
+
+static int mobj_set_notification_in_param(DMOBJECT_ARGS)
+{
+ return FAULT_9005;
+}
+
+/*********************
+ * load enabled notify
+ ********************/
+int dm_entry_enabled_notify(struct dmctx *dmctx)
+{
+ int err;
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+
+ dmctx->method_obj = enabled_notify_check_obj;
+ dmctx->method_param = enabled_notify_check_param;
+ dmctx->checkobj = NULL ;
+ dmctx->checkleaf = NULL;
+ remove(DM_ENABLED_NOTIFY);
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ return err;
+
+}
+
+static int enabled_notify_check_obj(DMOBJECT_ARGS)
+{
+ return FAULT_9005;
+}
+
+static int enabled_notify_check_param(DMPARAM_ARGS)
+{
+ char *refparam, *stype, *notif, *value = "";
+ FILE *fp;
+
+ dmastrcat(&refparam, node->current_object, lastname);
+
+ if (notification == NULL) {
+ notif = get_parameter_notification(dmctx, refparam);
+ } else {
+ notif = notification->val;
+ if (notification->get_notif)
+ notif = notification->get_notif(refparam, dmctx, data, instance);
+ }
+ if (notif[0] == '0') {
+ dmfree(refparam);
+ return 0;
+ }
+ (get_cmd)(refparam, dmctx, data, instance, &value);
+ fp = fopen(DM_ENABLED_NOTIFY, "a");
+ if (fp == NULL) {
+ dmfree(refparam);
+ return 0;
+ }
+ if (notif[0] == '1' || notif[0] == '2' || notif[0] == '4' || notif[0] == '6') {
+ stype = DMT_TYPE[type];
+ dmjson_fprintf(fp, 4, DMJSON_ARGS{{"parameter", refparam}, {"notification", notif}, {"value", value}, {"type", stype}});
+ }
+ fclose(fp);
+
+ if (notif[0] >= '3') {
+ add_list_enabled_lwnotify(dmctx, refparam, notif, value);
+ }
+ dmfree(refparam);
+ return 0;
+}
+
+/*********************
+ * Check enabled notify value change
+ ********************/
+int dm_entry_enabled_notify_check_value_change(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ FILE *fp;
+ char buf[512];
+ char *jval;
+
+ fp = fopen(DM_ENABLED_NOTIFY, "r");
+ if (fp == NULL) {
+ return 0;
+ }
+
+ while (fgets(buf, 512, fp) != NULL) {
+ DMNODE node = {.current_object = ""};
+ int len = strlen(buf);
+ if (len)
+ buf[len-1] = '\0';
+ dmjson_parse_init(buf);
+ dmjson_get_var("parameter", &jval);
+ dmctx->in_param = dmstrdup(jval);
+ dmjson_get_var("value", &jval);
+ dmctx->in_value = dmstrdup(jval);
+ dmjson_get_var("notification", &jval);
+ dmctx->in_notification = dmstrdup(jval);
+ dmjson_parse_fini();
+ dmctx->checkobj = NULL ;
+ dmctx->checkleaf = NULL;
+ dmctx->method_obj = enabled_notify_check_value_change_obj;
+ dmctx->method_param = enabled_notify_check_value_change_param;
+ dm_browse(dmctx, &node, root, NULL, NULL);
+ }
+ fclose(fp);
+ return 0;
+}
+
+static int enabled_notify_check_value_change_obj(DMOBJECT_ARGS)
+{
+ return FAULT_9005;
+}
+
+static int enabled_notify_check_value_change_param(DMPARAM_ARGS)
+{
+ char *refparam, *value = "";
+
+ dmastrcat(&refparam, node->current_object, lastname);
+ if (strcmp(refparam, dmctx->in_param) != 0) {
+ dmfree(refparam);
+ return FAULT_9005;
+ }
+ (get_cmd)(refparam, dmctx, data, instance, &value);
+ if (strcmp(value, dmctx->in_value) != 0) {
+ add_list_value_change(refparam, value, DMT_TYPE[type]);
+ if(dmctx->in_notification[0] =='2')
+ send_active_value_change();
+ }
+ dmfree(refparam);
+ return 0;
+}
+
+/******************
+ * get linker param
+ *****************/
+int dm_entry_get_linker(struct dmctx *dmctx)
+{
+ int err;
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+
+ dmctx->method_obj = get_linker_check_obj;
+ dmctx->method_param = get_linker_check_param;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_onlyobj_match;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->stop)
+ return err;
+ else
+ return FAULT_9005;
+}
+
+static int get_linker_check_obj(DMOBJECT_ARGS)
+{
+ char *link_val = "";
+
+ if (!get_linker) {
+ return FAULT_9005;
+ }
+ if (node->obj->browseinstobj && !node->is_instanceobj) {
+ return FAULT_9005;
+ }
+ get_linker(node->current_object, dmctx, data, instance, &link_val);
+ if (dmctx->linker[0] == '\0') {
+ return FAULT_9005;
+ }
+ if (link_val && link_val[0] != '\0' && strcmp(link_val, dmctx->linker) == 0) {
+ dmctx->linker_param = dmstrdup(node->current_object);
+ dmctx->stop = true;
+ return 0;
+ }
+ return FAULT_9005;
+}
+
+static int get_linker_check_param(DMPARAM_ARGS)
+{
+ return FAULT_9005;
+}
+
+/******************
+ * get linker value
+ *****************/
+int dm_entry_get_linker_value(struct dmctx *dmctx)
+{
+ int err ;
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+
+ dmctx->method_obj = get_linker_value_check_obj;
+ dmctx->method_param = get_linker_value_check_param;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmentry_instance_lookup_inparam(dmctx);
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->stop)
+ return err;
+ else
+ return FAULT_9005;
+}
+
+static int get_linker_value_check_obj(DMOBJECT_ARGS)
+{
+ char *link_val;
+ if (!get_linker)
+ return FAULT_9005;
+
+ if (strcmp(node->current_object, dmctx->in_param) == 0) {
+ get_linker(node->current_object, dmctx, data, instance, &link_val);
+ dmctx->linker = dmstrdup(link_val);
+ dmctx->stop = true;
+ return 0;
+ }
+ return FAULT_9005;
+}
+
+static int get_linker_value_check_param(DMPARAM_ARGS)
+{
+ return FAULT_9005;
+}
+
+#ifdef BBF_TR064
+/* ******************
+ * UPNP entries
+ * ******************/
+
+int upnp_map_cwmp_fault(int cwmp_fault)
+{
+ switch (cwmp_fault) {
+ case FAULT_9005:
+ return FAULT_UPNP_703;
+ case FAULT_9003:
+ return FAULT_UPNP_701;
+ case FAULT_9007:
+ return FAULT_UPNP_705;
+ case FAULT_9008:
+ return FAULT_UPNP_706;
+ }
+ if (cwmp_fault > __FAULT_UPNP_MAX)
+ return FAULT_UPNP_701;
+ return cwmp_fault;
+}
+
+int plugin_upnp_structured_obj_match(DMOBJECT_ARGS)
+{
+ if (node->matched)
+ return 0;
+ if (!dmctx->inparam_isparam && strstructered(node->current_object, dmctx->in_param) == STRUCTERED_SAME) {
+ node->matched++;
+ dmctx->findparam = 1;
+ return 0;
+ }
+ if (strstructered(dmctx->in_param, node->current_object) == STRUCTERED_PART) {
+ return 0;
+ }
+ return FAULT_UPNP_703;
+}
+
+int plugin_upnp_leaf_match(DMOBJECT_ARGS)
+{
+ char *str;
+ if (node->matched)
+ return 0;
+ if (!dmctx->inparam_isparam)
+ return FAULT_UPNP_703;
+ str = dmctx->in_param + strlen(node->current_object);
+ if (!strchr(str, dm_delim))
+ return 0;
+ return FAULT_UPNP_703;
+}
+
+static int plugin_upnp_obj_depth_match(DMOBJECT_ARGS)
+{
+ if (node->matched) {
+ node->matched++;
+ }
+ else if (strcmp(node->current_object, dmctx->in_param) == 0) {
+ node->matched++;
+ dmctx->findparam = 1;
+ }
+ else if (strstr(dmctx->in_param, node->current_object) == dmctx->in_param) {
+ return 0;
+ }
+ if (dmctx->depth == 0 || dmctx->depth >= (node->matched - 1))
+ return 0;
+ return FAULT_UPNP_703;
+}
+
+int plugin_upnp_leaf_depth_match(DMOBJECT_ARGS)
+{
+ char *str;
+ if (!node->matched) {
+ if (!dmctx->inparam_isparam) {
+ return FAULT_UPNP_703;
+ }
+ else {
+ str = dmctx->in_param + strlen(node->current_object);
+ if (strchr(str, dm_delim))
+ return FAULT_UPNP_703;
+ }
+ }
+ if (dmctx->depth == 0)
+ return 0;
+ if (dmctx->depth >= node->matched)
+ return 0;
+ return FAULT_UPNP_703;
+}
+
+static int plugin_upnp_skip_leafs(DMOBJECT_ARGS)
+{
+ return FAULT_UPNP_703;
+}
+
+static int upnp_get_parameter_onchange(struct dmctx *ctx, char *param, char *onchange)
+{
+ struct uci_list *list_onchange;
+ char *pch;
+ struct uci_element *e;
+ dmuci_get_option_value_list(UPNP_CFG, "@notifications[0]", onchange, &list_onchange);
+ if (list_onchange) {
+ uci_foreach_element(list_onchange, e) {
+ pch = e->name;
+ if (strcmp(pch, param) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int upnp_set_parameter_onchange(struct dmctx *ctx, char *param, char *onchange, unsigned int value)
+{
+ char *tmp;
+ struct uci_section *s;
+
+ dmuci_get_section_type(UPNP_CFG, "@notifications[0]", &tmp);
+ if (!tmp || tmp[0] == '\0') {
+ dmuci_add_section(UPNP_CFG, "notifications", &s, &tmp);
+ }
+
+ dmuci_del_list_value(UPNP_CFG, "@notifications[0]",onchange, param);
+ if (value) {
+ dmuci_add_list_value(UPNP_CFG, "@notifications[0]", onchange, param);
+ }
+ return 0;
+}
+
+void add_list_upnp_param_track(struct dmctx *dmctx, struct list_head *pchead, char *param, char *key, char *value, unsigned int isobj)
+{
+ struct dm_upnp_enabled_track *dm_upnp_enabled_track;
+
+ dm_upnp_enabled_track = calloc(1, sizeof(struct dm_upnp_enabled_track)); // Should be calloc and not dmcalloc
+ list_add_tail(&dm_upnp_enabled_track->list, pchead);
+ dm_upnp_enabled_track->name = strdup(param); // Should be strdup and not dmstrdup
+ dm_upnp_enabled_track->value = value ? strdup(value) : strdup(""); // Should be strdup and not dmstrdup
+ dm_upnp_enabled_track->key = key ? strdup(key) : NULL; // Should be strdup and not dmstrdup
+ dm_upnp_enabled_track->isobj = isobj;
+}
+
+void del_list_upnp_param_track(struct dm_upnp_enabled_track *dm_upnp_enabled_track)
+{
+ list_del(&dm_upnp_enabled_track->list); // Should be free and not dmfree
+ free(dm_upnp_enabled_track->name);
+ free(dm_upnp_enabled_track->value);
+ free(dm_upnp_enabled_track->key);
+ free(dm_upnp_enabled_track);
+}
+
+void free_all_list_upnp_param_track(struct list_head *pchead)
+{
+ struct dm_upnp_enabled_track *dm_upnp_enabled_track;
+ while (pchead->next != pchead) {
+ dm_upnp_enabled_track = list_entry(pchead->next, struct dm_upnp_enabled_track, list);
+ del_list_upnp_param_track(dm_upnp_enabled_track);
+ }
+}
+
+int get_parameter_version(struct dmctx *ctx, char *param, char **version, struct uci_section **rs)
+{
+ int found = 0;
+ struct uci_list *list_struc;
+ struct uci_section *s = NULL;
+ char *pch;
+ unsigned int acl = 0, f;
+ struct uci_element *e;
+
+ *version = NULL;
+ *rs = NULL;
+
+ uci_foreach_option_eq(UPNP_CFG, "parameter_version", "parameter", param, s) {
+ break;
+ }
+ if (s != NULL) {
+ *rs = s;
+ dmuci_get_value_by_section_string(s, "version", version);
+ if (**version == '\0')
+ *version = "0";
+ return 1;
+ }
+ else {
+ dmuci_get_option_value_list(UPNP_CFG, "@parameter_version_structured[0]", "paramater", &list_struc);
+ if (list_struc) {
+ uci_foreach_element(list_struc, e) {
+ pch = e->name;
+ if (strstructered(pch, param) == STRUCTERED_SAME) {
+ *version = "0";
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+unsigned int get_parameter_acl(struct dmctx *ctx, char *param)
+{
+ int i, maxlen = 0, len;
+ struct uci_list *list_acl;
+ char *pch;
+ unsigned int acl = 0, f;
+ struct uci_element *e;
+
+ for (i = (ARRAY_SIZE(dm_acl) - 1); i >= 0; i--) {
+ dmuci_get_option_value_list(UPNP_CFG, "@acl_factorized[0]", dm_acl[i].user_access, &list_acl);
+ if (list_acl) {
+ f = 0;
+ maxlen = 0;
+ uci_foreach_element(list_acl, e) {
+ pch = e->name;
+ if (strstructered(pch, param) == STRUCTERED_SAME) {
+ f = dm_acl[i].flag;
+ break;
+ }
+ len = strlen(pch);
+ if (pch[len-1] == dm_delim) {
+ if (strstructered(param, pch) == STRUCTERED_PART) {
+ if (len > maxlen )
+ {
+ f = dm_acl[i].flag;
+ maxlen = len;
+ }
+ }
+ }
+ }
+ acl |= f;
+ }
+ }
+ return acl;
+}
+
+unsigned int dm_upnp_check_acl_list(struct dmctx *dmctx, char *param)
+{
+ unsigned int flag;
+ unsigned int mask = DM_LIST_MASK | DM_READ_MASK | DM_WRITE_MASK;
+ flag = get_parameter_acl(dmctx, param);
+ if (flag & mask & dmctx->user_mask)
+ return flag;
+ return 0;
+}
+
+unsigned int dm_upnp_check_acl_read(struct dmctx *dmctx, char *param)
+{
+ unsigned int flag;
+ unsigned int mask = DM_READ_MASK | DM_WRITE_MASK;
+ flag = get_parameter_acl(dmctx, param);
+ if (flag & mask & dmctx->user_mask)
+ return flag;
+ return 0;
+}
+
+unsigned int dm_upnp_check_acl_write(struct dmctx *dmctx, char *param)
+{
+ unsigned int flag;
+ unsigned int mask = DM_WRITE_MASK;
+ flag = get_parameter_acl(dmctx, param);
+ if (flag & mask & dmctx->user_mask)
+ return flag;
+ return 0;
+}
+
+int dm_entry_upnp_update_attribute_values_update(struct dmctx *dmctx)
+{
+ char *v, *tmp, buf[32];
+ struct uci_section *s;
+ int version;
+ time_t time_value;
+
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "attribute_values_version", &v);
+ version = atoi(v);
+ version++;
+
+ dmuci_get_section_type(UPNP_CFG, "@dm[0]", &tmp);
+ if (!tmp || tmp[0] == '\0') {
+ dmuci_add_section(UPNP_CFG, "dm", &s, &tmp);
+ }
+ sprintf(buf, "%d", version);
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "attribute_values_version", buf);
+ sprintf(buf, "%ld", time(NULL));
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "attribute_values_epochtime", buf);
+
+ return 0;
+}
+
+/* ******************
+ * UPNP get instances
+ * ******************/
+
+int dm_entry_upnp_get_instances(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = {.current_object = ""};
+ int err;
+ char buf[4] = {0};
+ buf[0] = dm_delim;
+
+ if (*(dmctx->in_param) == '\0')
+ dmctx->in_param = buf;
+
+ if (*(dmctx->in_param + strlen(dmctx->in_param) - 1) != dm_delim)
+ return FAULT_UPNP_701;
+
+ dmctx->inparam_isparam = 0;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_upnp_obj_depth_match;
+ dmctx->checkleaf = plugin_upnp_skip_leafs;
+ dmctx->method_obj = mobj_upnp_get_instances;
+ dmctx->method_param = mparam_upnp_get_instances;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->findparam)
+ return 0;
+ else
+ return (upnp_map_cwmp_fault(err));
+}
+
+static int mparam_upnp_get_instances(DMPARAM_ARGS)
+{
+ return 0;
+}
+
+static int mobj_upnp_get_instances(DMOBJECT_ARGS)
+{
+ char *refparam;
+ refparam = node->current_object;
+ if (!node->is_instanceobj || !node->matched)
+ return FAULT_UPNP_703;
+ if (!dm_upnp_check_acl_read(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+ add_list_paramameter(dmctx, refparam, NULL, NULL, NULL, 0);
+ return 0;
+}
+
+/* *****************************
+ * UPNP get supported parameters
+ * *****************************/
+
+int dm_entry_upnp_get_supported_parameters(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = {.current_object = ""};
+ int err;
+
+ char buf[4] = {0};
+ buf[0] = dm_delim;
+
+ if (*(dmctx->in_param) == '\0')
+ dmctx->in_param = buf;
+
+ if (*(dmctx->in_param + strlen(dmctx->in_param) - 1) != dm_delim)
+ dmctx->inparam_isparam = 1;
+ else
+ dmctx->inparam_isparam = 0;
+ dmctx->instance_wildchar = "#";
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_upnp_obj_depth_match;
+ dmctx->checkleaf = plugin_upnp_leaf_depth_match;
+ dmctx->method_obj = mobj_upnp_get_supportedparams;
+ dmctx->method_param = mparam_upnp_get_supportedparams;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->findparam)
+ return 0;
+ else
+ return (upnp_map_cwmp_fault(err));
+}
+
+static int mparam_upnp_get_supportedparams(DMPARAM_ARGS)
+{
+ char *refparam;
+ dmastrcat(&refparam, node->current_object, lastname);
+ if (dmctx->inparam_isparam) {
+ if (strcmp(refparam, dmctx->in_param) == 0) {
+ if (!dm_upnp_check_acl_list(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+ dmctx->findparam = 1;
+ add_list_paramameter(dmctx, refparam, NULL, NULL, NULL, 0);
+ return 0;
+ }
+ }
+ else {
+ if (!dm_upnp_check_acl_list(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+ add_list_paramameter(dmctx, refparam, NULL, NULL, NULL, 0);
+ return 0;
+ }
+ return FAULT_UPNP_703;
+}
+
+static int mobj_upnp_get_supportedparams(DMOBJECT_ARGS)
+{
+ char *refparam;
+ if (node->matched <= 1)
+ return FAULT_UPNP_703;
+ if (dmctx->depth == (node->matched - 1)) {
+ if (node->obj->browseinstobj && !node->is_instanceobj)
+ dmastrcat(&refparam, node->current_object, "#/");
+ else
+ refparam = node->current_object;
+ if (!dm_upnp_check_acl_list(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+ add_list_paramameter(dmctx, refparam, NULL, NULL, NULL, 0);
+ return 0;
+ }
+ return FAULT_UPNP_703;
+}
+
+/* ************************
+ * UPNP get selected values
+ * ************************/
+
+int dm_entry_upnp_get_selected_values(struct dmctx *dmctx)
+{
+ int i;
+ int err = 0;
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = {.current_object = ""};
+
+ if (dmctx->in_param[0] == '\0' || rootcmp(dmctx->in_param, root->obj) == 0) {
+ dmctx->inparam_isparam = 0;
+ dmctx->method_obj = get_value_obj;
+ dmctx->method_param = get_value_param;
+ dmctx->checkobj = NULL;
+ dmctx->checkleaf = NULL;
+ dmctx->findparam = 1;
+ dmctx->stop = 0;
+ } else if (dmctx->in_param[strlen(dmctx->in_param) - 1] == dm_delim) {
+ dmctx->inparam_isparam = 0;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_upnp_structured_obj_match;
+ dmctx->checkleaf = plugin_upnp_leaf_match;
+ dmctx->method_obj = get_value_obj;
+ dmctx->method_param = get_value_param;
+ } else {
+ dmctx->inparam_isparam = 1;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_upnp_structured_obj_match;
+ dmctx->checkleaf = plugin_upnp_leaf_match;
+ dmctx->method_obj = mobj_get_value_in_param;
+ dmctx->method_param = mparam_upnp_structured_get_value_in_param;
+ }
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->findparam)
+ return 0;
+ else
+ return (upnp_map_cwmp_fault(err));
+}
+
+static int mparam_upnp_structured_get_value_in_param(DMPARAM_ARGS)
+{
+ char *full_param;
+ char *value = "";
+
+ dmastrcat(&full_param, node->current_object, lastname);
+ if (strstructered(dmctx->in_param, full_param) == STRUCTERED_NULL) {
+ dmfree(full_param);
+ return FAULT_UPNP_703;
+ }
+ if (!dm_upnp_check_acl_read(dmctx, full_param)) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+ dmctx->findparam = 1;
+ (get_cmd)(full_param, dmctx, data, instance, &value);
+ add_list_paramameter(dmctx, full_param, value, DMT_TYPE[type], NULL, 0);
+ return 0;
+}
+
+/* ***************
+ * UPNP get values
+ * ***************/
+
+int dm_entry_upnp_get_values(struct dmctx *dmctx)
+{
+ int i;
+ int err = 0;
+ unsigned char findparam_check = 0;
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = {.current_object = ""};
+
+ if (dmctx->in_param[0] == '\0' || rootcmp(dmctx->in_param, root->obj) == 0) {
+ dmctx->inparam_isparam = 0;
+ dmctx->method_obj = upnp_get_value_obj;
+ dmctx->method_param = upnp_get_value_param;
+ dmctx->checkobj = NULL;
+ dmctx->checkleaf = NULL;
+ dmctx->findparam = 1;
+ dmctx->stop = 0;
+ findparam_check = 1;
+ } else if (dmctx->in_param[strlen(dmctx->in_param) - 1] == dm_delim) {
+ dmctx->inparam_isparam = 0;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = upnp_get_value_obj;
+ dmctx->method_param = upnp_get_value_param;
+ findparam_check = 1;
+ } else {
+ dmctx->inparam_isparam = 1;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_upnp_get_value_in_param;
+ dmctx->method_param = mparam_upnp_get_value_in_param;
+ }
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (findparam_check && dmctx->findparam)
+ return 0;
+ else
+ return (upnp_map_cwmp_fault(err));
+}
+
+static int upnp_get_value_obj(DMOBJECT_ARGS)
+{
+ return 0;
+}
+
+static int upnp_get_value_param(DMPARAM_ARGS)
+{
+ char *full_param;
+ char *value = "";
+
+ dmastrcat(&full_param, node->current_object, lastname);
+ if (!dm_upnp_check_acl_read(dmctx, full_param)) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+ (get_cmd)(full_param, dmctx, data, instance, &value);
+ add_list_paramameter(dmctx, full_param, value, NULL, NULL, 0);
+ return 0;
+}
+
+static int mobj_upnp_get_value_in_param(DMOBJECT_ARGS)
+{
+ return 0;
+}
+static int mparam_upnp_get_value_in_param(DMPARAM_ARGS)
+{
+ char *full_param;
+ char *value = "";
+
+ dmastrcat(&full_param, node->current_object, lastname);
+ if (strcmp(dmctx->in_param, full_param) != 0) {
+ dmfree(full_param);
+ return FAULT_UPNP_703;
+ }
+
+ if (!dm_upnp_check_acl_read(dmctx, full_param)) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+ (get_cmd)(full_param, dmctx, data, instance, &value);
+ add_list_paramameter(dmctx, full_param, value, NULL, NULL, 0);
+ dmctx->stop = 1;
+ return 0;
+}
+
+/* ***************
+ * UPNP set values
+ * ***************/
+
+int dm_entry_upnp_set_values(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ int err;
+
+ if (dmctx->in_param == NULL || dmctx->in_param[0] == '\0'
+ || (*(dmctx->in_param + strlen(dmctx->in_param) - 1) == dm_delim))
+ return FAULT_UPNP_703;
+
+ dmctx->inparam_isparam = 1;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_upnp_set_value;
+ dmctx->method_param = mparam_upnp_set_value;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->stop)
+ return (upnp_map_cwmp_fault(err));
+ else
+ return FAULT_UPNP_703;
+}
+
+static int mobj_upnp_set_value(DMOBJECT_ARGS)
+{
+ return FAULT_UPNP_703;
+}
+
+static int mparam_upnp_set_value(DMPARAM_ARGS)
+{
+ int err;
+ char *refparam;
+ char *perm;
+ char *v = "";
+
+ dmastrcat(&refparam, node->current_object, lastname);
+ if (strcmp(refparam, dmctx->in_param) != 0) {
+ dmfree(refparam);
+ return FAULT_UPNP_703;
+ }
+ dmctx->stop = 1;
+
+ if (dmctx->setaction == VALUECHECK) {
+ perm = permission->val;
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ if (perm[0] == '0' || !set_cmd) {
+ dmfree(refparam);
+ return FAULT_UPNP_706;
+ }
+ if (!dm_upnp_check_acl_write(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ return FAULT_UPNP_706;
+ }
+ int fault = (set_cmd)(refparam, dmctx, data, instance, dmctx->in_value, VALUECHECK);
+ if (fault) {
+ dmfree(refparam);
+ return fault;
+ }
+ add_set_list_tmp(dmctx, dmctx->in_param, dmctx->in_value, 0);
+ }
+ else if (dmctx->setaction == VALUESET) {
+ (set_cmd)(refparam, dmctx, data, instance, dmctx->in_value, VALUESET);
+ (get_cmd)(refparam, dmctx, data, instance, &v);
+ dm_update_enabled_notify_byname(refparam, v);
+ }
+ dmfree(refparam);
+ return 0;
+}
+
+/* ********************
+ * UPNP delete instance
+ * *******************/
+
+int dm_entry_upnp_delete_instance(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ int err;
+
+ if (dmctx->in_param == NULL || dmctx->in_param[0] == '\0'
+ || (*(dmctx->in_param + strlen(dmctx->in_param) - 1) != dm_delim))
+ return FAULT_UPNP_703;
+
+ dmctx->inparam_isparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_onlyobj_match;
+ dmctx->method_obj = upnp_delete_instance_obj;
+ dmctx->method_param = upnp_delete_instance_param;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->stop)
+ return (upnp_map_cwmp_fault(err));
+ else
+ return FAULT_UPNP_703;
+}
+
+static int upnp_delete_instance_obj(DMOBJECT_ARGS)
+{
+ char *refparam = node->current_object;
+ char *perm = permission->val;
+ unsigned char del_action = DEL_INST;
+ if (strcmp(refparam, dmctx->in_param) != 0)
+ return FAULT_UPNP_703;
+
+ dmctx->stop = 1;
+
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ if (perm[0] == '0' || delobj == NULL)
+ return FAULT_UPNP_706;
+
+ if (!dm_upnp_check_acl_write(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ return FAULT_UPNP_706;
+ }
+
+ if (!node->is_instanceobj)
+ del_action = DEL_ALL;
+ int fault = (delobj)(refparam, dmctx, data, instance, del_action);
+ return fault;
+}
+
+static int upnp_delete_instance_param(DMPARAM_ARGS)
+{
+ return FAULT_UPNP_703;
+}
+
+/* ********************
+ * UPNP add instance
+ * *******************/
+
+int dm_entry_upnp_add_instance(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ int err;
+
+ if (dmctx->in_param == NULL || dmctx->in_param[0] == '\0'
+ || (*(dmctx->in_param + strlen(dmctx->in_param) - 1) != dm_delim))
+ return FAULT_UPNP_703;
+
+ dmctx->inparam_isparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_onlyobj_match;
+ dmctx->method_obj = mobj_upnp_add_instance;
+ dmctx->method_param = mparam_upnp_add_instance;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->stop)
+ return (upnp_map_cwmp_fault(err));
+ else
+ return FAULT_UPNP_703;
+}
+
+static int mparam_upnp_add_instance(DMPARAM_ARGS)
+{
+ return FAULT_UPNP_703;
+}
+
+static int mobj_upnp_add_instance(DMOBJECT_ARGS)
+{
+ char *addinst;
+ char newparam[256];
+ char *refparam = node->current_object;
+ char *perm = permission->val;
+ char *objinst;
+
+ if (strcmp(refparam, dmctx->in_param) != 0)
+ return FAULT_UPNP_703;
+
+ dmctx->stop = 1;
+ if (node->is_instanceobj)
+ return FAULT_UPNP_703;
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ if (perm[0] == '0' || addobj == NULL)
+ return FAULT_UPNP_706;
+
+ if (!dm_upnp_check_acl_write(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ return FAULT_UPNP_706;
+ }
+
+ int fault = (addobj)(refparam, dmctx, data, &instance);
+ if (fault)
+ return fault;
+ dmctx->addobj_instance = instance;
+ dmasprintf(&objinst, "%s%s%c", node->current_object, instance, dm_delim);
+ set_parameter_notification(dmctx, objinst, "0");
+ dmfree(objinst);
+ return 0;
+}
+
+/* ********************
+ * UPNP get attributes
+ * ********************/
+int dm_entry_upnp_get_attributes(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ unsigned char findparam_check = 0;
+ int err;
+ char buf[4] = {0};
+ buf[0] = dm_delim;
+
+ if (*(dmctx->in_param) == '\0')
+ dmctx->in_param = buf;
+
+ if (*(dmctx->in_param + strlen(dmctx->in_param) - 1) != dm_delim)
+ dmctx->inparam_isparam = 1;
+ else
+ dmctx->inparam_isparam = 0;
+
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_upnp_get_attributes;
+ dmctx->method_param = mparam_upnp_get_attributes;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->findparam)
+ return 0;
+ else
+ return (upnp_map_cwmp_fault(err));
+}
+
+static int mparam_upnp_get_attributes(DMPARAM_ARGS)
+{
+ char *refparam;
+ unsigned int flags = 0;
+ char *perm = permission->val;
+ char *version = NULL;
+ struct uci_section *s = NULL;
+
+ dmastrcat(&refparam, node->current_object, lastname);
+
+ if (strcmp(refparam, dmctx->in_param) != 0)
+ return FAULT_UPNP_703;
+
+ if (!dm_upnp_check_acl_read(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+
+ dmctx->stop = 1;
+
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ perm = (*perm == '1') ? "readWrite" : "readOnly";
+
+ if (upnp_get_parameter_onchange(dmctx, refparam, "alarmchange"))
+ flags |= DM_PARAM_ALARAM_ON_CHANGE;
+ if (upnp_get_parameter_onchange(dmctx, refparam, "eventchange"))
+ flags |= DM_PARAM_EVENT_ON_CHANGE;
+ get_parameter_version(dmctx, refparam, &version, &s);
+ flags |= UPNP_DMT_TYPE[type];
+
+ add_list_paramameter(dmctx, refparam, perm, NULL, version, flags);
+ return 0;
+}
+
+static int mobj_upnp_get_attributes(DMOBJECT_ARGS)
+{
+ char *refparam;
+ unsigned int flags = 0;
+ char *perm = permission->val;
+ char *version = NULL;
+ char *type;
+ struct uci_section *s = NULL;
+
+ refparam = node->current_object;
+
+ if (strcmp(refparam, dmctx->in_param) != 0)
+ return FAULT_UPNP_703;
+
+ if (!dm_upnp_check_acl_read(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+
+ dmctx->stop = 1;
+
+ if (permission->get_permission != NULL)
+ perm = permission->get_permission(refparam, dmctx, data, instance);
+
+ perm = (*perm == '1') ? "readWrite" : "readOnly";
+
+ if (!node->is_instanceobj && upnp_get_parameter_onchange(dmctx, refparam, "eventchange"))
+ flags |= DM_PARAM_EVENT_ON_CHANGE;
+
+ get_parameter_version(dmctx, refparam, &version, &s);
+
+ if (node->is_instanceobj)
+ flags |= (NODE_DATA_ATTRIBUTE_INSTANCE | NODE_DATA_ATTRIBUTE_TYPEPTR);
+ else if (node->obj->browseinstobj)
+ flags |= (NODE_DATA_ATTRIBUTE_MULTIINSTANCE | NODE_DATA_ATTRIBUTE_TYPEPTR);
+
+ add_list_paramameter(dmctx, refparam, perm, NULL, version, flags);
+
+ return 0;
+}
+
+/* ********************
+ * UPNP set attributes
+ * ********************/
+int dm_entry_upnp_set_attributes(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ unsigned char findparam_check = 0;
+ int err;
+ char buf[4] = {0};
+ buf[0] = dm_delim;
+
+ if (*(dmctx->in_param) == '\0')
+ dmctx->in_param = buf;
+
+ if (*(dmctx->in_param + strlen(dmctx->in_param) - 1) != dm_delim)
+ dmctx->inparam_isparam = 1;
+ else
+ dmctx->inparam_isparam = 0;
+
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_upnp_set_attributes;
+ dmctx->method_param = mparam_upnp_set_attributes;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->findparam)
+ return 0;
+ else
+ return (upnp_map_cwmp_fault(err));
+}
+
+static int mparam_upnp_set_attributes(DMPARAM_ARGS)
+{
+ char *refparam;
+ unsigned int flags = 0;
+ char *perm = permission->val;
+
+ dmastrcat(&refparam, node->current_object, lastname);
+
+ if (strcmp(refparam, dmctx->in_param) != 0)
+ return FAULT_UPNP_703;
+
+ dmctx->stop = 1;
+ if (dmctx->setaction == VALUECHECK) {
+ if (!dm_upnp_check_acl_write(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ return FAULT_UPNP_706;
+ }
+ add_set_list_tmp(dmctx, dmctx->in_param, NULL, dmctx->dmparam_flags);
+ }
+ else {
+ upnp_set_parameter_onchange(dmctx, refparam, "alarmchange", dmctx->dmparam_flags & DM_PARAM_ALARAM_ON_CHANGE);
+ upnp_set_parameter_onchange(dmctx, refparam, "eventchange", dmctx->dmparam_flags & DM_PARAM_EVENT_ON_CHANGE);
+ dm_entry_upnp_update_attribute_values_update(dmctx);
+ }
+ return 0;
+}
+
+static int mobj_upnp_set_attributes(DMOBJECT_ARGS)
+{
+ char *refparam;
+ unsigned int flags = 0;
+ char *perm = permission->val;
+
+ refparam = node->current_object;
+
+ if (strcmp(refparam, dmctx->in_param) != 0)
+ return FAULT_UPNP_703;
+
+ dmctx->stop = 1;
+
+ if (dmctx->setaction == VALUECHECK) {
+ if (!dm_upnp_check_acl_write(dmctx, refparam)) {
+ dmctx->findparam = 0;
+ return FAULT_UPNP_706;
+ }
+ add_set_list_tmp(dmctx, dmctx->in_param, NULL, dmctx->dmparam_flags);
+ }
+ else {
+ if (!node->is_instanceobj) {
+ upnp_set_parameter_onchange(dmctx, refparam, "eventchange", dmctx->dmparam_flags & DM_PARAM_EVENT_ON_CHANGE);
+ dm_entry_upnp_update_attribute_values_update(dmctx);
+ }
+ }
+ return 0;
+}
+
+/* *******************
+ * UPNP get ACL data
+ * ******************/
+
+int dm_entry_upnp_get_acl_data(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+ unsigned char findparam_check = 0;
+ int err;
+ char buf[4] = {0};
+ buf[0] = dm_delim;
+
+ if (*(dmctx->in_param) == '\0')
+ dmctx->in_param = buf;
+
+ if (*(dmctx->in_param + strlen(dmctx->in_param) - 1) != dm_delim)
+ dmctx->inparam_isparam = 1;
+ else
+ dmctx->inparam_isparam = 0;
+
+ if (strchr(dmctx->in_param, '#'))
+ dmctx->instance_wildchar = "#";
+ else
+ dmctx->instance_wildchar = NULL;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_obj_match;
+ dmctx->checkleaf = plugin_leaf_match;
+ dmctx->method_obj = mobj_upnp_get_acldata;
+ dmctx->method_param = mparam_upnp_get_acldata;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->findparam)
+ return 0;
+ else
+ return (upnp_map_cwmp_fault(err));
+}
+
+static int mparam_upnp_get_acldata(DMPARAM_ARGS)
+{
+ char *refparam;
+ unsigned int flags = 0;
+ char *perm = permission->val;
+
+ dmastrcat(&refparam, node->current_object, lastname);
+
+ if (strcmp(refparam, dmctx->in_param) != 0)
+ return FAULT_UPNP_703;
+
+ flags = dm_upnp_check_acl_list(dmctx, refparam);
+ if (!flags) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+
+ dmctx->stop = 1;
+
+ add_list_paramameter(dmctx, refparam, NULL, NULL, NULL, flags);
+ return 0;
+}
+
+static int mobj_upnp_get_acldata(DMOBJECT_ARGS)
+{
+ char *refparam;
+ unsigned int flags = 0;
+ char *perm = permission->val;
+
+ refparam = node->current_object;
+
+ if (strcmp(refparam, dmctx->in_param) != 0)
+ return FAULT_UPNP_703;
+
+ flags = dm_upnp_check_acl_list(dmctx, refparam);
+ if (!flags) {
+ dmctx->findparam = 0;
+ dmctx->stop = 1;
+ return FAULT_UPNP_703;
+ }
+
+ dmctx->stop = 1;
+ flags |= DM_FACTORIZED;
+
+ add_list_paramameter(dmctx, refparam, NULL, NULL, NULL, flags);
+ return 0;
+}
+
+/* **************************
+ * UPNP get instance numbers
+ * *************************/
+
+char *dm_entry_get_all_instance_numbers(struct dmctx *pctx, char *param)
+{
+ static char instbuf[256];
+ struct dmctx dmctx = {0};
+
+ dm_ctx_init_sub(&dmctx, pctx->dm_type, pctx->amd_version, pctx->instance_mode);
+ dmctx.in_param = param;
+ dmctx.depth = 1;
+ dm_entry_upnp_get_instance_numbers(&dmctx);
+ strcpy(instbuf, dmctx.all_instances);
+ dm_ctx_clean_sub(&dmctx);
+ return instbuf;
+}
+
+int dm_entry_upnp_get_instance_numbers(struct dmctx *dmctx)
+{
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = {.current_object = ""};
+ int err;
+ char buf[4] = {0};
+ buf[0] = dm_delim;
+
+ if (*(dmctx->in_param) == '\0')
+ dmctx->in_param = buf;
+
+ if (*(dmctx->in_param + strlen(dmctx->in_param) - 1) != dm_delim)
+ return FAULT_UPNP_701;
+
+ dmctx->inparam_isparam = 0;
+ dmctx->findparam = 0;
+ dmctx->stop = 0;
+ dmctx->checkobj = plugin_upnp_obj_depth_match;
+ dmctx->checkleaf = plugin_upnp_skip_leafs;
+ dmctx->method_obj = mobj_upnp_get_instance_numbers;
+ dmctx->method_param = mparam_upnp_get_instance_numbers;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ if (dmctx->findparam)
+ return 0;
+ else
+ return (upnp_map_cwmp_fault(err));
+}
+
+static int mparam_upnp_get_instance_numbers(DMPARAM_ARGS)
+{
+ return 0;
+}
+
+static int mobj_upnp_get_instance_numbers(DMOBJECT_ARGS)
+{
+ char *refparam;
+ refparam = node->current_object;
+ if (!node->is_instanceobj || !node->matched)
+ return FAULT_UPNP_703;
+ if (*(dmctx->all_instances)) {
+ strcat(dmctx->all_instances, ",");
+ }
+ strcat(dmctx->all_instances, instance);
+ return 0;
+}
+
+/************************************
+ * upnp load tracked parameter values
+ ***********************************/
+int dm_entry_upnp_tracked_parameters(struct dmctx *dmctx)
+{
+ int err;
+ DMOBJ *root = dmctx->dm_entryobj;
+ DMNODE node = { .current_object = "" };
+
+ dmctx->method_obj = enabled_tracked_param_check_obj;
+ dmctx->method_param = enabled_tracked_param_check_param;
+ dmctx->checkobj = NULL ;
+ dmctx->checkleaf = NULL;
+ err = dm_browse(dmctx, &node, root, NULL, NULL);
+ return err;
+}
+
+static int enabled_tracked_param_check_obj(DMOBJECT_ARGS)
+{
+ char *refparam;
+ char *all_instances;
+ char *version = "0";
+ struct uci_section *s;
+ int isevnt, isversion;
+
+ refparam = node->current_object;
+ if (!node->obj->browseinstobj || node->is_instanceobj)
+ return FAULT_UPNP_703;
+
+ isevnt = upnp_get_parameter_onchange(dmctx, refparam, "eventchange");
+ isversion = get_parameter_version(dmctx, refparam, &version, &s);
+ if (isevnt || isversion)
+ all_instances = dm_entry_get_all_instance_numbers(dmctx, refparam);
+
+ if (isevnt) {
+ add_list_upnp_param_track(dmctx, &list_upnp_enabled_onevent, refparam, "1", all_instances, 1);
+ }
+ if (isversion) {
+ add_list_upnp_param_track(dmctx, &list_upnp_enabled_version, refparam, (s ? section_name(s) : NULL), all_instances, 1);
+ }
+ return 0;
+}
+
+static int enabled_tracked_param_check_param(DMPARAM_ARGS)
+{
+ char *refparam;
+ char *value = "";
+ char *version = "0";
+ struct uci_section *s;
+ int isalrm, isevnt, isversion;
+
+ dmastrcat(&refparam, node->current_object, lastname);
+ isalrm = upnp_get_parameter_onchange(dmctx, refparam, "alarmchange");
+ isevnt = upnp_get_parameter_onchange(dmctx, refparam, "eventchange");
+ isversion = get_parameter_version(dmctx, refparam, &version, &s);
+
+ if (isalrm || isevnt || isversion)
+ (get_cmd)(refparam, dmctx, data, instance, &value);
+ if (isalrm) {
+ add_list_upnp_param_track(dmctx, &list_upnp_enabled_onalarm, refparam, "1", value, 0);
+ }
+ if (isevnt) {
+ add_list_upnp_param_track(dmctx, &list_upnp_enabled_onevent, refparam, "1", value, 0);
+ }
+ if (isversion) {
+ add_list_upnp_param_track(dmctx, &list_upnp_enabled_version, refparam, (s ? section_name(s) : NULL), value, 0);
+ }
+
+ dmfree(refparam);
+ return 0;
+}
+#endif
+
+/********************/
+
+int dm_add_end_session(struct dmctx *ctx, void(*function)(struct execute_end_session *), int action, void *data)
+{
+ struct execute_end_session *execute_end_session;
+
+ execute_end_session = calloc (1,sizeof(struct execute_end_session));
+ if (execute_end_session == NULL)
+ {
+ return -1;
+ }
+ execute_end_session->action = action;
+ execute_end_session->data = data;
+ execute_end_session->function = function;
+ execute_end_session->amd_version = ctx->amd_version;
+ execute_end_session->instance_mode = ctx->instance_mode;
+ execute_end_session->dm_type = ctx->dm_type;
+ list_add_tail (&(execute_end_session->list), &(list_execute_end_session));
+
+ return 0;
+}
+
+int cwmp_free_dm_end_session(struct execute_end_session *execute_end_session)
+{
+ if(execute_end_session != NULL)
+ {
+ FREE(execute_end_session);
+ }
+ return 0;
+}
+
+int apply_end_session()
+{
+ struct execute_end_session *p, *q;
+ list_for_each_entry_safe(p, q, &(list_execute_end_session), list) {
+ p->function(p);
+ list_del(&(p->list));
+ cwmp_free_dm_end_session(p);
+ }
+ return 0;
+}
+
+void cwmp_set_end_session (unsigned int flag)
+{
+ end_session_flag |= flag;
+}
+
+char *dm_print_path(char *fpath, ...)
+{
+ static char pathbuf[512] = "";
+ va_list vl;
+
+ va_start(vl, fpath);
+ vsprintf(pathbuf, fpath, vl);
+ va_end(vl);
+ return pathbuf;
+}
diff --git a/dmcwmp.h b/dmcwmp.h
new file mode 100644
index 00000000..f54ea5b4
--- /dev/null
+++ b/dmcwmp.h
@@ -0,0 +1,589 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2015 Inteno Broadband Technology AB
+ * Author MOHAMED Kallel
+ * Author Imen Bhiri
+ * Author Feten Besbes
+ *
+ */
+
+#ifndef __DMCWMP_H__
+#define __DMCWMP_H__
+#include
+#include
+#include
+#include
+#include
+#include "dmuci.h"
+#include "dmmem.h"
+
+#ifdef BBF_TR064
+#define DMROOT_UPNP ""
+#define DMDELIM_UPNP '/'
+#endif
+
+#define DMDELIM_CWMP '.'
+
+#define DM_PROMPT "icwmp>"
+
+#define DM_ENABLED_NOTIFY "/etc/icwmpd/.dm_enabled_notify"
+#define DM_ENABLED_NOTIFY_TEMPORARY "/tmp/.dm_enabled_notify_temporary"
+
+#ifdef BBF_TR064
+#define UPNP_CFG "tr064"
+#endif
+
+#ifdef UNDEF
+#undef UNDEF
+#endif
+#define UNDEF -1
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+#ifndef FREE
+#define FREE(x) do { free(x); x = NULL; } while (0)
+#endif
+
+extern struct dm_permession_s DMREAD;
+extern struct dm_permession_s DMWRITE;
+extern struct dm_forced_inform_s DMFINFRM;
+
+extern struct dm_notif_s DMNONE;
+extern struct dm_notif_s DMACTIVE;
+extern struct dm_notif_s DMPASSIVE;
+
+#define DMPARAM_ARGS \
+ struct dmctx *dmctx, \
+ struct dmnode *node, \
+ char *lastname, \
+ struct dm_permession_s *permission, \
+ int type, \
+ int (*get_cmd)(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value), \
+ int (*set_cmd)(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action), \
+ struct dm_forced_inform_s *forced_inform, \
+ struct dm_notif_s *notification, \
+ void *data, \
+ char *instance
+
+#define DMOBJECT_ARGS \
+ struct dmctx *dmctx, \
+ struct dmnode *node, \
+ struct dm_permession_s *permission, \
+ int (*addobj)(char *refparam, struct dmctx *ctx, void *data, char **instance), \
+ int (*delobj)(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action), \
+ struct dm_forced_inform_s *forced_inform, \
+ struct dm_notif_s *notification, \
+ int (*get_linker)(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker), \
+ void *data, \
+ char *instance
+
+#define TAILLE_MAX 1024
+
+struct dm_forced_inform_s;
+struct dm_permession_s;
+struct dm_parameter;
+struct dm_leaf_s;
+struct dm_obj_s;
+struct dmnode;
+struct dmctx;
+struct dm_notif_s;
+
+struct dm_permession_s {
+ char *val;
+ char *(*get_permission)(char *refparam, struct dmctx *dmctx, void *data, char *instance);
+};
+
+struct dm_forced_inform_s {
+ unsigned char val;
+ unsigned char (*get_forced_inform)(char *refparam, struct dmctx *dmctx, void *data, char *instance);
+};
+
+struct dm_notif_s {
+ char *val;
+ char *(*get_notif)(char *refparam, struct dmctx *dmctx, void *data, char *instance);
+};
+
+typedef struct dm_leaf_s {
+ /* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type(8)*/
+ char *parameter;
+ struct dm_permession_s *permission;
+ int type;
+ int (*getvalue)(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+ int (*setvalue)(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+ struct dm_forced_inform_s *forced_inform;
+ struct dm_notif_s *notification;
+ int bbfdm_type;
+} DMLEAF;
+
+typedef struct dm_obj_s {
+ /* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type(12)*/
+ char *obj;
+ struct dm_permession_s *permission;
+ int (*addobj)(char *refparam, struct dmctx *ctx, void *data, char **instance);
+ int (*delobj)(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+ bool (*checkobj)(struct dmctx *dmctx, void *data);
+ int (*browseinstobj)(struct dmctx *dmctx, struct dmnode *node, void *data, char *instance);
+ struct dm_forced_inform_s *forced_inform;
+ struct dm_notif_s *notification;
+ struct dm_obj_s *nextobj;
+ struct dm_leaf_s *leaf;
+ int (*get_linker)(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+ int bbfdm_type;
+} DMOBJ;
+
+#ifdef BBF_TR064
+typedef struct dm_upnp_supported_dm_s {
+ char *location;
+ char *uri;
+ char *url;
+ char *description;
+ char *source_location;
+} UPNP_SUPPORTED_DM;
+#endif
+
+struct set_tmp {
+ struct list_head list;
+ char *name;
+ char *value;
+ unsigned int flags;
+};
+
+struct param_fault {
+ struct list_head list;
+ char *name;
+ int fault;
+};
+
+struct dm_enabled_notify {
+ struct list_head list;
+ char *name;
+ char *notification;
+ char *value;
+};
+
+#ifdef BBF_TR064
+struct dm_upnp_enabled_track {
+ struct list_head list;
+ char *name;
+ char *key;
+ char *value;
+ unsigned int isobj;
+};
+#endif
+
+struct dm_parameter {
+ struct list_head list;
+ char *name;
+ char *data;
+ char *type;
+ char *version;
+ unsigned int flags;
+};
+
+struct dmctx
+{
+ bool stop;
+ bool match;
+ int (*method_param)(DMPARAM_ARGS);
+ int (*method_obj)(DMOBJECT_ARGS);
+ int (*checkobj)(DMOBJECT_ARGS);
+ int (*checkleaf)(DMOBJECT_ARGS);
+ struct list_head list_parameter;
+ struct list_head set_list_tmp;
+ struct list_head list_fault_param;
+ DMOBJ *dm_entryobj;
+ bool nextlevel;
+ int depth;
+ int faultcode;
+ int setaction;
+ char *in_param;
+ char *in_notification;
+ bool notification_change;
+ char *in_value;
+ char *addobj_instance;
+ char *linker;
+ char *linker_param;
+ unsigned int dmparam_flags;
+ unsigned int alias_register;
+ unsigned int nbrof_instance;
+ unsigned int amd_version;
+ unsigned int instance_mode;
+ unsigned int dm_type;
+ unsigned int user_mask;
+ unsigned char inparam_isparam;
+ unsigned char findparam;
+ char all_instances[512];
+ char *inst_buf[16];
+ char *instance_wildchar;
+};
+
+
+typedef struct dmnode {
+ DMOBJ *obj;
+ struct dmnode *parent;
+ char *current_object;
+ unsigned char instance_level;
+ unsigned char matched;
+ unsigned char is_instanceobj;
+} DMNODE;
+
+struct prefix_method {
+ const char *prefix_name;
+ bool enable;
+ bool (*set_enable)(void);
+ bool forced_inform;
+ int (*method)(struct dmctx *ctx);
+};
+
+struct notification {
+ char *value;
+ char *type;
+};
+
+struct dm_acl {
+ unsigned int flag;
+ char *user_access;
+};
+
+typedef struct execute_end_session {
+ struct list_head list;
+ int action;
+ unsigned int dm_type;
+ unsigned int amd_version;
+ unsigned int instance_mode;
+ void *data;
+ void (*function)(struct execute_end_session *);
+} execute_end_session;
+
+enum set_value_action {
+ VALUECHECK,
+ VALUESET
+};
+
+enum del_action_enum {
+ DEL_INST,
+ DEL_ALL
+};
+enum {
+ CMD_GET_VALUE,
+ CMD_GET_NAME,
+ CMD_GET_NOTIFICATION,
+ CMD_SET_VALUE,
+ CMD_SET_NOTIFICATION,
+ CMD_ADD_OBJECT,
+ CMD_DEL_OBJECT,
+ CMD_INFORM,
+ CMD_USP_OPERATE,
+#ifdef BBF_TR064
+ CMD_UPNP_GET_SUPPORTED_PARAMETERS,
+ CMD_UPNP_GET_INSTANCES,
+ CMD_UPNP_GET_SELECTED_VALUES,
+ CMD_UPNP_GET_VALUES,
+ CMD_UPNP_SET_VALUES,
+ CMD_UPNP_GET_ATTRIBUTES,
+ CMD_UPNP_SET_ATTRIBUTES,
+ CMD_UPNP_DEL_INSTANCE,
+ CMD_UPNP_ADD_INSTANCE,
+ CMD_UPNP_GET_ACLDATA,
+ CMD_UPNP_INIT_STATE_VARIABLES,
+ CMD_UPNP_LOAD_ENABLED_PARAMETRS_TRACK,
+ CMD_UPNP_GET_CONFIGURATION_UPDATE,
+ CMD_UPNP_GET_CURRENT_CONFIGURATION_VERSION,
+ CMD_UPNP_GET_SUPPORTED_DATA_MODEL_UPDATE,
+ CMD_UPNP_GET_SUPPORTED_PARAMETERS_UPDATE,
+ CMD_UPNP_GET_ATTRIBUTE_VALUES_UPDATE,
+ CMD_UPNP_GET_ENABLED_PARAMETRS_ALARM,
+ CMD_UPNP_GET_ENABLED_PARAMETRS_EVENT,
+ CMD_UPNP_GET_ENABLED_PARAMETRS_VERSION,
+ CMD_UPNP_CHECK_CHANGED_PARAMETRS_ALARM,
+ CMD_UPNP_CHECK_CHANGED_PARAMETRS_EVENT,
+ CMD_UPNP_CHECK_CHANGED_PARAMETRS_VERSION,
+#endif
+ CMD_EXTERNAL_COMMAND
+};
+
+enum fault_code_enum {
+ FAULT_9000 = 9000,// Method not supported
+ FAULT_9001,// Request denied
+ FAULT_9002,// Internal error
+ FAULT_9003,// Invalid arguments
+ FAULT_9004,// Resources exceeded
+ FAULT_9005,// Invalid parameter name
+ FAULT_9006,// Invalid parameter type
+ FAULT_9007,// Invalid parameter value
+ FAULT_9008,// Attempt to set a non-writable parameter
+ FAULT_9009,// Notification request rejected
+ FAULT_9010,// Download failure
+ FAULT_9011,// Upload failure
+ FAULT_9012,// File transfer server authentication failure
+ FAULT_9013,// Unsupported protocol for file transfer
+ FAULT_9014,// Download failure: unable to join multicast group
+ FAULT_9015,// Download failure: unable to contact file server
+ FAULT_9016,// Download failure: unable to access file
+ FAULT_9017,// Download failure: unable to complete download
+ FAULT_9018,// Download failure: file corrupted
+ FAULT_9019,// Download failure: file authentication failure
+ FAULT_9020,// Download failure: unable to complete download
+ FAULT_9021,// Cancelation of file transfer not permitted
+ FAULT_9022,// Invalid UUID format
+ FAULT_9023,// Unknown Execution Environment
+ FAULT_9024,// Disabled Execution Environment
+ FAULT_9025,// Diployment Unit to Execution environment mismatch
+ FAULT_9026,// Duplicate Deployment Unit
+ FAULT_9027,// System Ressources Exceeded
+ FAULT_9028,// Unknown Deployment Unit
+ FAULT_9029,// Invalid Deployment Unit State
+ FAULT_9030,// Invalid Deployment Unit Update: Downgrade not permitted
+ FAULT_9031,// Invalid Deployment Unit Update: Version not specified
+ FAULT_9032,// Invalid Deployment Unit Update: Version already exist
+ __FAULT_MAX
+};
+
+#ifdef BBF_TR064
+enum upnp_fault_code_enum {
+ FAULT_UPNP_606 = 606,// Action not authorized
+ FAULT_UPNP_701 = 701,// Invalid Argument Syntax
+ FAULT_UPNP_702,//Invalid XML Argument
+ FAULT_UPNP_703,// No Such Name
+ FAULT_UPNP_704,// Invalid Value Type
+ FAULT_UPNP_705,// Invalid Value
+ FAULT_UPNP_706,// Read Only Violation
+ FAULT_UPNP_707,// Multiple Set
+ FAULT_UPNP_708,// Resource Temporarily Unavailable
+ __FAULT_UPNP_MAX
+};
+#endif
+
+enum {
+ INSTANCE_UPDATE_NUMBER,
+ INSTANCE_UPDATE_ALIAS
+};
+
+enum instance_mode {
+ INSTANCE_MODE_NUMBER,
+ INSTANCE_MODE_ALIAS
+};
+
+enum end_session_enum {
+ END_SESSION_REBOOT = 1,
+ END_SESSION_EXTERNAL_ACTION = 1<<1,
+ END_SESSION_RELOAD = 1<<2,
+ END_SESSION_FACTORY_RESET = 1<<3,
+ END_SESSION_IPPING_DIAGNOSTIC = 1<<4,
+ END_SESSION_DOWNLOAD_DIAGNOSTIC = 1<<5,
+ END_SESSION_UPLOAD_DIAGNOSTIC = 1<<6,
+ END_SESSION_X_FACTORY_RESET_SOFT = 1<<7,
+ END_SESSION_NSLOOKUP_DIAGNOSTIC = 1<<8,
+ END_SESSION_TRACEROUTE_DIAGNOSTIC = 1<<9,
+ END_SESSION_UDPECHO_DIAGNOSTIC = 1<<10,
+ END_SESSION_SERVERSELECTION_DIAGNOSTIC = 1<<11
+};
+
+enum dm_browse_enum {
+ DM_ERROR = -1,
+ DM_OK = 0,
+ DM_STOP = 1
+};
+
+enum dmt_type_enum {
+ DMT_STRING,
+ DMT_UNINT,
+ DMT_INT,
+ DMT_LONG,
+ DMT_BOOL,
+ DMT_TIME,
+ DMT_HEXBIN,
+};
+
+enum amd_version_enum{
+ AMD_1 = 1,
+ AMD_2,
+ AMD_3,
+ AMD_4,
+ AMD_5,
+};
+
+enum dm_type_enum{
+ DM_CWMP,
+ DM_UPNP,
+};
+
+enum bbfdm_type_enum{
+ BBFDM_BOTH,
+ BBFDM_CWMP,
+ BBFDM_USP,
+};
+
+enum dm_param_flags_enum{
+ /* UPNP OnChange flags flags */
+ DM_PARAM_ALARAM_ON_CHANGE = 1 << 0,
+ DM_PARAM_EVENT_ON_CHANGE = 1 << 1,
+ /* UPNP type flags */
+ NODE_DATA_ATTRIBUTE_INSTANCE = 0x0010,
+ NODE_DATA_ATTRIBUTE_MULTIINSTANCE = 0x0020,
+ NODE_DATA_ATTRIBUTE_TYPESTRING = 0x0100,
+ NODE_DATA_ATTRIBUTE_TYPEINT = 0x0200,
+ NODE_DATA_ATTRIBUTE_TYPELONG = 0x0400,
+ NODE_DATA_ATTRIBUTE_TYPEBOOL = 0x0800,
+ NODE_DATA_ATTRIBUTE_TYPEDATETIME = 0x1000,
+ NODE_DATA_ATTRIBUTE_TYPEBASE64 = 0x2000,
+ NODE_DATA_ATTRIBUTE_TYPEBIN = 0x4000,
+ NODE_DATA_ATTRIBUTE_TYPEPTR = 0x8000,
+ NODE_DATA_ATTRIBUTE_TYPEMASK = 0x0000FF00,
+ /*ACLRoles*/
+ DM_PUBLIC_LIST = 1 << 0,
+ DM_PUBLIC_READ = 1 << 1,
+ DM_PUBLIC_WRITE = 1 << 2,
+ DM_PUBLIC_MASK = DM_PUBLIC_LIST|DM_PUBLIC_READ|DM_PUBLIC_WRITE,
+ DM_BASIC_LIST = 1 << 3,
+ DM_BASIC_READ = 1 << 4,
+ DM_BASIC_WRITE = 1 << 5,
+ DM_BASIC_MASK = DM_PUBLIC_MASK|DM_BASIC_LIST|DM_BASIC_READ|DM_BASIC_WRITE,
+ DM_XXXADMIN_LIST = 1 << 6,
+ DM_XXXADMIN_READ = 1 << 7,
+ DM_XXXADMIN_WRITE = 1 << 8,
+ DM_XXXADMIN_MASK = DM_BASIC_MASK|DM_XXXADMIN_LIST|DM_XXXADMIN_READ|DM_XXXADMIN_WRITE,
+ DM_SUPERADMIN_MASK = DM_XXXADMIN_MASK | (1 << 9),
+ DM_LIST_MASK = DM_PUBLIC_LIST|DM_BASIC_LIST|DM_XXXADMIN_LIST,
+ DM_READ_MASK = DM_PUBLIC_READ|DM_BASIC_READ|DM_XXXADMIN_READ,
+ DM_WRITE_MASK = DM_PUBLIC_WRITE|DM_BASIC_WRITE|DM_XXXADMIN_WRITE,
+ DM_FACTORIZED = 1 << 31
+};
+
+extern struct list_head list_enabled_notify;
+extern struct list_head list_enabled_lw_notify;
+extern struct list_head list_execute_end_session;
+
+#ifdef BBF_TR064
+extern struct list_head list_upnp_enabled_onevent;
+extern struct list_head list_upnp_enabled_onalarm;
+extern struct list_head list_upnp_enabled_version;
+extern struct list_head list_upnp_changed_onevent;
+extern struct list_head list_upnp_changed_onalarm;
+extern struct list_head list_upnp_changed_version;
+#endif
+
+extern int end_session_flag;
+extern int ip_version;
+extern char dm_delim;
+extern char dmroot[64];
+extern int bbfdatamodel_type;
+extern unsigned int upnp_in_user_mask;
+
+char *update_instance(struct uci_section *s, char *last_inst, char *inst_opt);
+char *update_instance_icwmpd(struct uci_section *s, char *last_inst, char *inst_opt);
+char *update_instance_alias_icwmpd(int action, char **last_inst , void *argv[]);
+char *update_instance_alias(int action, char **last_inst , void *argv[]);
+char *update_instance_without_section(int action, char **last_inst, void *argv[]);
+int get_empty(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+void add_list_paramameter(struct dmctx *ctx, char *param_name, char *param_data, char *param_type, char *param_version, unsigned int flags);
+void del_list_parameter(struct dm_parameter *dm_parameter);
+void free_all_list_parameter(struct dmctx *ctx);
+void add_set_list_tmp(struct dmctx *ctx, char *param, char *value, unsigned int flags);
+void del_set_list_tmp(struct set_tmp *set_tmp);
+void free_all_set_list_tmp(struct dmctx *ctx);
+void add_list_fault_param(struct dmctx *ctx, char *param, int fault);
+void del_list_fault_param(struct param_fault *param_fault);
+void free_all_list_fault_param(struct dmctx *ctx);
+int string_to_bool(char *v, bool *b);
+int dm_entry_operate(struct dmctx *dmctx);
+int dm_entry_get_value(struct dmctx *ctx);
+int dm_entry_get_name(struct dmctx *ctx);
+int dm_entry_get_notification(struct dmctx *ctx);
+int dm_entry_inform(struct dmctx *ctx);
+int dm_entry_add_object(struct dmctx *ctx);
+int dm_entry_delete_object(struct dmctx *ctx);
+int dm_entry_set_value(struct dmctx *ctx);
+int dm_entry_set_notification(struct dmctx *ctx);
+int dm_entry_enabled_notify(struct dmctx *ctx);
+int dm_entry_enabled_notify_check_value_change(struct dmctx *dmctx);
+int dm_entry_get_linker(struct dmctx *ctx);
+int dm_entry_get_linker_value(struct dmctx *ctx);
+#ifdef BBF_TR064
+int dm_entry_upnp_get_instances(struct dmctx *ctx);
+int dm_entry_upnp_get_selected_values(struct dmctx *dmctx);
+int dm_entry_upnp_get_values(struct dmctx *dmctx);
+int dm_entry_upnp_set_values(struct dmctx *dmctx);
+int dm_entry_upnp_get_attributes(struct dmctx *dmctx);
+int upnp_state_variables_init(struct dmctx *dmctx);
+int dm_entry_upnp_tracked_parameters(struct dmctx *dmctx);
+int dm_entry_upnp_get_instance_numbers(struct dmctx *dmctx);
+char *dm_entry_get_all_instance_numbers(struct dmctx *pctx, char *param);
+void free_all_list_enabled_notify();
+void free_all_list_upnp_param_track(struct list_head *head);
+#endif
+void dm_update_enabled_notify(struct dm_enabled_notify *p, char *new_value);
+int dm_update_file_enabled_notify(char *param, char *new_value);
+void dm_update_enabled_notify_byname(char *name, char *new_value);
+char *get_last_instance(char *package, char *section, char *opt_inst);
+char *get_last_instance_icwmpd_without_update(char *package, char *section, char *opt_inst);
+char *get_last_instance_icwmpd(char *package, char *section, char *opt_inst);
+char *get_vlan_last_instance_icwmpd(char *package, char *section, char *opt_inst, char *vlan_method);
+char *get_last_instance_lev2(char *package, char *section, char *opt_inst, char *opt_check, char *value_check);
+char *get_last_instance_lev2_icwmpd_dmmap_opt(char* dmmap_package, char *section, char *opt_inst, char *opt_check, char *value_check);
+char *get_last_instance_lev2_icwmpd(char *package, char *section, char* dmmap_package, char *opt_inst, char *opt_check, char *value_check);
+char *handle_update_instance(int instance_ranck, struct dmctx *ctx, char **last_inst, char * (*up_instance)(int action, char **last_inst, void *argv[]), int argc, ...);
+int dm_add_end_session(struct dmctx *ctx, void(*function)(struct execute_end_session *), int action, void *data);
+int apply_end_session();
+void cwmp_set_end_session (unsigned int flag);
+char *dm_print_path(char *fpath, ...);
+void free_all_list_enabled_lwnotify();
+int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char *instance);
+#ifdef BBF_TR064
+void dm_upnp_apply_config(void);
+void add_list_upnp_param_track(struct dmctx *dmctx, struct list_head *pchead, char *param, char *key, char *value, unsigned int isobj);
+int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char *instance);
+int dm_entry_upnp_get_supported_parameters(struct dmctx *dmctx);
+int dm_entry_upnp_set_attributes(struct dmctx *dmctx);
+int dm_entry_upnp_delete_instance(struct dmctx *dmctx);
+int dm_entry_upnp_get_acl_data(struct dmctx *dmctx);
+void free_all_list_enabled_lwnotify();
+int dm_entry_upnp_add_instance(struct dmctx *dmctx);
+#endif
+
+static inline int DM_LINK_INST_OBJ(struct dmctx *dmctx, DMNODE *parent_node, void *data, char *instance)
+{
+ dmctx->faultcode = dm_link_inst_obj(dmctx, parent_node, data, instance);
+ if (dmctx->stop)
+ return DM_STOP;
+ return DM_OK;
+}
+
+#ifndef TRACE
+#define TRACE_TYPE 0
+static inline void trace_empty_func()
+{
+}
+#if TRACE_TYPE == 2
+#define TRACE(MESSAGE,args...) do { \
+ const char *A[] = {MESSAGE}; \
+ fprintf(stderr, "TRACE: %s %s %d ",__FUNCTION__,__FILE__,__LINE__); \
+ if(sizeof(A) > 0) \
+ fprintf(stderr, *A,##args); \
+ fprintf(stderr, "\n"); \
+ fflush(stderr); \
+} while(0)
+#elif TRACE_TYPE == 1
+#define TRACE(MESSAGE, ...) printf(MESSAGE, ## __VA_ARGS__)
+#else
+#define TRACE(MESSAGE, ...) trace_empty_func()
+#endif
+#endif
+
+#ifndef DETECT_CRASH
+#define DETECT_CRASH(MESSAGE,args...) { \
+ const char *A[] = {MESSAGE}; \
+ printf("DETECT_CRASH: %s %s %d\n",__FUNCTION__,__FILE__,__LINE__); fflush(stdout);\
+ if(sizeof(A) > 0) \
+ printf(*A,##args); \
+ sleep(1); \
+}
+#endif
+
+#endif
diff --git a/dmdiagnostics.c b/dmdiagnostics.c
new file mode 100644
index 00000000..4efb4358
--- /dev/null
+++ b/dmdiagnostics.c
@@ -0,0 +1,656 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB
+ * Author: Amin Ben Ramdhane
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "dmentry.h"
+#include "dmcommon.h"
+#include "dmdiagnostics.h"
+
+int read_next;
+struct download_diag download_stats = {0};
+struct upload_diagnostic_stats upload_stats = {0};
+
+char *get_param_diagnostics(char *diag, char *option)
+{
+ char buf[32], *value;
+
+ sprintf(buf, "@%s[0]", diag);
+ dmuci_get_varstate_string("cwmp", buf, option, &value);
+ return value;
+}
+
+void set_param_diagnostics(char *diag, char *option, char *value)
+{
+ struct uci_section *curr_section = NULL;
+ char buf[32], *tmp;
+
+ curr_section = dmuci_walk_state_section("cwmp", diag, NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", diag, &curr_section, &tmp);
+ }
+ sprintf(buf, "@%s[0]", diag);
+ dmuci_set_varstate_value("cwmp", buf, option, value);
+}
+
+void init_download_stats(void)
+{
+ memset(&download_stats, 0, sizeof(download_stats));
+}
+
+void init_upload_stats(void)
+{
+ memset(&upload_stats, 0, sizeof(upload_stats));
+}
+
+static void ftp_download_per_packet(libtrace_packet_t *packet)
+{
+ struct tm lt;
+ struct timeval ts;
+ libtrace_tcp_t *tcp;
+ char tcp_flag[16] = "";
+ char *nexthdr;
+ char s_now[default_date_size];
+ uint8_t proto;
+ uint32_t remaining;
+
+ tcp = trace_get_transport(packet, &proto, &remaining);
+ if (tcp == NULL)
+ return;
+ else
+ nexthdr = trace_get_payload_from_tcp(tcp, &remaining);
+
+ if (tcp->ecn_ns) strcat(tcp_flag, "ECN_NS ");
+ if (tcp->cwr) strcat(tcp_flag, "CWR ");
+ if (tcp->ece) strcat(tcp_flag, "ECE ");
+ if (tcp->fin) strcat(tcp_flag, "FIN ");
+ if (tcp->syn) strcat(tcp_flag, "SYN ");
+ if (tcp->rst) strcat(tcp_flag, "RST ");
+ if (tcp->psh) strcat(tcp_flag, "PSH ");
+ if (tcp->ack) strcat(tcp_flag, "ACK ");
+ if (tcp->urg) strcat(tcp_flag, "URG ");
+
+ if (strcmp(tcp_flag, "PSH ACK ") == 0 && strlen(nexthdr) > strlen(FTP_SIZE_RESPONSE) && strncmp(nexthdr, FTP_SIZE_RESPONSE, strlen(FTP_SIZE_RESPONSE)) == 0)
+ {
+ char *val = strstr(nexthdr,"213");
+ char *pch, *pchr;
+ val += strlen("213 ");
+ pch=strtok_r(val, " \r\n\t", &pchr);
+ download_stats.test_bytes_received = atoi(pch);
+ }
+ if(strcmp(tcp_flag, "PSH ACK ") == 0 && strlen(nexthdr) > strlen(FTP_PASV_RESPONSE) && strncmp(nexthdr, FTP_PASV_RESPONSE, strlen(FTP_PASV_RESPONSE)) == 0)
+ {
+ download_stats.ftp_syn = 1;
+ return;
+ }
+ if (download_stats.random_seq == 0 && strcmp(tcp_flag, "SYN ") == 0 && download_stats.ftp_syn == 1)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ download_stats.random_seq = ntohl(tcp->seq);
+ sprintf((download_stats.tcpopenrequesttime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ }
+ if (strcmp(tcp_flag, "SYN ACK ") == 0 && download_stats.random_seq != 0 && (ntohl(tcp->ack_seq) - 1 ) == download_stats.random_seq)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((download_stats.tcpopenresponsetime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ download_stats.random_seq = ntohl(tcp->ack_seq);
+ sprintf((download_stats.tcpopenresponsetime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ }
+ if (strcmp(tcp_flag, "PSH ACK ") == 0 && strlen(nexthdr) > strlen(FTP_RETR_REQUEST) && strncmp(nexthdr, FTP_RETR_REQUEST, strlen(FTP_RETR_REQUEST)) == 0)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((download_stats.romtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ }
+ if(strcmp(tcp_flag, "ACK ") == 0 && ntohl(tcp->seq) == download_stats.random_seq && download_stats.ack_seq == 0)
+ {
+ download_stats.ack_seq = ntohl(tcp->seq);
+ return;
+ }
+ if(strcmp(tcp_flag, "ACK ") == 0 && ntohl(tcp->ack_seq) == download_stats.ack_seq )
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ if (download_stats.first_data == 0)
+ {
+ sprintf((download_stats.bomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ }
+ download_stats.first_data = 1;
+ }
+ if ( (strcmp(tcp_flag, "PSH ACK ") == 0 || strcmp(tcp_flag, "FIN PSH ACK ") == 0) && ntohl(tcp->ack_seq) == download_stats.ack_seq)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ if (download_stats.first_data == 0)
+ {
+ sprintf((download_stats.bomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ download_stats.first_data = 1;
+ }
+ sprintf((download_stats.eomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ }
+}
+
+static void http_download_per_packet(libtrace_packet_t *packet)
+{
+ struct tm lt;
+ struct timeval ts;
+ libtrace_tcp_t *tcp;
+ uint32_t seq = 0;
+ char tcp_flag[16] = "";
+ char *nexthdr;
+ char s_now[default_date_size];
+ uint8_t proto;
+ uint32_t remaining;
+
+ tcp = trace_get_transport(packet, &proto, &remaining);
+ if (tcp == NULL)
+ return;
+ else
+ nexthdr = trace_get_payload_from_tcp(tcp, &remaining);
+
+ if (tcp->ecn_ns) strcat(tcp_flag, "ECN_NS ");
+ if (tcp->cwr) strcat(tcp_flag, "CWR ");
+ if (tcp->ece) strcat(tcp_flag, "ECE ");
+ if (tcp->fin) strcat(tcp_flag, "FIN ");
+ if (tcp->syn) strcat(tcp_flag, "SYN ");
+ if (tcp->rst) strcat(tcp_flag, "RST ");
+ if (tcp->psh) strcat(tcp_flag, "PSH ");
+ if (tcp->ack) strcat(tcp_flag, "ACK ");
+ if (tcp->urg) strcat(tcp_flag, "URG ");
+
+ if (strcmp(tcp_flag, "SYN ") == 0 && download_stats.random_seq == 0)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((download_stats.tcpopenrequesttime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ download_stats.random_seq = ntohl(tcp->seq);
+ return;
+ }
+ if (strcmp(tcp_flag, "SYN ACK ") == 0 && download_stats.random_seq != 0 && (ntohl(tcp->ack_seq) - 1 ) == download_stats.random_seq)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((download_stats.tcpopenresponsetime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ download_stats.random_seq = ntohl(tcp->seq);
+ return;
+ }
+ if (strcmp(tcp_flag, "PSH ACK ") == 0 && strncmp(nexthdr, "GET", 3) == 0)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((download_stats.romtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ download_stats.get_ack = ntohl(tcp->ack_seq);
+ return;
+ }
+ if(strcmp(tcp_flag, "ACK ") == 0 && ntohl(tcp->seq) == download_stats.get_ack && download_stats.ack_seq == 0)
+ {
+ download_stats.ack_seq = ntohl(tcp->ack_seq);
+ return;
+ }
+ if(strcmp(tcp_flag, "ACK ") == 0 && ntohl(tcp->ack_seq) == download_stats.ack_seq )
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ if (download_stats.first_data == 0)
+ {
+ sprintf((download_stats.bomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ char *val = strstr(nexthdr,"Content-Length");
+ char *pch, *pchr;
+ val += strlen("Content-Length: ");
+ pch=strtok_r(val, " \r\n\t", &pchr);
+ download_stats.test_bytes_received = atoi(pch);
+ download_stats.first_data = 1;
+ }
+ return;
+ }
+ if ( (strcmp(tcp_flag, "PSH ACK ") == 0 || strcmp(tcp_flag, "FIN PSH ACK ") == 0) && ntohl(tcp->ack_seq) == download_stats.ack_seq)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ if (download_stats.first_data == 0)
+ {
+ sprintf((download_stats.bomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ char *val = strstr(nexthdr,"Content-Length");
+ char *pch, *pchr;
+ val += strlen("Content-Length: ");
+ pch=strtok_r(val, " \r\n\t", &pchr);
+ download_stats.test_bytes_received = atoi(pch);
+ download_stats.first_data = 1;
+ }
+ sprintf((download_stats.eomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ return;
+ }
+}
+
+static void libtrace_cleanup(libtrace_t *trace, libtrace_packet_t *packet)
+{
+ if (trace)
+ trace_destroy(trace);
+
+ if (packet)
+ trace_destroy_packet(packet);
+}
+
+static void set_download_stats(char *protocol)
+{
+ char buf[16];
+
+ if(strcmp(protocol, "cwmp")== 0)
+ init_uci_varstate_ctx();
+
+ set_param_diagnostics("downloaddiagnostic", "ROMtime", download_stats.romtime);
+ set_param_diagnostics("downloaddiagnostic", "BOMtime", download_stats.bomtime);
+ set_param_diagnostics("downloaddiagnostic", "EOMtime", download_stats.eomtime);
+ set_param_diagnostics("downloaddiagnostic", "TCPOpenRequestTimes", download_stats.tcpopenrequesttime);
+ set_param_diagnostics("downloaddiagnostic", "TCPOpenResponseTime", download_stats.tcpopenresponsetime);
+ sprintf(buf,"%d", download_stats.test_bytes_received);
+ set_param_diagnostics("downloaddiagnostic", "TestBytesReceived", buf);
+
+ if(strcmp(protocol, "cwmp")== 0)
+ end_uci_varstate_ctx();
+}
+
+static void set_upload_stats(char *protocol)
+{
+ if(strcmp(protocol, "cwmp")== 0)
+ init_uci_varstate_ctx();
+
+ set_param_diagnostics("uploaddiagnostic", "ROMtime", upload_stats.romtime);
+ set_param_diagnostics("uploaddiagnostic", "BOMtime", upload_stats.bomtime);
+ set_param_diagnostics("uploaddiagnostic", "EOMtime", upload_stats.eomtime);
+ set_param_diagnostics("uploaddiagnostic", "TCPOpenRequestTimes", upload_stats.tcpopenrequesttime);
+ set_param_diagnostics("uploaddiagnostic", "TCPOpenResponseTime", upload_stats.tcpopenresponsetime);
+
+ if(strcmp(protocol, "cwmp")== 0)
+ end_uci_varstate_ctx();
+}
+
+static void http_upload_per_packet(libtrace_packet_t *packet)
+{
+ struct tm lt;
+ struct timeval ts;
+ libtrace_tcp_t *tcp;
+ char tcp_flag[16] = "";
+ char *nexthdr;
+ char s_now[default_date_size];
+ uint8_t proto;
+ uint32_t remaining;
+
+ tcp = trace_get_transport(packet, &proto, &remaining);
+ if (tcp == NULL)
+ return;
+ else
+ nexthdr = trace_get_payload_from_tcp(tcp, &remaining);
+
+ if (tcp->ecn_ns) strcat(tcp_flag, "ECN_NS ");
+ if (tcp->cwr) strcat(tcp_flag, "CWR ");
+ if (tcp->ece) strcat(tcp_flag, "ECE ");
+ if (tcp->fin) strcat(tcp_flag, "FIN ");
+ if (tcp->syn) strcat(tcp_flag, "SYN ");
+ if (tcp->rst) strcat(tcp_flag, "RST ");
+ if (tcp->psh) strcat(tcp_flag, "PSH ");
+ if (tcp->ack) strcat(tcp_flag, "ACK ");
+ if (tcp->urg) strcat(tcp_flag, "URG ");
+
+ if (strcmp(tcp_flag, "SYN ") == 0 && download_stats.random_seq == 0)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((upload_stats.tcpopenrequesttime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ upload_stats.random_seq = ntohl(tcp->seq);
+ }
+ if (strcmp(tcp_flag, "SYN ACK ") == 0 && upload_stats.random_seq != 0 && (ntohl(tcp->ack_seq) - 1 ) == upload_stats.random_seq)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((upload_stats.tcpopenresponsetime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ upload_stats.random_seq = ntohl(tcp->seq);
+ }
+ if (strcmp(tcp_flag, "PSH ACK ") == 0 && strncmp(nexthdr, "PUT", 3) == 0)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((upload_stats.romtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ if (strstr(nexthdr, "Expect: 100-continue"))
+ {
+ upload_stats.tmp=1;
+ upload_stats.ack_seq = ntohl(tcp->ack_seq);
+ }
+ else
+ upload_stats.ack_seq = ntohl(tcp->ack_seq);
+ return;
+ }
+ if (strcmp(tcp_flag, "PSH ACK ") == 0 && upload_stats.tmp == 1 && strstr(nexthdr, "100 Continue"))
+ {
+ upload_stats.tmp = 2;
+ upload_stats.ack_seq = ntohl(tcp->ack_seq);
+ return;
+ }
+ if (strcmp(tcp_flag, "ACK ") == 0 && upload_stats.tmp == 2 && ntohl(tcp->seq) == upload_stats.ack_seq)
+ {
+ upload_stats.tmp = 0;
+ upload_stats.ack_seq = ntohl(tcp->ack_seq);
+ return;
+ }
+ if(strcmp(tcp_flag, "ACK ") == 0 && ntohl(tcp->ack_seq) == upload_stats.ack_seq && upload_stats.tmp == 0)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ if (upload_stats.first_data == 0)
+ {
+ sprintf((upload_stats.bomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ upload_stats.first_data = 1;
+ }
+ }
+ if ( (strcmp(tcp_flag, "PSH ACK ") == 0 || strcmp(tcp_flag, "FIN PSH ACK ") == 0) && ntohl(tcp->ack_seq) == upload_stats.ack_seq && upload_stats.tmp == 0)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ if (upload_stats.first_data == 0)
+ {
+ sprintf((upload_stats.bomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ upload_stats.first_data = 1;
+ }
+ }
+ if ( (strcmp(tcp_flag, "PSH ACK ") == 0 || strcmp(tcp_flag, "FIN PSH ACK ") == 0) && ntohl(tcp->seq) == upload_stats.ack_seq && upload_stats.tmp == 0)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((upload_stats.eomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ }
+}
+
+static void ftp_upload_per_packet(libtrace_packet_t *packet)
+{
+ struct tm lt;
+ struct timeval ts;
+ libtrace_tcp_t *tcp;
+ uint8_t proto;
+ uint32_t remaining;
+ char tcp_flag[16] = "";
+ char *nexthdr;
+ char s_now[default_date_size];
+
+ tcp = trace_get_transport(packet, &proto, &remaining);
+ if (tcp == NULL)
+ return;
+ else
+ nexthdr = trace_get_payload_from_tcp(tcp, &remaining);
+
+ if (tcp->ecn_ns) strcat(tcp_flag, "ECN_NS ");
+ if (tcp->cwr) strcat(tcp_flag, "CWR ");
+ if (tcp->ece) strcat(tcp_flag, "ECE ");
+ if (tcp->fin) strcat(tcp_flag, "FIN ");
+ if (tcp->syn) strcat(tcp_flag, "SYN ");
+ if (tcp->rst) strcat(tcp_flag, "RST ");
+ if (tcp->psh) strcat(tcp_flag, "PSH ");
+ if (tcp->ack) strcat(tcp_flag, "ACK ");
+ if (tcp->urg) strcat(tcp_flag, "URG ");
+
+ if(strcmp(tcp_flag, "PSH ACK ") == 0 && strlen(nexthdr) > strlen(FTP_PASV_RESPONSE) && strncmp(nexthdr, FTP_PASV_RESPONSE, strlen(FTP_PASV_RESPONSE)) == 0)
+ {
+ upload_stats.ftp_syn = 1;
+ return;
+ }
+ if (strcmp(tcp_flag, "SYN ") == 0 && upload_stats.ftp_syn == 1)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ upload_stats.random_seq = ntohl(tcp->seq);
+ sprintf((upload_stats.tcpopenrequesttime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ }
+ if (strcmp(tcp_flag, "SYN ACK ") == 0 && upload_stats.random_seq != 0 && (ntohl(tcp->ack_seq) - 1 ) == upload_stats.random_seq)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((upload_stats.tcpopenresponsetime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ upload_stats.random_seq = ntohl(tcp->ack_seq);
+ }
+ if (strcmp(tcp_flag, "PSH ACK ") == 0 && strlen(nexthdr) > strlen(FTP_STOR_REQUEST) && strncmp(nexthdr, FTP_STOR_REQUEST, strlen(FTP_STOR_REQUEST)) == 0)
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((upload_stats.romtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ }
+ if(strcmp(tcp_flag, "ACK ") == 0 && ntohl(tcp->seq) == upload_stats.random_seq && upload_stats.ack_seq == 0)
+ {
+ upload_stats.ack_seq = ntohl(tcp->ack_seq);
+ return;
+ }
+ if(strcmp(tcp_flag, "ACK ") == 0 && ntohl(tcp->ack_seq) == upload_stats.ack_seq )
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ if (upload_stats.first_data == 0)
+ {
+ sprintf((upload_stats.bomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ upload_stats.first_data = 1;
+ }
+ }
+ if ( (strcmp(tcp_flag, "PSH ACK ") == 0 || strcmp(tcp_flag, "FIN PSH ACK ") == 0) && ntohl(tcp->ack_seq) == upload_stats.ack_seq) //&& strlen(nexthdr) > 16 && strncmp(nexthdr, "HTTP/1.1 200 OK", 16) == 0
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ if (upload_stats.first_data == 0)
+ {
+ sprintf((upload_stats.bomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ upload_stats.first_data = 1;
+ }
+ }
+ if ( (strcmp(tcp_flag, "PSH ACK ") == 0 || strcmp(tcp_flag, "FIN PSH ACK ") == 0) && strlen(nexthdr) > strlen(FTP_TRANSFERT_COMPLETE) && strncmp(nexthdr, FTP_TRANSFERT_COMPLETE, strlen(FTP_TRANSFERT_COMPLETE)) == 0) //&& strlen(nexthdr) > 16 && strncmp(nexthdr, "HTTP/1.1 200 OK", 16) == 0
+ {
+ ts = trace_get_timeval(packet);
+ (void) localtime_r(&(ts.tv_sec), <);
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", <);
+ sprintf((upload_stats.eomtime),"%s.%06ld", s_now, (long) ts.tv_usec);
+ read_next = 0;
+ }
+}
+
+int extract_stats(char *dump_file, int proto, int diagnostic_type, char *protocol)
+{
+ libtrace_t *trace = NULL;
+ libtrace_packet_t *packet = NULL;
+ read_next = 1;
+ packet = trace_create_packet();
+ if (packet == NULL) {
+ perror("Creating libtrace packet");
+ libtrace_cleanup(trace, packet);
+ return 1;
+ }
+
+ trace = trace_create(dump_file);
+ if (!trace) {
+ return -1;
+ }
+
+ if (trace_is_err(trace)) {
+ trace_perror(trace,"Opening trace file");
+ libtrace_cleanup(trace, packet);
+ return 1;
+ }
+
+ if (trace_start(trace) == -1) {
+ trace_perror(trace,"Starting trace");
+ libtrace_cleanup(trace, packet);
+ return 1;
+ }
+ if (proto == DOWNLOAD_DIAGNOSTIC_HTTP && diagnostic_type == DOWNLOAD_DIAGNOSTIC)
+ {
+ while (trace_read_packet(trace,packet)>0 && read_next == 1) {
+ http_download_per_packet(packet);
+ continue;
+ }
+ set_download_stats(protocol);
+ }
+ else if (proto == DOWNLOAD_DIAGNOSTIC_FTP && diagnostic_type == DOWNLOAD_DIAGNOSTIC)
+ {
+ while (trace_read_packet(trace,packet)>0 && read_next == 1) {
+ ftp_download_per_packet(packet);
+ continue;
+ }
+ set_download_stats(protocol);
+ }
+ else if (proto == DOWNLOAD_DIAGNOSTIC_HTTP && diagnostic_type == UPLOAD_DIAGNOSTIC)
+ {
+ while (trace_read_packet(trace,packet)>0 && read_next == 1) {
+ http_upload_per_packet(packet);
+ continue;
+ }
+ set_upload_stats(protocol);
+ }
+ else
+ {
+ while (trace_read_packet(trace,packet)>0 && read_next == 1) {
+ ftp_upload_per_packet(packet);
+ continue;
+ }
+ set_upload_stats(protocol);
+ }
+ libtrace_cleanup(trace, packet);
+ return 0;
+}
+
+int get_default_gateway_device( char **gw )
+{
+ FILE *f;
+ char line[100], *p, *c, *saveptr;
+
+ f = fopen("/proc/net/route" , "r");
+ if (f != NULL)
+ {
+ while(fgets(line , 100 , f))
+ {
+ p = strtok_r(line, " \t", &saveptr);
+ c = strtok_r(NULL, " \t", &saveptr);
+ if(p!=NULL && c!=NULL)
+ {
+ if(strcmp(c, "00000000") == 0)
+ {
+ dmasprintf(gw, "%s", p);
+ fclose(f);
+ return 0;
+ }
+ }
+ }
+ fclose(f);
+ }
+ return -1;
+}
+
+int start_upload_download_diagnostic(int diagnostic_type)
+{
+ char *url = NULL;
+ char *interface = NULL;
+ char *size = NULL;
+ int error;
+ char *status;
+
+ if (diagnostic_type == DOWNLOAD_DIAGNOSTIC) {
+ dmuci_get_varstate_string("cwmp", "@downloaddiagnostic[0]", "url", &url);
+ dmuci_get_varstate_string("cwmp", "@downloaddiagnostic[0]", "device", &interface);
+ }
+ else {
+ dmuci_get_varstate_string("cwmp", "@uploaddiagnostic[0]", "url", &url);
+ dmuci_get_varstate_string("cwmp", "@uploaddiagnostic[0]", "TestFileLength", &size);
+ dmuci_get_varstate_string("cwmp", "@uploaddiagnostic[0]", "device", &interface);
+ }
+
+ if ( interface == NULL || interface[0] == '\0' )
+ {
+ error = get_default_gateway_device(&interface);
+ if (error == -1)
+ return -1;
+ }
+ if (diagnostic_type == DOWNLOAD_DIAGNOSTIC)
+ {
+ //Free uci_varstate_ctx
+ end_uci_varstate_ctx();
+
+ dmcmd("/bin/sh", 5, DOWNLOAD_DIAGNOSTIC_PATH, "run", "usp", url, interface);
+
+ //Allocate uci_varstate_ctx
+ init_uci_varstate_ctx();
+
+ dmuci_get_varstate_string("cwmp", "@downloaddiagnostic[0]", "url", &url);
+ dmuci_get_varstate_string("cwmp", "@downloaddiagnostic[0]", "DiagnosticState", &status);
+ if (status && strcmp(status, "Completed") == 0)
+ {
+ init_download_stats();
+ if(strncmp(url,DOWNLOAD_UPLOAD_PROTOCOL_HTTP,strlen(DOWNLOAD_UPLOAD_PROTOCOL_HTTP)) == 0)
+ extract_stats(DOWNLOAD_DUMP_FILE, DOWNLOAD_DIAGNOSTIC_HTTP, DOWNLOAD_DIAGNOSTIC, "usp");
+ if(strncmp(url,DOWNLOAD_UPLOAD_PROTOCOL_FTP,strlen(DOWNLOAD_UPLOAD_PROTOCOL_FTP)) == 0)
+ extract_stats(DOWNLOAD_DUMP_FILE, DOWNLOAD_DIAGNOSTIC_FTP, DOWNLOAD_DIAGNOSTIC, "usp");
+ }
+ else if (status && strncmp(status, "Error_", strlen("Error_")) == 0)
+ return -1;
+ }
+ else
+ {
+ //Free uci_varstate_ctx
+ end_uci_varstate_ctx();
+
+ dmcmd("/bin/sh", 6, UPLOAD_DIAGNOSTIC_PATH, "run", "usp", url, interface, size);
+
+ //Allocate uci_varstate_ctx
+ init_uci_varstate_ctx();
+
+ dmuci_get_varstate_string("cwmp", "@uploaddiagnostic[0]", "url", &url);
+ dmuci_get_varstate_string("cwmp", "@uploaddiagnostic[0]", "DiagnosticState", &status);
+ if (status && strcmp(status, "Completed") == 0)
+ {
+ init_upload_stats();
+ if(strncmp(url,DOWNLOAD_UPLOAD_PROTOCOL_HTTP,strlen(DOWNLOAD_UPLOAD_PROTOCOL_HTTP)) == 0)
+ extract_stats(UPLOAD_DUMP_FILE, DOWNLOAD_DIAGNOSTIC_HTTP, UPLOAD_DIAGNOSTIC, "usp");
+ if(strncmp(url,DOWNLOAD_UPLOAD_PROTOCOL_FTP,strlen(DOWNLOAD_UPLOAD_PROTOCOL_FTP)) == 0)
+ extract_stats(UPLOAD_DUMP_FILE, DOWNLOAD_DIAGNOSTIC_FTP, UPLOAD_DIAGNOSTIC, "usp");
+ }
+ else if (status && strncmp(status, "Error_", strlen("Error_")) == 0)
+ return -1;
+ }
+ return 0;
+}
diff --git a/dmdiagnostics.h b/dmdiagnostics.h
new file mode 100644
index 00000000..e4684bb6
--- /dev/null
+++ b/dmdiagnostics.h
@@ -0,0 +1,79 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB
+ * Author: Amin Ben Ramdhane
+ *
+ */
+
+#ifndef __DMDIAGNOSTICS_H__
+#define __DMDIAGNOSTICS_H__
+
+#define DOWNLOAD_UPLOAD_PROTOCOL_HTTP "http://"
+#define DOWNLOAD_UPLOAD_PROTOCOL_FTP "ftp://"
+#define default_date_format "AAAA-MM-JJTHH:MM:SS.000000Z"
+#define default_date_size sizeof(default_date_format) + 1
+#define FTP_SIZE_RESPONSE "213"
+#define FTP_PASV_RESPONSE "227 Entering Passive"
+#define FTP_TRANSFERT_COMPLETE "226 Transfer"
+#define FTP_RETR_REQUEST "RETR"
+#define FTP_STOR_REQUEST "STOR"
+
+struct download_diag
+{
+ char romtime[default_date_size];
+ char bomtime[default_date_size];
+ char eomtime[default_date_size];
+ int test_bytes_received;
+ unsigned long total_bytes_received;
+ char tcpopenrequesttime[default_date_size];
+ char tcpopenresponsetime[default_date_size];
+ int tmp;
+ int first_data;
+ uint16_t ip_len;
+ uint32_t ack_seq;
+ uint32_t random_seq;
+ uint32_t get_ack;
+ uint32_t ftp_syn;
+};
+
+struct upload_diagnostic_stats
+{
+ char romtime[default_date_size];
+ char bomtime[default_date_size];
+ char eomtime[default_date_size];
+ unsigned long total_bytes_sent;
+ char tcpopenrequesttime[default_date_size];
+ char tcpopenresponsetime[default_date_size];
+ int tmp;
+ int first_data;
+ uint16_t ip_len;
+ uint32_t ack_seq;
+ uint32_t random_seq;
+ uint32_t get_ack;
+ uint32_t ftp_syn;
+};
+
+
+enum download_diagnostic_protocol {
+ DOWNLOAD_DIAGNOSTIC_HTTP = 1,
+ DOWNLOAD_DIAGNOSTIC_FTP
+};
+
+enum diagnostic_type {
+ DOWNLOAD_DIAGNOSTIC = 1,
+ UPLOAD_DIAGNOSTIC
+};
+
+char *get_param_diagnostics(char *diag, char *option);
+void set_param_diagnostics(char *diag, char *option, char *value);
+void init_download_stats(void);
+void init_upload_stats(void);
+int extract_stats(char *dump_file, int proto, int diagnostic_type, char *protocol);
+int get_default_gateway_device( char **gw );
+int start_upload_download_diagnostic(int diagnostic_type);
+
+#endif
diff --git a/dmentry.c b/dmentry.c
new file mode 100644
index 00000000..a3ccd7b2
--- /dev/null
+++ b/dmentry.c
@@ -0,0 +1,1989 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2015 Inteno Broadband Technology AB
+ * Author MOHAMED Kallel
+ * Author Imen Bhiri
+ * Author Feten Besbes
+ *
+ */
+
+#include "dmcwmp.h"
+#include "dmubus.h"
+#include "dmuci.h"
+#include "dmentry.h"
+#include "device.h"
+#include "wepkey.h"
+#include
+#include
+#include
+#include "dmcommon.h"
+#include "dmoperate.h"
+
+LIST_HEAD(head_package_change);
+unsigned char dmcli_timetrack = 0;
+unsigned char dmcli_evaluatetest = 0;
+
+static void print_dm_help(void)
+{
+ printf("Usage:\n");
+ printf(" get_value [param]\n");
+ printf(" set_value [ ] .... [ ]\n");
+ printf(" get_name \n");
+ printf(" get_notification [param]\n");
+ printf(" set_notification [ ] ....[ ]\n");
+ printf(" add_obj \n");
+ printf(" del_obj \n");
+ printf(" inform\n");
+#ifdef BBF_TR064
+ printf(" upnp_get_values [param]\n");
+ printf(" upnp_get_selected_values [param]\n");
+ printf(" upnp_get_instances \n");
+ printf(" upnp_get_supported_parameters \n");
+ printf(" upnp_set_values [ ] .... [ ]\n");
+ printf(" upnp_get_attributes \n");
+ printf(" upnp_set_attributes .... [ \n");
+ printf(" upnp_add_instance [ ] [ ] .... [ ]\n");
+ printf(" upnp_delete_instance \n");
+ printf(" upnp_get_acldata \n");
+ printf(" upnp_init_state_variables\n");
+ printf(" upnp_get_supported_parameters_update\n");
+ printf(" upnp_get_supported_datamodel_update\n");
+ printf(" upnp_get_configuration_update\n");
+ printf(" upnp_get_current_configuration_version\n");
+ printf(" upnp_get_attribute_values_update\n");
+ printf(" upnp_load_enabled_parametrs_track\n");
+ printf(" upnp_get_enabled_parametrs_alarm\n");
+ printf(" upnp_get_enabled_parametrs_event\n");
+ printf(" upnp_get_enabled_parametrs_version\n");
+ printf(" upnp_check_changed_parametrs_alarm\n");
+ printf(" upnp_check_changed_parametrs_event\n");
+ printf(" upnp_check_changed_parametrs_version\n");
+#endif
+ printf(" external_command [arg 1] [arg 2] ... [arg N]\n");
+ printf(" exit\n");
+}
+
+static int dm_ctx_init_custom(struct dmctx *ctx, unsigned int dm_type, unsigned int amd_version, unsigned int instance_mode, int custom)
+{
+#ifdef BBF_TR064
+ UPNP_SUPPORTED_DM *tUPNPSupportedDM = NULL;
+#endif
+ if (custom == CTX_INIT_ALL) {
+ memset(&dmubus_ctx, 0, sizeof(struct dmubus_ctx));
+ INIT_LIST_HEAD(&dmubus_ctx.obj_head);
+ uci_ctx = uci_alloc_context();
+ uci_varstate_ctx = uci_alloc_context();
+ DMUCI_INIT(icwmpd);
+ }
+ INIT_LIST_HEAD(&ctx->list_parameter);
+ INIT_LIST_HEAD(&ctx->set_list_tmp);
+ INIT_LIST_HEAD(&ctx->list_fault_param);
+ ctx->amd_version = amd_version;
+ ctx->instance_mode = instance_mode;
+ ctx->dm_type = dm_type;
+#ifdef BBF_TR064
+ if (dm_type == DM_UPNP) {
+ if(uci_data_model == DM_TR098) {
+ strcpy(dmroot, DMROOT_UPNP);
+ dm_delim = DMDELIM_UPNP;
+ ctx->dm_entryobj = tEntry098ObjUPNP;
+ ctx->user_mask = upnp_in_user_mask;
+ }
+ else {
+ strcpy(dmroot, DMROOT_UPNP);
+ dm_delim = DMDELIM_UPNP;
+ ctx->dm_entryobj = tEntry181ObjUPNP;
+ ctx->user_mask = upnp_in_user_mask;
+ }
+ }
+ else {
+ if(uci_data_model == DM_TR098) {
+ strcpy(dmroot, "InternetGatewayDevice");
+ dm_delim = DMDELIM_CWMP;
+ ctx->dm_entryobj = tEntry098Obj;
+ }
+ else {
+ strcpy(dmroot, "Device");
+ dm_delim = DMDELIM_CWMP;
+ ctx->dm_entryobj = tEntry181Obj;
+ }
+ }
+
+ if(uci_data_model == DM_TR098) {
+ tUPNPSupportedDM = malloc(tr98_size);
+ if (tUPNPSupportedDM == NULL) {
+ exit(0);
+ }
+ tUPNPSupportedDM = tUPNPSupportedDM_098;
+ }
+ else {
+ tUPNPSupportedDM = malloc(tr181_size);
+ if (tUPNPSupportedDM == NULL) {
+ exit(0);
+ }
+ tUPNPSupportedDM = tUPNPSupportedDM_181;
+ }
+
+ free(tUPNPSupportedDM);
+#else
+ strcpy(dmroot, "Device");
+ dm_delim = DMDELIM_CWMP;
+ ctx->dm_entryobj = tEntry181Obj;
+#endif
+ return 0;
+}
+
+static int dm_ctx_clean_custom(struct dmctx *ctx, int custom)
+{
+ free_all_list_parameter(ctx);
+ free_all_set_list_tmp(ctx);
+ free_all_list_fault_param(ctx);
+ DMFREE(ctx->addobj_instance);
+ if (custom == CTX_INIT_ALL) {
+ if (uci_ctx) uci_free_context(uci_ctx);
+ uci_ctx = NULL;
+ if (uci_varstate_ctx) uci_free_context(uci_varstate_ctx);
+ uci_varstate_ctx = NULL;
+ DMUCI_EXIT(icwmpd);
+ dmubus_ctx_free(&dmubus_ctx);
+ dmcleanmem();
+ }
+ return 0;
+}
+
+int dm_ctx_init(struct dmctx *ctx, unsigned int dm_type, unsigned int amd_version, unsigned int instance_mode)
+{
+ dm_ctx_init_custom(ctx, dm_type, amd_version, instance_mode, CTX_INIT_ALL);
+ return 0;
+}
+
+int dm_ctx_clean(struct dmctx *ctx)
+{
+ dm_ctx_clean_custom(ctx, CTX_INIT_ALL);
+ return 0;
+}
+
+int dm_ctx_init_sub(struct dmctx *ctx, unsigned int dm_type, unsigned int amd_version, unsigned int instance_mode)
+{
+ dm_ctx_init_custom(ctx, dm_type, amd_version, instance_mode, CTX_INIT_SUB);
+ return 0;
+}
+
+int dm_ctx_clean_sub(struct dmctx *ctx)
+{
+ dm_ctx_clean_custom(ctx, CTX_INIT_SUB);
+ return 0;
+}
+
+void dmentry_instance_lookup_inparam(struct dmctx *ctx)
+{
+ char *pch, *spch, *in_param;
+ in_param = dmstrdup(ctx->in_param);
+ int i = 0;
+ char pat[2] = {0};
+ *pat = dm_delim;
+ for (pch = strtok_r(in_param, pat, &spch); pch != NULL; pch = strtok_r(NULL, pat, &spch)) {
+ if (pch[0]== '[') {
+ ctx->alias_register |= (1 << i);
+ i++;
+ } else if (isdigit(pch[0])) {
+ i++;
+ }
+ }
+ dmfree(in_param);
+ ctx->nbrof_instance = i;
+}
+
+int dm_entry_param_method(struct dmctx *ctx, int cmd, char *inparam, char *arg1, char *arg2)
+{
+ int fault = 0;
+ bool setnotif = true;
+ bool alarm = false, event = false;
+ int err, err2;
+
+ if (!inparam) inparam = "";
+ ctx->in_param = inparam;
+ dmentry_instance_lookup_inparam(ctx);
+ ctx->stop = false;
+ switch(cmd) {
+ case CMD_GET_VALUE:
+ if (ctx->dm_type == DM_CWMP && ctx->in_param[0] == dm_delim && strlen(ctx->in_param) == 1)
+ fault = FAULT_9005;
+ else
+ fault = dm_entry_get_value(ctx);
+ break;
+ case CMD_GET_NAME:
+ if (ctx->dm_type == DM_CWMP && ctx->in_param[0] == dm_delim && strlen(ctx->in_param) == 1)
+ fault = FAULT_9005;
+ else if (arg1 && string_to_bool(arg1, &ctx->nextlevel) == 0){
+ fault = dm_entry_get_name(ctx);
+ } else {
+ fault = FAULT_9003;
+ }
+ break;
+ case CMD_GET_NOTIFICATION:
+ if (ctx->dm_type == DM_CWMP && ctx->in_param[0] == dm_delim && strlen(ctx->in_param) == 1)
+ fault = FAULT_9005;
+ else
+ fault = dm_entry_get_notification(ctx);
+ break;
+ case CMD_SET_VALUE:
+ ctx->in_value = arg1 ? arg1 : "";
+ ctx->setaction = VALUECHECK;
+ fault = dm_entry_set_value(ctx);
+ if (fault)
+ add_list_fault_param(ctx, ctx->in_param, fault);
+ break;
+ case CMD_SET_NOTIFICATION:
+ if (arg2)
+ err = string_to_bool(arg2, &setnotif);
+ if (!err && arg1 &&
+ (strcmp(arg1, "0") == 0 ||
+ strcmp(arg1, "1") == 0 ||
+ strcmp(arg1, "2") == 0 ||
+ strcmp(arg1, "3") == 0 ||
+ strcmp(arg1, "4") == 0 ||
+ strcmp(arg1, "5") == 0 ||
+ strcmp(arg1, "6") == 0)) {
+ ctx->in_notification = arg1;
+ ctx->setaction = VALUECHECK;
+ ctx->notification_change = setnotif;
+ fault = dm_entry_set_notification(ctx);
+ } else {
+ fault = FAULT_9003;
+ }
+ break;
+ case CMD_INFORM:
+ dm_entry_inform(ctx);
+ break;
+ case CMD_ADD_OBJECT:
+ fault = dm_entry_add_object(ctx);
+ if (!fault) {
+ dmuci_set_value("cwmp", "acs", "ParameterKey", arg1 ? arg1 : "");
+ dmuci_change_packages(&head_package_change);
+ }
+ break;
+ case CMD_DEL_OBJECT:
+ fault = dm_entry_delete_object(ctx);
+ if (!fault) {
+ dmuci_set_value("cwmp", "acs", "ParameterKey", arg1 ? arg1 : "");
+ dmuci_change_packages(&head_package_change);
+ }
+ break;
+ case CMD_USP_OPERATE:
+ ctx->in_value = arg1 ? arg1 : "";
+ fault = dm_entry_operate(ctx);
+ break;
+#ifdef BBF_TR064
+ case CMD_UPNP_GET_SUPPORTED_PARAMETERS:
+ ctx->depth = atoi(arg1);
+ fault = dm_entry_upnp_get_supported_parameters(ctx);
+ break;
+ case CMD_UPNP_GET_VALUES:
+ fault = dm_entry_upnp_get_values(ctx);
+ break;
+ case CMD_UPNP_GET_SELECTED_VALUES:
+ fault = dm_entry_upnp_get_selected_values(ctx);
+ break;
+ case CMD_UPNP_GET_INSTANCES:
+ ctx->depth = atoi(arg1);
+ fault = dm_entry_upnp_get_instances(ctx);
+ break;
+ case CMD_UPNP_SET_VALUES:
+ ctx->in_value = arg1 ? arg1 : "";
+ ctx->setaction = VALUECHECK;
+ fault = dm_entry_upnp_set_values(ctx);
+ break;
+ case CMD_UPNP_SET_ATTRIBUTES:
+ if (arg1)
+ err = string_to_bool(arg1, &event);
+ if (arg2)
+ err2 = string_to_bool(arg2, &alarm);
+ if (!err && !err2) {
+ ctx->dmparam_flags |= (event) ? DM_PARAM_EVENT_ON_CHANGE : 0;
+ ctx->dmparam_flags |= (alarm) ? DM_PARAM_ALARAM_ON_CHANGE : 0;
+ ctx->setaction = VALUECHECK;
+ fault = dm_entry_upnp_set_attributes(ctx);
+ } else {
+ fault = FAULT_9003;
+ }
+ break;
+ case CMD_UPNP_GET_ATTRIBUTES:
+ fault = dm_entry_upnp_get_attributes(ctx);
+ break;
+ case CMD_UPNP_DEL_INSTANCE:
+ fault = dm_entry_upnp_delete_instance(ctx);
+ if (!fault) {
+ dmuci_change_packages(&head_package_change);
+ }
+ break;
+ case CMD_UPNP_ADD_INSTANCE:
+ fault = dm_entry_upnp_add_instance(ctx);
+ if (!fault) {
+ dmuci_change_packages(&head_package_change);
+ }
+ break;
+ case CMD_UPNP_GET_ACLDATA:
+ fault = dm_entry_upnp_get_acl_data(ctx);
+ break;
+#endif
+ }
+ dmuci_commit();
+ return fault;
+}
+
+int dm_entry_apply(struct dmctx *ctx, int cmd, char *arg1, char *arg2)
+{
+ int fault = 0;
+ struct set_tmp *n, *p;
+
+ switch(cmd) {
+ case CMD_SET_VALUE:
+ ctx->setaction = VALUESET;
+ list_for_each_entry_safe(n, p, &ctx->set_list_tmp, list) {
+ ctx->in_param = n->name;
+ ctx->in_value = n->value ? n->value : "";
+ ctx->stop = false;
+ fault = dm_entry_set_value(ctx);
+ if (fault) break;
+ }
+ if (fault) {
+ //Should not happen
+ dmuci_revert();
+ add_list_fault_param(ctx, ctx->in_param, fault);
+ } else {
+ dmuci_set_value("cwmp", "acs", "ParameterKey", arg1 ? arg1 : "");
+ dmuci_change_packages(&head_package_change);
+ dmuci_commit();
+ }
+ free_all_set_list_tmp(ctx);
+ break;
+ case CMD_SET_NOTIFICATION:
+ ctx->setaction = VALUESET;
+ list_for_each_entry_safe(n, p, &ctx->set_list_tmp, list) {
+ ctx->in_param = n->name;
+ ctx->in_notification = n->value ? n->value : "0";
+ ctx->stop = false;
+ fault = dm_entry_set_notification(ctx);
+ if (fault) break;
+ }
+ if (fault) {
+ //Should not happen
+ dmuci_revert();
+ } else {
+ dmuci_commit();
+ }
+ free_all_set_list_tmp(ctx);
+ break;
+#ifdef BBF_TR064
+ case CMD_UPNP_SET_VALUES:
+ ctx->setaction = VALUESET;
+ list_for_each_entry_safe(n, p, &ctx->set_list_tmp, list) {
+ ctx->in_param = n->name;
+ ctx->in_value = n->value ? n->value : "";
+ ctx->stop = false;
+ fault = dm_entry_upnp_set_values(ctx);
+ if (fault) break;
+ }
+ if (fault) {
+ //Should not happen
+ dmuci_revert();
+ } else {
+ dmuci_change_packages(&head_package_change);
+ dmuci_commit();
+ }
+ break;
+ case CMD_UPNP_SET_ATTRIBUTES:
+ ctx->setaction = VALUESET;
+ list_for_each_entry_safe(n, p, &ctx->set_list_tmp, list) {
+ ctx->in_param = n->name;
+ ctx->dmparam_flags = n->flags;
+ ctx->stop = false;
+ fault = dm_entry_upnp_set_attributes(ctx);
+ if (fault) break;
+ }
+ if (fault) {
+ //Should not happen
+ dmuci_revert();
+ } else {
+ dmuci_commit();
+ }
+ free_all_set_list_tmp(ctx);
+ break;
+#endif
+ }
+ return fault;
+}
+
+int dm_entry_load_enabled_notify(unsigned int dm_type, unsigned int amd_version, int instance_mode)
+{
+ struct dmctx dmctx = {0};
+
+ dm_ctx_init(&dmctx, dm_type, amd_version, instance_mode);
+ dmctx.in_param = "";
+
+ free_all_list_enabled_lwnotify();
+ dm_entry_enabled_notify_check_value_change(&dmctx);
+ dm_entry_enabled_notify(&dmctx);
+
+ dm_ctx_clean(&dmctx);
+ return 0;
+}
+
+int dm_entry_reload_enabled_notify(unsigned int dm_type, unsigned int amd_version, int instance_mode)
+{
+ struct dmctx dmctx = {0};
+
+ dm_ctx_init(&dmctx, dm_type, amd_version, instance_mode);
+ dmctx.in_param = "";
+
+ free_all_list_enabled_lwnotify();
+ dm_entry_enabled_notify(&dmctx);
+
+ dm_ctx_clean(&dmctx);
+ return 0;
+}
+
+int adm_entry_get_linker_param(struct dmctx *ctx, char *param, char *linker, char **value)
+{
+ struct dmctx dmctx = {0};
+
+ dm_ctx_init_sub(&dmctx, ctx->dm_type, ctx->amd_version, ctx->instance_mode);
+ dmctx.in_param = param ? param : "";
+ dmctx.linker = linker;
+
+ dm_entry_get_linker(&dmctx);
+ *value = dmctx.linker_param;
+ dm_ctx_clean_sub(&dmctx);
+ return 0;
+}
+
+int adm_entry_get_linker_value(struct dmctx *ctx, char *param, char **value)
+{
+ struct dmctx dmctx = {0};
+ *value = NULL;
+
+ if (!param || param[0] == '\0') {
+ return 0;
+ }
+
+ dm_ctx_init_sub(&dmctx, ctx->dm_type, ctx->amd_version, ctx->instance_mode);
+ dmctx.in_param = param;
+
+ dm_entry_get_linker_value(&dmctx);
+ *value = dmctx.linker;
+
+ dm_ctx_clean_sub(&dmctx);
+ return 0;
+}
+
+#ifdef BBF_TR064
+/****************************************
+ * upnp load tracked on change parameters
+ ****************************************/
+
+int dm_entry_upnp_load_tracked_parameters(struct dmctx *dmctx)
+{
+
+ dmctx->in_param = "";
+
+ free_all_list_upnp_param_track(&list_upnp_enabled_onevent);
+ free_all_list_upnp_param_track(&list_upnp_enabled_onalarm);
+ free_all_list_upnp_param_track(&list_upnp_enabled_version);
+ dm_entry_upnp_tracked_parameters(dmctx);
+
+ return 0;
+}
+
+/*********************************************
+ * upnp check on change params (event & alarm)
+ *********************************************/
+
+void dm_upnp_update_enabled_track_value(struct dm_upnp_enabled_track *p, char *new_value)
+{
+ free(p->value); // Should be free and not dmfree
+ p->value = strdup(new_value);
+}
+
+void dm_upnp_update_enabled_track_key(struct dm_upnp_enabled_track *p, char *key)
+{
+ free(p->key); // Should be free and not dmfree
+ p->key = strdup(key);
+}
+
+int dm_entry_upnp_check_onchange_param(struct dmctx *pctx, struct list_head *enabled_head, struct list_head *changed_head)
+{
+ struct dmctx dmctx = {0};
+ struct dm_upnp_enabled_track *p;
+ struct dm_parameter *dm_parameter;
+ int fault;
+ int ischange = 0;
+ char *all_instances;
+
+ list_for_each_entry(p, enabled_head, list) {
+ dm_ctx_init_sub(&dmctx, pctx->dm_type, pctx->amd_version, pctx->instance_mode);
+ dmctx.user_mask = DM_SUPERADMIN_MASK;
+ if (p->isobj) {
+ all_instances = dm_entry_get_all_instance_numbers(&dmctx, p->name);
+ if (all_instances && strcmp(all_instances, p->value) != 0) {
+ dm_upnp_update_enabled_track_value(p, all_instances);
+ add_list_upnp_param_track(&dmctx, changed_head, p->name, "1", all_instances, 1);
+ ischange = 1;
+ }
+ }
+ else {
+ fault = dm_entry_param_method(&dmctx, CMD_UPNP_GET_VALUES, p->name, NULL, NULL);
+ if (!fault && dmctx.list_parameter.next != &dmctx.list_parameter) {
+ dm_parameter = list_entry(dmctx.list_parameter.next, struct dm_parameter, list);
+ if (strcmp(dm_parameter->data, p->value) != 0) {
+ dm_upnp_update_enabled_track_value(p, dm_parameter->data);
+ add_list_upnp_param_track(&dmctx, changed_head, p->name, "1", dm_parameter->data, 0);
+ ischange = 1;
+ }
+ }
+ free_all_list_parameter(&dmctx);
+ }
+ dm_ctx_clean_sub(&dmctx);
+ memset(&dmctx, 0, sizeof(struct dmctx));
+ }
+ return ischange;
+}
+
+int dm_entry_upnp_check_alarmonchange_param(struct dmctx *dmctx)
+{
+ int r;
+ r = dm_entry_upnp_check_onchange_param(dmctx, &list_upnp_enabled_onalarm, &list_upnp_changed_onalarm);
+ return r;
+}
+
+int dm_entry_upnp_check_eventonchange_param(struct dmctx *dmctx)
+{
+ int r;
+ r = dm_entry_upnp_check_onchange_param(dmctx, &list_upnp_enabled_onevent, &list_upnp_changed_onevent);
+ return r;
+}
+
+/*************************************
+ * upnp check on change version params
+ *************************************/
+
+int dm_entry_upnp_update_version_configuration(struct dmctx *dmctx)
+{
+ char *v, *tmp, buf[32];
+ struct uci_section *s;
+ int version;
+
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "current_configuration_version", &v);
+ version = atoi(v);
+ version++;
+
+ dmuci_get_section_type(UPNP_CFG, "@dm[0]", &tmp);
+ if (!tmp || tmp[0] == '\0') {
+ dmuci_add_section(UPNP_CFG, "dm", &s, &tmp);
+ }
+ sprintf(buf, "%d", version);
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "current_configuration_version", buf);
+ sprintf(buf, "%ld", time(NULL));
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "current_configuration_epochtime", buf);
+
+ return version;
+}
+
+int dm_entry_upnp_check_versiononchange_param(struct dmctx *pctx)
+{
+ struct dmctx dmctx = {0};
+ struct dm_upnp_enabled_track *p;
+ struct dm_parameter *dm_parameter;
+ int version, fault;
+ int ischange;
+ char *all_instances;
+
+ list_for_each_entry(p, &list_upnp_enabled_version, list) {
+ ischange = 0;
+ dm_ctx_init_sub(&dmctx, pctx->dm_type, pctx->amd_version, pctx->instance_mode);
+ dmctx.user_mask = DM_SUPERADMIN_MASK;
+ if (p->isobj) {
+ all_instances = dm_entry_get_all_instance_numbers(&dmctx, p->name);
+ if (strcmp(all_instances, p->value) != 0) {
+ dm_upnp_update_enabled_track_value(p, all_instances);
+ add_list_upnp_param_track(&dmctx, &list_upnp_changed_version, p->name, "1", all_instances, 1);
+ ischange = 1;
+ }
+ }
+ else {
+ fault = dm_entry_param_method(&dmctx, CMD_UPNP_GET_VALUES, p->name, NULL, NULL);
+ if (!fault && dmctx.list_parameter.next != &dmctx.list_parameter) {
+ dm_parameter = list_entry(dmctx.list_parameter.next, struct dm_parameter, list);
+ if (strcmp(dm_parameter->data, p->value) != 0) {
+ dm_upnp_update_enabled_track_value(p, dm_parameter->data);
+ add_list_upnp_param_track(&dmctx, &list_upnp_changed_version, p->name, p->key, dm_parameter->data, 0);
+ ischange = 1;
+ }
+ }
+ free_all_list_parameter(&dmctx);
+ }
+ if (ischange)
+ {
+ char buf[32];
+ char *tmp;
+ struct uci_section *s = NULL;
+ version = dm_entry_upnp_update_version_configuration(&dmctx);
+ sprintf(buf, "%d", version);
+ if (p->key) {
+ dmuci_set_value(UPNP_CFG, p->key, "version", buf);
+ }
+ else {
+ dmuci_add_section(UPNP_CFG, "parameter_version", &s, &tmp);
+ if (s != NULL) {
+ dmuci_set_value_by_section(s, "version", buf);
+ dmuci_set_value_by_section(s, "parameter", p->name);
+ dm_upnp_update_enabled_track_key(p, section_name(s));
+ }
+ }
+ dmuci_commit();
+ }
+ dm_ctx_clean_sub(&dmctx);
+ memset(&dmctx, 0, sizeof(struct dmctx));
+ }
+ return ischange;
+}
+
+/* *************************
+ * UPNP init state variables
+ * ************************/
+int upnp_state_variables_init(struct dmctx *dmctx)
+{
+ char *v, *tmp;
+ struct uci_section *s;
+ char buf[32];
+ int n;
+
+ dmuci_get_section_type(UPNP_CFG, "@dm[0]", &tmp);
+ if (!tmp || tmp[0] == '\0') {
+ dmuci_add_section(UPNP_CFG, "dm", &s, &tmp);
+ }
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "supported_datamodel_version", &v);
+ n = atoi(v);
+ if (n != UPNP_SUPPORTED_DATAMODEL_VERSION) {
+ sprintf(buf, "%d", UPNP_SUPPORTED_DATAMODEL_VERSION);
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "supported_datamodel_version", buf);
+ sprintf(buf, "%ld", time(NULL));
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "supported_datamodel_epochtime", buf);
+ }
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "supported_parameters_version", &v);
+ n = atoi(v);
+ if (n != UPNP_SUPPORTED_PARAMETERS_VERSION) {
+ sprintf(buf, "%d", UPNP_SUPPORTED_PARAMETERS_VERSION);
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "supported_parameters_version", buf);
+ sprintf(buf, "%ld", time(NULL));
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "supported_parameters_epochtime", buf);
+ }
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "current_configuration_version", &v);
+ if (*v == '\0') {
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "current_configuration_version", "0");
+ sprintf(buf, "%ld", time(NULL));
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "current_configuration_epochtime", buf);
+ }
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "attribute_values_version", &v);
+ if (*v == '\0') {
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "attribute_values_version", "0");
+ sprintf(buf, "%ld", time(NULL));
+ dmuci_set_value(UPNP_CFG, "@dm[0]", "attribute_values_epochtime", buf);
+ }
+
+ dmuci_commit();
+ return 0;
+}
+
+/* ************************************
+ * UPNP get supported parameters update
+ * ***********************************/
+
+int dm_entry_upnp_get_supported_parameters_update(struct dmctx *dmctx, char **value)
+{
+ static char csv[128] = "";
+ char *v;
+ time_t time_value;
+
+ *value = csv;
+
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "supported_parameters_epochtime", &v);
+ if (v[0] != '0' && v[0] != '\0') {
+ time_value = atoi(v);
+ char s_now[sizeof "AAAA-MM-JJTHH:MM:SS.000Z"];
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S.000Z", localtime(&time_value));
+ sprintf(csv, "%d,%s", UPNP_SUPPORTED_PARAMETERS_VERSION, s_now);
+ }
+
+ return 0;
+}
+
+/* ************************************
+ * UPNP get supported_datamodel update
+ * ***********************************/
+
+int dm_entry_upnp_get_supported_datamodel_update(struct dmctx *dmctx, char **value)
+{
+ static char csv[128] = "";
+ char *v;
+ time_t time_value;
+
+ *value = csv;
+
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "supported_datamodel_epochtime", &v);
+ if (v[0] != '0' && v[0] != '\0') {
+ time_value = atoi(v);
+ char s_now[sizeof "AAAA-MM-JJTHH:MM:SS.000Z"];
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S.000Z", localtime(&time_value));
+ sprintf(csv, "%d,%s", UPNP_SUPPORTED_DATAMODEL_VERSION, s_now);
+ }
+
+ return 0;
+}
+
+/* ********************************
+ * UPNP get attribute values update
+ * ********************************/
+
+int dm_entry_upnp_get_attribute_values_update(struct dmctx *dmctx, char **value)
+{
+ static char csv[128] = "";
+ char *v, *s;
+ time_t time_value;
+
+ *value = csv;
+
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "attribute_values_epochtime", &v);
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "attribute_values_version", &s);
+ if (v[0] != '0' && v[0] != '\0' && s[0] != '\0') {
+ time_value = atoi(v);
+ char s_now[sizeof "AAAA-MM-JJTHH:MM:SS.000Z"];
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S.000Z", localtime(&time_value));
+ sprintf(csv, "%s,%s", s, s_now);
+ }
+
+ return 0;
+}
+
+/* ********************************
+ * UPNP get configuration update
+ * ********************************/
+
+int dm_entry_upnp_get_configuration_update(struct dmctx *dmctx, char **value)
+{
+ static char csv[128] = "";
+ char *v, *s;
+ time_t time_value;
+
+ *value = csv;
+
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "current_configuration_epochtime", &v);
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "current_configuration_version", &s);
+ if (v[0] != '\0' && s[0] != '\0') {
+ time_value = atoi(v);
+ char s_now[sizeof "AAAA-MM-JJTHH:MM:SS.000Z"];
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S.000Z", localtime(&time_value));
+ sprintf(csv, "%s,%s", s, s_now);
+ }
+
+ return 0;
+}
+
+/* **************************************
+ * UPNP get current configuration version
+ * *************************************/
+
+int dm_entry_upnp_get_current_configuration_version(struct dmctx *dmctx, char **value)
+{
+ dmuci_get_option_value_string(UPNP_CFG, "@dm[0]", "current_configuration_version", value);
+ return 0;
+}
+#endif
+/************************/
+
+int dm_entry_restart_services(void)
+{
+ struct package_change *pc;
+
+ list_for_each_entry(pc, &head_package_change, list) {
+ if(strcmp(pc->package, "cwmp") == 0)
+ continue;
+ dmubus_call_set("uci", "commit", UBUS_ARGS{{"config", pc->package, String}}, 1);
+ }
+ free_all_list_package_change(&head_package_change);
+
+ return 0;
+}
+
+void dm_apply_config(void)
+{
+ apply_end_session();
+ dm_entry_restart_services();
+}
+
+#ifdef BBF_TR064
+int dm_entry_upnp_restart_services(void)
+{
+ struct package_change *pc;
+
+ list_for_each_entry(pc, &head_package_change, list) {
+ dmubus_call_set("uci", "commit", UBUS_ARGS{{"config", pc->package}}, 1);
+ }
+ free_all_list_package_change(&head_package_change);
+
+ return 0;
+}
+
+void dm_upnp_apply_config(void)
+{
+ apply_end_session();
+ dm_entry_upnp_restart_services();
+}
+
+int cli_output_dm_upnp_variable_state(struct dmctx *dmctx, int cmd, char *variable)
+{
+ switch (cmd) {
+ case CMD_UPNP_GET_CONFIGURATION_UPDATE:
+ fprintf (stdout, "{ \"ConfigurationUpdate\": \"%s\"}\n", variable);
+ break;
+ case CMD_UPNP_GET_CURRENT_CONFIGURATION_VERSION:
+ fprintf (stdout, "{ \"CurrentConfigurationVersion\": \"%s\"}\n", variable);
+ break;
+ case CMD_UPNP_GET_SUPPORTED_DATA_MODEL_UPDATE:
+ fprintf (stdout, "{ \"SupportedDataModelsUpdate\": \"%s\"}\n", variable);
+ break;
+ case CMD_UPNP_GET_SUPPORTED_PARAMETERS_UPDATE:
+ fprintf (stdout, "{ \"SupportedParametersUpdate\": \"%s\"}\n", variable);
+ break;
+ case CMD_UPNP_GET_ATTRIBUTE_VALUES_UPDATE:
+ fprintf (stdout, "{ \"AttributeValuesUpdate\": \"%s\"}\n", variable);
+ break;
+ }
+ return 0;
+}
+#endif
+
+int cli_output_dm_result(struct dmctx *dmctx, int fault, int cmd, int out)
+{
+ struct dm_parameter *n;
+ if (!out) return 0;
+
+ if (dmctx->list_fault_param.next != &dmctx->list_fault_param) {
+ struct param_fault *p;
+ list_for_each_entry(p, &dmctx->list_fault_param, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"fault\": \"%d\" }\n", p->name, p->fault);
+ }
+ goto end;
+ }
+ if (fault) {
+ fprintf (stdout, "{ \"fault\": \"%d\" }\n", fault);
+ goto end;
+ }
+
+ switch (cmd) {
+ case CMD_ADD_OBJECT:
+ if (dmctx->addobj_instance) {
+ fprintf (stdout, "{ \"status\": \"1\", \"instance\": \"%s\" }\n", dmctx->addobj_instance);
+ } else {
+ fprintf (stdout, "{ \"fault\": \"%d\" }\n", FAULT_9002);
+ }
+ break;
+#ifdef BBF_TR064
+ case CMD_UPNP_ADD_INSTANCE:
+ if (dmctx->addobj_instance) {
+ fprintf (stdout, "{ \"status\": \"ChangesApplied\", \"instance_path\": \"%s%s%c\" }\n", dmctx->in_param, dmctx->addobj_instance, dm_delim);
+ } else {
+ fprintf (stdout, "{ \"fault\": \"%d\" }\n", FAULT_UPNP_701);
+ }
+ break;
+#endif
+ case CMD_DEL_OBJECT:
+ case CMD_SET_VALUE:
+ fprintf (stdout, "{ \"status\": \"1\" }\n");
+ break;
+
+ case CMD_SET_NOTIFICATION:
+ fprintf (stdout, "{ \"status\": \"0\" }\n");
+ break;
+
+#ifdef BBF_TR064
+ case CMD_UPNP_SET_ATTRIBUTES:
+ case CMD_UPNP_SET_VALUES:
+ case CMD_UPNP_DEL_INSTANCE:
+ fprintf (stdout, "{ \"status\": \"ChangesApplied\" }\n");
+ break;
+#endif
+
+ case CMD_GET_NAME:
+ list_for_each_entry(n, &dmctx->list_parameter, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"writable\": \"%s\" }\n", n->name, n->data);
+ }
+ break;
+ case CMD_GET_NOTIFICATION:
+ list_for_each_entry(n, &dmctx->list_parameter, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"notification\": \"%s\" }\n", n->name, n->data);
+ }
+ break;
+ case CMD_GET_VALUE:
+ case CMD_INFORM:
+ list_for_each_entry(n, &dmctx->list_parameter, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"value\": \"%s\", \"type\": \"%s\" }\n", n->name, n->data, n->type);
+ }
+ break;
+
+#ifdef BBF_TR064
+ case CMD_UPNP_GET_VALUES:
+ case CMD_UPNP_GET_SELECTED_VALUES:
+ list_for_each_entry(n, &dmctx->list_parameter, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"value\": \"%s\" }\n", n->name, n->data);
+ }
+ break;
+ case CMD_UPNP_GET_ATTRIBUTES:
+ list_for_each_entry(n, &dmctx->list_parameter, list) {
+ char alrm[32] = "", evnt[32] = "", btype[16], bversion[32] = "", *stype = NULL;
+ if (n->flags & DM_PARAM_ALARAM_ON_CHANGE)
+ strcpy(alrm, ", \"alarmOnChange\": \"1\"");
+ if (n->flags & DM_PARAM_EVENT_ON_CHANGE)
+ strcpy(evnt, ", \"eventOnChange\": \"1\"");
+ if (n->version)
+ sprintf(bversion, ", \"version\": \"%s\"", n->version);
+ switch (n->flags & NODE_DATA_ATTRIBUTE_TYPEMASK) {
+ case NODE_DATA_ATTRIBUTE_TYPEINT:
+ stype = "int";
+ break;
+ case NODE_DATA_ATTRIBUTE_TYPESTRING:
+ stype = "string";
+ break;
+ case NODE_DATA_ATTRIBUTE_TYPELONG:
+ stype = "long";
+ break;
+ case NODE_DATA_ATTRIBUTE_TYPEBOOL:
+ stype = "boolean";
+ break;
+ case NODE_DATA_ATTRIBUTE_TYPEDATETIME:
+ stype = "dateTime";
+ break;
+ case NODE_DATA_ATTRIBUTE_TYPEPTR:
+ if (n->flags & NODE_DATA_ATTRIBUTE_INSTANCE)
+ stype = "Instance";
+ else if (n->flags & NODE_DATA_ATTRIBUTE_MULTIINSTANCE)
+ stype = "MultiInstance";
+ break;
+ }
+ if (stype)
+ sprintf(btype, ", \"type\": \"%s\"", stype);
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"access\": \"%s\"%s%s%s%s}\n", n->name, n->data, btype, evnt, alrm, bversion);
+ }
+ break;
+ case CMD_UPNP_GET_INSTANCES:
+ case CMD_UPNP_GET_SUPPORTED_PARAMETERS:
+ list_for_each_entry(n, &dmctx->list_parameter, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\"}\n", n->name);
+ }
+ break;
+ case CMD_UPNP_GET_ACLDATA:
+ list_for_each_entry(n, &dmctx->list_parameter, list) {
+ char blist[64] = "";
+ char bread[64] = "";
+ char bwrite[64] = "";
+ char bfac[32] = "";
+ if (n->flags & DM_PUBLIC_LIST) {
+ strcat(blist, "Public ");
+ }
+ if (n->flags & DM_BASIC_LIST) {
+ strcat(blist, "Basic ");
+ }
+ if (n->flags & DM_XXXADMIN_LIST) {
+ strcat(blist, "xxxAdmin ");
+ }
+ if (*blist)
+ blist[strlen(blist) - 1] = '\0';
+ if (n->flags & DM_PUBLIC_READ) {
+ strcat(bread, "Public ");
+ }
+ if (n->flags & DM_BASIC_READ) {
+ strcat(bread, "Basic ");
+ }
+ if (n->flags & DM_XXXADMIN_READ) {
+ strcat(bread, "xxxAdmin ");
+ }
+ if (*bread)
+ bread[strlen(bread) - 1] = '\0';
+ if (n->flags & DM_PUBLIC_WRITE) {
+ strcat(bwrite, "Public ");
+ }
+ if (n->flags & DM_BASIC_WRITE) {
+ strcat(bwrite, "Basic ");
+ }
+ if (n->flags & DM_XXXADMIN_WRITE) {
+ strcat(bwrite, "xxxAdmin ");
+ }
+ if (*bwrite)
+ bwrite[strlen(bwrite) - 1] = '\0';
+ if (n->flags & DM_FACTORIZED)
+ sprintf(bfac, ", \"factorized\": \"1\"");
+ fprintf (stdout, "{ \"ACLDataPath\": \"%s\", \"List\": \"%s\", \"Read\": \"%s\", \"Write\": \"%s\"%s }\n", n->name, blist, bread, bwrite, bfac);
+ }
+ break;
+ case CMD_UPNP_GET_ENABLED_PARAMETRS_ALARM:
+ {
+ struct dm_upnp_enabled_track *p;
+ list_for_each_entry(p, &list_upnp_enabled_onalarm, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"value\": \"%s\", \"key\": \"%s\"}\n", p->name, p->value, p->key ? p->key : "");
+ }
+ }
+ break;
+ case CMD_UPNP_GET_ENABLED_PARAMETRS_EVENT:
+ {
+ struct dm_upnp_enabled_track *p;
+ list_for_each_entry(p, &list_upnp_enabled_onevent, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"value\": \"%s\", \"key\": \"%s\"}\n", p->name, p->value, p->key ? p->key : "");
+ }
+ }
+ break;
+ case CMD_UPNP_GET_ENABLED_PARAMETRS_VERSION:
+ {
+ struct dm_upnp_enabled_track *p;
+ list_for_each_entry(p, &list_upnp_enabled_version, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"value\": \"%s\", \"key\": \"%s\"}\n", p->name, p->value, p->key ? p->key : "");
+ }
+ }
+ break;
+ case CMD_UPNP_CHECK_CHANGED_PARAMETRS_ALARM:
+ {
+ struct dm_upnp_enabled_track *p;
+ list_for_each_entry(p, &list_upnp_changed_onalarm, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"value\": \"%s\", \"key\": \"%s\"}\n", p->name, p->value, p->key ? p->key : "");
+ }
+ }
+ break;
+ case CMD_UPNP_CHECK_CHANGED_PARAMETRS_EVENT:
+ {
+ struct dm_upnp_enabled_track *p;
+ list_for_each_entry(p, &list_upnp_changed_onevent, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"value\": \"%s\", \"key\": \"%s\"}\n", p->name, p->value, p->key ? p->key : "");
+ }
+ }
+ break;
+ case CMD_UPNP_CHECK_CHANGED_PARAMETRS_VERSION:
+ {
+ struct dm_upnp_enabled_track *p;
+ list_for_each_entry(p, &list_upnp_changed_version, list) {
+ fprintf (stdout, "{ \"parameter\": \"%s\", \"value\": \"%s\", \"key\": \"%s\"}\n", p->name, p->value, p->key ? p->key : "");
+ }
+ }
+ break;
+#endif
+ }
+end:
+ return 0;
+}
+
+static char *parse_arg_r(char *pch, char **last)
+{
+ if (pch == NULL) {
+ pch = *last;
+ }
+
+ if (pch == NULL) {
+ return NULL;
+ }
+
+ for(; *pch != '\0'; pch++)
+ {
+ if(*pch == ' ' || *pch == '\t')
+ continue;
+ if (*pch == '"')
+ {
+ char *s = strchr(++pch, '"');
+ if(s) {
+ *s = '\0';
+ *last = s + 1;
+ return pch;
+ }
+ else {
+ *last = NULL;
+ return NULL;
+ }
+ }
+ else
+ {
+ char *s = strchr(pch, ' ');
+ if(s) {
+ *s = '\0';
+ *last = s + 1;
+ }
+ else {
+ s = strchr(pch, '\t');
+ if(s) {
+ *s = '\0';
+ *last = s + 1;
+ }
+ else {
+ *last = NULL;
+ }
+ }
+
+ return pch;
+ }
+ }
+ *last = NULL;
+ return NULL;
+}
+
+static int dmentry_external_cmd(char **argv)
+{
+ int pid;
+
+ if ((pid = fork()) == -1)
+ return -1;
+
+ if (pid == 0) {
+ /* child */
+ execvp(argv[0], argv);
+ exit(ESRCH);
+
+ } else if (pid < 0)
+ return -1;
+
+ int status;
+ while (wait(&status) != pid);
+
+ return 0;
+}
+
+void dm_execute_cli_shell(int argc, char** argv, unsigned int dmtype, unsigned int amd_version, unsigned int instance_mode)
+{
+ struct dmctx cli_dmctx = {0};
+ int output = 1, dmrpc;
+ char *param, *next_level, *parameter_key, *value, *cmd;
+ int fault = 0, status = -1;
+ bool set_fault = false;
+ long ms; // Milliseconds
+ time_t s; // Seconds
+ struct timespec tstart, tend;
+ unsigned char apply_services = 0;
+
+ if (dmcli_timetrack)
+ clock_gettime(CLOCK_REALTIME, &tstart);
+
+ dm_ctx_init(&cli_dmctx, dmtype, amd_version, instance_mode);
+
+ if (argc < 4) goto invalid_arguments;
+
+ output = atoi(argv[2]);
+ cmd = argv[3];
+
+ check_create_dmmap_package(DMMAP);
+ /* GET NAME */
+ if (strcmp(cmd, "get_name") == 0) {
+ if (argc < 6) goto invalid_arguments;
+ dmrpc = CMD_GET_NAME;
+ param = argv[4];
+ next_level =argv[5];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_GET_NAME, param, next_level, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_GET_NAME, output);
+ }
+ /* GET VALUE */
+ else if (strcmp(cmd, "get_value") == 0) {
+ if (argc < 5) goto invalid_arguments;
+ dmrpc = CMD_GET_VALUE;
+ param = argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_GET_VALUE, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_GET_VALUE, output);
+ }
+ /* GET NOTIFICATION */
+ else if (strcmp(cmd, "get_notification") == 0) {
+ if (argc < 5) goto invalid_arguments;
+ dmrpc = CMD_GET_NOTIFICATION;
+ param = argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_GET_NOTIFICATION, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_GET_NOTIFICATION, output);
+ }
+ /* SET VALUE */
+ else if (strcmp(cmd, "set_value") == 0) {
+ if (argc < 7 || (argc % 2) == 0) goto invalid_arguments;
+ dmrpc = CMD_SET_VALUE;
+ int i;
+ for (i = 5; i < argc; i+=2) {
+ param = argv[i];
+ value = argv[i+1];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_SET_VALUE, param, value, NULL);
+ if (fault) set_fault = true;
+ }
+ parameter_key = argv[4];
+ if (!set_fault) {
+ apply_services = 1;
+ fault = dm_entry_apply(&cli_dmctx, CMD_SET_VALUE, parameter_key, NULL);
+ }
+ cli_output_dm_result(&cli_dmctx, fault, CMD_SET_VALUE, output);
+ }
+ /* SET NOTIFICATION */
+ else if (strcmp(cmd, "set_notification") == 0) {
+ if (argc < 6 || (argc % 2) != 0) goto invalid_arguments;
+ dmrpc = CMD_SET_NOTIFICATION;
+ int i;
+ for (i = 4; i < argc; i+=2) {
+ param = argv[i];
+ value = argv[i+1];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_SET_NOTIFICATION, param, value, "1");
+ if (fault) set_fault = true;
+ }
+ if(!set_fault) {
+ fault = dm_entry_apply(&cli_dmctx, CMD_SET_NOTIFICATION, NULL, NULL);
+ }
+ cli_output_dm_result(&cli_dmctx, fault, CMD_SET_NOTIFICATION, output);
+ }
+ /* ADD OBJECT */
+ else if (strcmp(cmd, "add_object") == 0) {
+ if (argc < 6) goto invalid_arguments;
+ dmrpc = CMD_ADD_OBJECT;
+ param =argv[5];
+ parameter_key =argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_ADD_OBJECT, param, parameter_key, NULL);
+ if (!fault)
+ apply_services = 1;
+ cli_output_dm_result(&cli_dmctx, fault, CMD_ADD_OBJECT, output);
+ }
+ /* DEL OBJECT */
+ else if (strcmp(cmd, "delete_object") == 0) {
+ dmrpc = CMD_DEL_OBJECT;
+ if (argc < 6) goto invalid_arguments;
+ param =argv[5];
+ parameter_key =argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_DEL_OBJECT, param, parameter_key, NULL);
+ if (!fault)
+ apply_services = 1;
+ cli_output_dm_result(&cli_dmctx, fault, CMD_DEL_OBJECT, output);
+ }
+ /* INFORM */
+ else if (strcmp(cmd, "inform") == 0) {
+ dmrpc = CMD_INFORM;
+ fault = dm_entry_param_method(&cli_dmctx, CMD_INFORM, "", NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_INFORM, output);
+ }
+#ifdef BBF_TR064
+ /* UPNP GET VALUES */
+ else if (strcmp(cmd, "upnp_get_values") == 0) {
+ if (argc < 5) goto invalid_arguments;
+ dmrpc = CMD_UPNP_GET_VALUES;
+ param = argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_VALUES, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_VALUES, output);
+ }
+ /* UPNP GET SELECTED VALUES */
+ else if (strcmp(cmd, "upnp_get_selected_values") == 0) {
+ if (argc < 5) goto invalid_arguments;
+ dmrpc = CMD_UPNP_GET_SELECTED_VALUES;
+ param = argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_SELECTED_VALUES, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_SELECTED_VALUES, output);
+ }
+ /* UPNP GET INSTANCES */
+ else if (strcmp(cmd, "upnp_get_instances") == 0) {
+ if (argc < 6) goto invalid_arguments;
+ dmrpc = CMD_UPNP_GET_INSTANCES;
+ param = argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_INSTANCES, param, argv[5], NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_INSTANCES, output);
+ }
+ /* UPNP GET SUPPORTED PARAMETERS */
+ else if (strcmp(cmd, "upnp_get_supported_parameters") == 0) {
+ if (argc < 6) goto invalid_arguments;
+ dmrpc = CMD_UPNP_GET_SUPPORTED_PARAMETERS;
+ param = argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_SUPPORTED_PARAMETERS, param, argv[5], NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_SUPPORTED_PARAMETERS, output);
+ }
+ /* UPNP SET VALUE */
+ else if (strcmp(cmd, "upnp_set_values") == 0) {
+ if (argc < 6 || (argc % 2) == 1) goto invalid_arguments;
+ dmrpc = CMD_UPNP_SET_VALUES;
+ int i;
+ for (i = 4; i < argc; i+=2) {
+ param = argv[i];
+ value = argv[i+1];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_SET_VALUES, param, value, NULL);
+ if (fault) break;
+ }
+ if (!fault) {
+ apply_services = 1;
+ fault = dm_entry_apply(&cli_dmctx, CMD_UPNP_SET_VALUES, NULL, NULL);
+ }
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_SET_VALUES, output);
+ }
+ /* UPNP DEL INSTANCE */
+ else if (strcmp(cmd, "upnp_delete_instance") == 0) {
+ if (argc < 5) goto invalid_arguments;
+ dmrpc = CMD_UPNP_DEL_INSTANCE;
+ param =argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_DEL_INSTANCE, param, NULL, NULL);
+ if (!fault)
+ apply_services = 1;
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_DEL_INSTANCE, output);
+ }
+ /* UPNP ADD INSTANCE */
+ else if (strcmp(cmd, "upnp_add_instance") == 0) {
+ char buf[256];
+ dmrpc = CMD_UPNP_ADD_INSTANCE;
+ int i;
+ if (argc < 5 || (argc % 2) == 0) goto invalid_arguments;
+ param = argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_ADD_INSTANCE, param, NULL, NULL);
+ if (!fault && cli_dmctx.addobj_instance) {
+ struct dmctx set_dmctx = {0};
+ apply_services = 1;
+ if (argc >= 6) {
+ dm_ctx_init_sub(&set_dmctx, dmtype, amd_version, instance_mode);
+ for (i = 5; i < argc; i+=2) {
+ sprintf(buf, "%s%s%c%s", param, cli_dmctx.addobj_instance, dm_delim, argv[i]); // concatenate obj path + instance + sub param
+ value = argv[i+1];
+ dm_entry_param_method(&set_dmctx, CMD_UPNP_SET_VALUES, buf, value, NULL);
+ }
+ dm_entry_apply(&set_dmctx, CMD_UPNP_SET_VALUES, NULL, NULL);
+ dm_ctx_clean_sub(&set_dmctx);
+ }
+ }
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_ADD_INSTANCE, output);
+ }
+ /* UPNP GET ATTRIBUTES */
+ else if (strcmp(cmd, "upnp_get_attributes") == 0) {
+ if (argc < 5) goto invalid_arguments;
+ dmrpc = CMD_UPNP_GET_ATTRIBUTES;
+ param = argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_ATTRIBUTES, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_ATTRIBUTES, output);
+ }
+ /* UPNP SET ATTRIBUTES */
+ else if (strcmp(cmd, "upnp_set_attributes") == 0) {
+ if (argc < 7 || (argc % 3) != 1) goto invalid_arguments;
+ dmrpc = CMD_UPNP_SET_ATTRIBUTES;
+ int i;
+ for (i = 4; i < argc; i+=3) {
+ param = argv[i];
+ char *evnt = argv[i+1];
+ char *alrm = argv[i+2];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_SET_ATTRIBUTES, param, evnt, alrm);
+ if (fault) break;
+ }
+ if(!fault) {
+ fault = dm_entry_apply(&cli_dmctx, CMD_UPNP_SET_ATTRIBUTES, NULL, NULL);
+ }
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_SET_ATTRIBUTES, output);
+ }
+ /* UPNP GET ACLDATA */
+ else if (strcmp(cmd, "upnp_get_acldata") == 0) {
+ if (argc < 5) goto invalid_arguments;
+ dmrpc = CMD_UPNP_GET_ACLDATA;
+ param = argv[4];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_ACLDATA, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_ACLDATA, output);
+ }
+ else if (strcmp(cmd, "upnp_init_state_variables") == 0) {
+ dmrpc = CMD_UPNP_INIT_STATE_VARIABLES;
+ upnp_state_variables_init(&cli_dmctx);
+ }
+ else if (strcmp(cmd, "upnp_get_supported_parameters_update") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_SUPPORTED_PARAMETERS_UPDATE;
+ dm_entry_upnp_get_supported_parameters_update(&cli_dmctx, &var);
+ cli_output_dm_upnp_variable_state(&cli_dmctx, CMD_UPNP_GET_SUPPORTED_PARAMETERS_UPDATE, var);
+ }
+ else if (strcmp(cmd, "upnp_get_supported_datamodel_update") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_SUPPORTED_DATA_MODEL_UPDATE;
+ dm_entry_upnp_get_supported_datamodel_update(&cli_dmctx, &var);
+ cli_output_dm_upnp_variable_state(&cli_dmctx, CMD_UPNP_GET_SUPPORTED_DATA_MODEL_UPDATE, var);
+ }
+ else if (strcmp(cmd, "upnp_get_configuration_update") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_CONFIGURATION_UPDATE;
+ dm_entry_upnp_get_configuration_update(&cli_dmctx, &var);
+ cli_output_dm_upnp_variable_state(&cli_dmctx, CMD_UPNP_GET_CONFIGURATION_UPDATE, var);
+ }
+ else if (strcmp(cmd, "upnp_get_current_configuration_version") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_CURRENT_CONFIGURATION_VERSION;
+ dm_entry_upnp_get_current_configuration_version(&cli_dmctx, &var);
+ cli_output_dm_upnp_variable_state(&cli_dmctx, CMD_UPNP_GET_CURRENT_CONFIGURATION_VERSION, var);
+ }
+ else if (strcmp(cmd, "upnp_get_attribute_values_update") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_ATTRIBUTE_VALUES_UPDATE;
+ dm_entry_upnp_get_attribute_values_update(&cli_dmctx, &var);
+ cli_output_dm_upnp_variable_state(&cli_dmctx, CMD_UPNP_GET_ATTRIBUTE_VALUES_UPDATE, var);
+ }
+ else if (strcmp(cmd, "upnp_load_enabled_parametrs_track") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_LOAD_ENABLED_PARAMETRS_TRACK;
+ dm_entry_upnp_load_tracked_parameters(&cli_dmctx);
+ }
+ else if (strcmp(cmd, "upnp_get_enabled_parametrs_alarm") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_ENABLED_PARAMETRS_ALARM;
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_ENABLED_PARAMETRS_ALARM, output);
+ }
+ else if (strcmp(cmd, "upnp_get_enabled_parametrs_event") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_ENABLED_PARAMETRS_EVENT;
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_ENABLED_PARAMETRS_EVENT, output);
+ }
+ else if (strcmp(cmd, "upnp_get_enabled_parametrs_version") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_ENABLED_PARAMETRS_VERSION;
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_ENABLED_PARAMETRS_VERSION, output);
+ }
+ else if (strcmp(cmd, "upnp_check_changed_parametrs_alarm") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_CHECK_CHANGED_PARAMETRS_ALARM;
+ dm_entry_upnp_check_alarmonchange_param(&cli_dmctx);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_CHECK_CHANGED_PARAMETRS_ALARM, output);
+ }
+ else if (strcmp(cmd, "upnp_check_changed_parametrs_event") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_CHECK_CHANGED_PARAMETRS_EVENT;
+ dm_entry_upnp_check_eventonchange_param(&cli_dmctx);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_CHECK_CHANGED_PARAMETRS_EVENT, output);
+ }
+ else if (strcmp(cmd, "upnp_check_changed_parametrs_version") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_CHECK_CHANGED_PARAMETRS_VERSION;
+ dm_entry_upnp_check_versiononchange_param(&cli_dmctx);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_CHECK_CHANGED_PARAMETRS_VERSION, output);
+ }
+#endif
+ else {
+ goto invalid_arguments;
+ }
+
+ dm_ctx_clean(&cli_dmctx);
+ if (apply_services) {
+ dm_apply_config();
+ }
+
+ if (!fault) {
+ int ualarm, uversion, uevent;
+#ifdef BBF_TR064
+ switch (dmrpc) {
+ case CMD_UPNP_SET_VALUES:
+ case CMD_UPNP_DEL_INSTANCE:
+ case CMD_UPNP_ADD_INSTANCE:
+ DM_ENTRY_UPNP_CHECK_CHANGES(ualarm, uevent, uversion);
+ break;
+ case CMD_UPNP_SET_ATTRIBUTES:
+ DM_ENTRY_UPNP_LOAD_TRACKED_PARAMETERS();
+ break;
+ }
+#endif
+ }
+
+ if (dmcli_timetrack) {
+ clock_gettime(CLOCK_REALTIME, &tend);
+ s = tend.tv_sec - tstart.tv_sec;
+ ms = (tend.tv_nsec - tstart.tv_nsec) / 1.0e6; // Convert nanoseconds to milliseconds
+ if (ms < 0) {
+ ms = 1000 + ms;
+ s--;
+ }
+ fprintf(stdout, "-----------------------------\n");
+ fprintf(stdout, "End: %ld s : %ld ms\n", (long)s, ms);
+ fprintf(stdout, "-----------------------------\n");
+ fflush(stdout);
+ }
+ return;
+
+invalid_arguments:
+ dm_ctx_clean(&cli_dmctx);
+ fprintf(stdout, "Invalid arguments!\n");;
+}
+
+int dmentry_cli(int argc, char *argv[], unsigned int dmtype, unsigned int amd_version, unsigned int instance_mode)
+{
+ struct dmctx cli_dmctx = {0};
+ int fault = 0, set_fault = 0;
+ int i, dmrpc;
+ char *param;
+ char *value;
+ char *parameter_key;
+ char *notifset;
+ unsigned char apply_services = 0;
+
+ if (argc < 3) {
+ fprintf(stderr, "Wrong arguments!\n");
+ return -1;
+ }
+
+ check_create_dmmap_package(DMMAP);
+ dm_ctx_init(&cli_dmctx, dmtype, amd_version, instance_mode);
+ if (strcmp(argv[2], "get_value") == 0) {
+ char *param = "";
+ dmrpc = CMD_GET_VALUE;
+ if (argc >= 4)
+ param = argv[3];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_GET_VALUE, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_GET_VALUE, 1);
+ }
+ else if (strcmp(argv[2], "get_name") == 0) {
+ if (argc < 5)
+ goto invalid_arguments;
+ dmrpc = CMD_GET_NAME;
+ fault = dm_entry_param_method(&cli_dmctx, CMD_GET_NAME, argv[3], argv[4], NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_GET_NAME, 1);
+ }
+ else if (strcmp(argv[2], "get_notification") == 0) {
+ char *param = "";
+ dmrpc = CMD_GET_NOTIFICATION;
+ if (argc >= 4)
+ param = argv[3];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_GET_NOTIFICATION, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_GET_NOTIFICATION, 1);
+ }
+ else if (strcmp(argv[2], "set_value") == 0) {
+ if (argc < 6 || (argc % 2) != 0)
+ goto invalid_arguments;
+
+ dmrpc = CMD_SET_VALUE;
+ for (i = 4; i < argc; i+=2) {
+ param = argv[i];
+ value = argv[i+1];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_SET_VALUE, param, value, NULL);
+ if (fault) set_fault = true;
+ }
+ parameter_key = argv[3];
+ if (!set_fault) {
+ apply_services = 1;
+ fault = dm_entry_apply(&cli_dmctx, CMD_SET_VALUE, parameter_key, NULL);
+ }
+ cli_output_dm_result(&cli_dmctx, fault, CMD_SET_VALUE, 1);
+ }
+ else if (strcmp(argv[2], "set_notification") == 0) {
+ if (argc < 6 || (argc % 3) != 0)
+ goto invalid_arguments;
+ dmrpc = CMD_SET_NOTIFICATION;
+ for (i=3; i= 4)
+ param = argv[3];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_VALUES, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_VALUES, 1);
+ }
+ else if (strcmp(argv[2], "upnp_get_selected_values") == 0) {
+ char *param = "";
+ dmrpc = CMD_UPNP_GET_SELECTED_VALUES;
+ if (argc >= 4)
+ param = argv[3];
+ param = argv[3];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_SELECTED_VALUES, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_SELECTED_VALUES, 1);
+ }
+ else if (strcmp(argv[2], "upnp_get_supported_parameters") == 0) {
+ if (argc < 5)
+ goto invalid_arguments;
+ dmrpc = CMD_UPNP_GET_SUPPORTED_PARAMETERS;
+ param = argv[3];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_SUPPORTED_PARAMETERS, param, argv[4], NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_SUPPORTED_PARAMETERS, 1);
+ }
+ else if (strcmp(argv[2], "upnp_get_instances") == 0) {
+ if (argc < 5)
+ goto invalid_arguments;
+ dmrpc = CMD_UPNP_GET_INSTANCES;
+ param = argv[3];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_INSTANCES, param, argv[4], NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_INSTANCES, 1);
+ }
+ else if (strcmp(argv[2], "upnp_set_values") == 0) {
+ if (argc < 5 || (argc % 2) == 0)
+ goto invalid_arguments;
+
+ dmrpc = CMD_UPNP_SET_VALUES;
+ for (i = 3; i < argc; i+=2) {
+ param = argv[i];
+ value = argv[i+1];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_SET_VALUES, param, value, NULL);
+ if (fault) break;
+ }
+ if (!fault) {
+ apply_services = 1;
+ fault = dm_entry_apply(&cli_dmctx, CMD_UPNP_SET_VALUES, parameter_key, NULL);
+ }
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_SET_VALUES, 1);
+ }
+ else if (strcmp(argv[2], "upnp_get_attributes") == 0) {
+ if (argc < 4) goto invalid_arguments;
+ dmrpc = CMD_UPNP_GET_ATTRIBUTES;
+ param = argv[3];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_ATTRIBUTES, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_ATTRIBUTES, 1);
+ }
+ else if (strcmp(argv[2], "upnp_set_attributes") == 0) {
+ if (argc < 6 || (argc % 3) != 0) goto invalid_arguments;
+ dmrpc = CMD_UPNP_SET_ATTRIBUTES;
+ int i;
+ for (i = 3; i < argc; i+=3) {
+ param = argv[i];
+ char *evnt = argv[i+1];
+ char *alrm = argv[i+2];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_SET_ATTRIBUTES, param, evnt, alrm);
+ if (fault) break;
+ }
+ if(!fault) {
+ fault = dm_entry_apply(&cli_dmctx, CMD_UPNP_SET_ATTRIBUTES, NULL, NULL);
+ }
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_SET_ATTRIBUTES, 1);
+ }
+ else if (strcmp(argv[2], "upnp_add_instance") == 0) {
+ char buf[256];
+ int i;
+ if (argc < 4 || (argc % 2) != 0)
+ goto invalid_arguments;
+ dmrpc = CMD_UPNP_ADD_INSTANCE;
+ param = argv[3];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_ADD_INSTANCE, param, NULL, NULL);
+ if (!fault && cli_dmctx.addobj_instance) {
+ struct dmctx set_dmctx = {0};
+ apply_services = 1;
+ if (argc >= 5) {
+ dm_ctx_init_sub(&set_dmctx, dmtype, amd_version, instance_mode);
+ for (i = 4; i < argc; i+=2) {
+ sprintf(buf, "%s%s%c%s", param, cli_dmctx.addobj_instance, dm_delim, argv[i]); // concatenate obj path + instance + sub param
+ value = argv[i+1];
+ dm_entry_param_method(&set_dmctx, CMD_UPNP_SET_VALUES, buf, value, NULL);
+ }
+ dm_entry_apply(&set_dmctx, CMD_UPNP_SET_VALUES, NULL, NULL);
+ dm_ctx_clean_sub(&set_dmctx);
+ }
+ }
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_ADD_INSTANCE, 1);
+ }
+ else if (strcmp(argv[2], "upnp_delete_instance") == 0) {
+ if (argc < 4)
+ goto invalid_arguments;
+ dmrpc = CMD_UPNP_DEL_INSTANCE;
+ param =argv[3];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_DEL_INSTANCE, param, NULL, NULL);
+ if (!fault)
+ apply_services = 1;
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_DEL_INSTANCE, 1);
+ }
+ else if (strcmp(argv[2], "upnp_get_acldata") == 0) {
+ if (argc < 4) goto invalid_arguments;
+ dmrpc = CMD_UPNP_GET_ACLDATA;
+ param = argv[3];
+ fault = dm_entry_param_method(&cli_dmctx, CMD_UPNP_GET_ACLDATA, param, NULL, NULL);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_ACLDATA, 1);
+ }
+ else if (strcmp(argv[2], "upnp_init_state_variables") == 0) {
+ dmrpc = CMD_UPNP_INIT_STATE_VARIABLES;
+ upnp_state_variables_init(&cli_dmctx);
+ }
+ else if (strcmp(argv[2], "upnp_get_supported_parameters_update") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_SUPPORTED_PARAMETERS_UPDATE;
+ dm_entry_upnp_get_supported_parameters_update(&cli_dmctx, &var);
+ cli_output_dm_upnp_variable_state(&cli_dmctx, CMD_UPNP_GET_SUPPORTED_PARAMETERS_UPDATE, var);
+ }
+ else if (strcmp(argv[2], "upnp_get_supported_datamodel_update") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_SUPPORTED_DATA_MODEL_UPDATE;
+ dm_entry_upnp_get_supported_datamodel_update(&cli_dmctx, &var);
+ cli_output_dm_upnp_variable_state(&cli_dmctx, CMD_UPNP_GET_SUPPORTED_DATA_MODEL_UPDATE, var);
+ }
+ else if (strcmp(argv[2], "upnp_get_configuration_update") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_CONFIGURATION_UPDATE;
+ dm_entry_upnp_get_configuration_update(&cli_dmctx, &var);
+ cli_output_dm_upnp_variable_state(&cli_dmctx, CMD_UPNP_GET_CONFIGURATION_UPDATE, var);
+ }
+ else if (strcmp(argv[2], "upnp_get_current_configuration_version") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_CURRENT_CONFIGURATION_VERSION;
+ dm_entry_upnp_get_current_configuration_version(&cli_dmctx, &var);
+ cli_output_dm_upnp_variable_state(&cli_dmctx, CMD_UPNP_GET_CURRENT_CONFIGURATION_VERSION, var);
+ }
+ else if (strcmp(argv[2], "upnp_get_attribute_values_update") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_ATTRIBUTE_VALUES_UPDATE;
+ dm_entry_upnp_get_attribute_values_update(&cli_dmctx, &var);
+ cli_output_dm_upnp_variable_state(&cli_dmctx, CMD_UPNP_GET_ATTRIBUTE_VALUES_UPDATE, var);
+ }
+ else if (strcmp(argv[2], "upnp_load_enabled_parametrs_track") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_LOAD_ENABLED_PARAMETRS_TRACK;
+ dm_entry_upnp_load_tracked_parameters(&cli_dmctx);
+ }
+ else if (strcmp(argv[2], "upnp_get_enabled_parametrs_alarm") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_ENABLED_PARAMETRS_ALARM;
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_ENABLED_PARAMETRS_ALARM, 1);
+ }
+ else if (strcmp(argv[2], "upnp_get_enabled_parametrs_event") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_ENABLED_PARAMETRS_EVENT;
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_ENABLED_PARAMETRS_EVENT, 1);
+ }
+ else if (strcmp(argv[2], "upnp_get_enabled_parametrs_version") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_GET_ENABLED_PARAMETRS_VERSION;
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_GET_ENABLED_PARAMETRS_VERSION, 1);
+ }
+ else if (strcmp(argv[2], "upnp_check_changed_parametrs_alarm") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_CHECK_CHANGED_PARAMETRS_ALARM;
+ dm_entry_upnp_check_alarmonchange_param(&cli_dmctx);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_CHECK_CHANGED_PARAMETRS_ALARM, 1);
+ }
+ else if (strcmp(argv[2], "upnp_check_changed_parametrs_event") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_CHECK_CHANGED_PARAMETRS_EVENT;
+ dm_entry_upnp_check_eventonchange_param(&cli_dmctx);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_CHECK_CHANGED_PARAMETRS_EVENT, 1);
+ }
+ else if (strcmp(argv[2], "upnp_check_changed_parametrs_version") == 0) {
+ char *var;
+ dmrpc = CMD_UPNP_CHECK_CHANGED_PARAMETRS_VERSION;
+ dm_entry_upnp_check_versiononchange_param(&cli_dmctx);
+ cli_output_dm_result(&cli_dmctx, fault, CMD_UPNP_CHECK_CHANGED_PARAMETRS_VERSION, 1);
+ }
+#endif
+ else {
+ goto invalid_arguments;
+ }
+
+ dm_ctx_clean(&cli_dmctx);
+ if (apply_services) {
+ dm_apply_config();
+ }
+
+ if (!fault) {
+ int ualarm, uversion, uevent;
+#ifdef BBF_TR064
+ switch (dmrpc) {
+ case CMD_UPNP_SET_VALUES:
+ case CMD_UPNP_DEL_INSTANCE:
+ case CMD_UPNP_ADD_INSTANCE:
+ DM_ENTRY_UPNP_CHECK_CHANGES(ualarm, uevent, uversion);
+ break;
+ case CMD_UPNP_SET_ATTRIBUTES:
+ DM_ENTRY_UPNP_LOAD_TRACKED_PARAMETERS();
+ break;
+ }
+#endif
+ }
+
+ return 0;
+
+invalid_arguments:
+ dm_ctx_clean(&cli_dmctx);
+ fprintf(stdout, "Invalid arguments!\n");
+ return -1;
+}
+
+void dm_execute_cli_command(char *file, unsigned int dmtype, unsigned int amd_version, unsigned int instance_mode)
+{
+ FILE *fp;
+ char *argv[64];
+ char buf[2048], dbuf[2048];
+ char *pch, *pchr;
+ int argc, len, i=0;
+ long ms; // Milliseconds
+ time_t s; // Seconds
+ struct timespec tstart, tend;
+
+ if (file) {
+ fp = fopen(file, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "ERROR: Wrong file!\n");
+ fflush(stderr);
+ return;
+ }
+ }
+ else {
+ fp = stdin;
+ }
+
+ printf("%s", DM_PROMPT" "); fflush(stdout);
+
+ while (fgets (buf , 2048 , fp) != NULL) {
+ if (dmcli_evaluatetest)
+ argc = 1;
+ else
+ argc = 2;
+
+ len = strlen(buf);
+ if (len>0 && buf[len-1] == '\n') {
+ buf[len-1] = '\0';
+ }
+ if (strcasecmp(buf, "exit") == 0) {
+ if (file) {
+ fprintf(stdout, "%s\n", buf);
+ fflush(stdout);
+ }
+ return;
+ }
+ if (strcasecmp(buf, "help") == 0) {
+ if (file) {
+ fprintf(stdout, "%s\n", buf);
+ fflush(stdout);
+ }
+ print_dm_help();
+ printf(DM_PROMPT" "); fflush(stdout);
+ continue;
+ }
+
+ i++;
+
+ strcpy(dbuf, buf);
+ for (pch = parse_arg_r(buf, &pchr); pch != NULL; pch = parse_arg_r(NULL, &pchr)) {
+ if(argc < 3 && (pch[0] == '#' || pch[0] == '\0'))
+ break;
+ if (*pch == '"')
+ pch++;
+ len = strlen(pch);
+ if (len>0 && pch[len-1] == '"')
+ pch[len-1] = '\0';
+ argv[argc++] = pch;
+ }
+ if (file) {
+ if (!pch || pch[0] != '#') {
+ fprintf(stdout, "%s\n", dbuf);
+ fflush(stdout);
+ }
+ else {
+ fprintf(stdout, "\n");
+ fflush(stdout);
+ }
+ }
+ if (argc>2) {
+ char testref[32] = "";
+ if (dmcli_evaluatetest)
+ sprintf(testref, "Ref: %s - ", argv[1]);
+ if (dmcli_timetrack || dmcli_evaluatetest) {
+ fprintf(stdout, "-----------------------------\n");
+ fprintf(stdout, "[%s%04d] %s\n", testref, i, dbuf);
+ fprintf(stdout, "-----------------------------\n");
+ fflush(stdout);
+ clock_gettime(CLOCK_REALTIME, &tstart);
+ }
+ if (dmentry_cli(argc, argv, dmtype, amd_version, instance_mode) == 0) {
+ if (dmcli_timetrack || dmcli_evaluatetest) {
+ clock_gettime(CLOCK_REALTIME, &tend);
+ s = tend.tv_sec - tstart.tv_sec;
+ ms = (tend.tv_nsec - tstart.tv_nsec) / 1.0e6; // Convert nanoseconds to milliseconds
+ if (ms < 0) {
+ ms = 1000 + ms;
+ s--;
+ }
+ fprintf(stdout, "-----------------------------\n");
+ fprintf(stdout, "%sEnd: %ld s : %ld ms\n", testref, (long)s, ms);
+ fprintf(stdout, "-----------------------------\n");
+ fflush(stdout);
+ }
+ }
+ else {
+ fprintf(stdout, "Type help for help\n");
+ fflush(stdout);
+ }
+ }
+ printf(DM_PROMPT" "); fflush(stdout);
+ }
+ if (file) {
+ fclose(fp);
+ fprintf(stdout, "\n");
+ fflush(stdout);
+ }
+}
+
+int cli_output_wepkey64(char strk64[4][11])
+{
+ fprintf(stdout, "%s\n%s\n%s\n%s\n", strk64[0], strk64[1], strk64[2], strk64[3]);
+ return 0;
+}
+
+int cli_output_wepkey128(char strk128[27])
+{
+ fprintf(stdout, "%s\n", strk128);
+ return 0;
+}
+
+void wepkey_cli(int argc, char** argv)
+{
+ if (argc < 4) goto invalid_arguments;
+
+ char *strength = argv[2];
+ char *passphrase = argv[3];
+
+ if (!strength || !passphrase || passphrase[0] == '\0')
+ goto invalid_arguments;
+
+ if (strcmp(strength, "64") == 0) {
+ char strk64[4][11];
+ wepkey64(passphrase, strk64);
+ cli_output_wepkey64(strk64);
+ }
+ else if (strcmp(strength, "128") == 0) {
+ char strk128[27];
+ wepkey128(passphrase, strk128);
+ cli_output_wepkey128(strk128);
+ }
+ else {
+ goto invalid_arguments;
+ }
+ return;
+
+invalid_arguments:
+ fprintf(stdout, "Invalid arguments!\n");;
+}
+
diff --git a/dmentry.h b/dmentry.h
new file mode 100644
index 00000000..2194cfa7
--- /dev/null
+++ b/dmentry.h
@@ -0,0 +1,77 @@
+#ifndef __DMENTRY_H__
+#define __DMENTRY_H__
+
+#include "dmcwmp.h"
+extern struct list_head head_package_change;
+extern unsigned char dmcli_timetrack;
+extern unsigned char dmcli_evaluatetest;
+
+enum ctx_init_enum {
+ CTX_INIT_ALL,
+ CTX_INIT_SUB
+};
+
+int dm_ctx_init(struct dmctx *ctx, unsigned int dm_type, unsigned int amd_version, unsigned int instance_mode);
+int dm_ctx_init_sub(struct dmctx *ctx, unsigned int dm_type, unsigned int amd_version, unsigned int instance_mode);
+int dm_entry_param_method(struct dmctx *ctx, int cmd, char *inparam, char *arg1, char *arg2);
+int dm_entry_apply(struct dmctx *ctx, int cmd, char *arg1, char *arg2);
+int dm_entry_load_enabled_notify(unsigned int dm_type, unsigned int amd_version, int instance_mode);
+int dm_entry_reload_enabled_notify(unsigned int dm_type, unsigned int amd_version, int instance_mode);
+int adm_entry_get_linker_param(struct dmctx *ctx, char *param, char *linker, char **value);
+int adm_entry_get_linker_value(struct dmctx *ctx, char *param, char **value);
+int dm_entry_restart_services(void);
+#ifdef BBF_TR064
+int dm_entry_upnp_restart_services(void);
+void dm_upnp_apply_config(void);
+int dm_entry_upnp_check_alarmonchange_param(struct dmctx *dmctx);
+int dm_entry_upnp_check_eventonchange_param(struct dmctx *dmctx);
+int dm_entry_upnp_check_versiononchange_param(struct dmctx *pctx);
+int dm_entry_upnp_load_tracked_parameters(struct dmctx *dmctx);
+int dm_entry_upnp_get_supported_parameters_update(struct dmctx *dmctx, char **value);
+int dm_entry_upnp_get_supported_datamodel_update(struct dmctx *dmctx, char **value);
+int dm_entry_upnp_get_attribute_values_update(struct dmctx *dmctx, char **value);
+int dm_entry_upnp_get_configuration_update(struct dmctx *dmctx, char **value);
+int dm_entry_upnp_get_current_configuration_version(struct dmctx *dmctx, char **value);
+#endif
+
+int dm_ctx_clean(struct dmctx *ctx);
+int dm_ctx_clean_sub(struct dmctx *ctx);
+void dm_execute_cli_shell(int argc, char** argv, unsigned int dmtype, unsigned int amd_version, unsigned int instance_mode);
+void dm_execute_cli_command(char *file, unsigned int dmtype, unsigned int amd_version, unsigned int instance_mode);
+void wepkey_cli(int argc, char** argv);
+void dmentry_instance_lookup_inparam(struct dmctx *ctx);
+
+#ifdef BBF_TR064
+#define DM_ENTRY_UPNP_CHECK_CHANGES(ALARM, EVENT, VERSION) \
+ do { \
+ struct dmctx dmctx_chg = {0}; \
+ dm_ctx_init(&dmctx_chg, DM_UPNP, AMD_2, INSTANCE_MODE_NUMBER); \
+ ALARM = dm_entry_upnp_check_alarmonchange_param(&dmctx_chg); \
+ dm_ctx_clean(&dmctx_chg); \
+ memset(&dmctx_chg, 0, sizeof(struct dmctx)); \
+ dm_ctx_init(&dmctx_chg, DM_UPNP, AMD_2, INSTANCE_MODE_NUMBER); \
+ EVENT = dm_entry_upnp_check_eventonchange_param(&dmctx_chg); \
+ dm_ctx_clean(&dmctx_chg); \
+ memset(&dmctx_chg, 0, sizeof(struct dmctx)); \
+ dm_ctx_init(&dmctx_chg, DM_UPNP, AMD_2, INSTANCE_MODE_NUMBER); \
+ VERSION = dm_entry_upnp_check_versiononchange_param(&dmctx_chg); \
+ dm_ctx_clean(&dmctx_chg); \
+ } while(0)
+
+#define DM_ENTRY_UPNP_FREE_ALL_CHECK_CHANGES() \
+ do { \
+ free_all_list_upnp_param_track(&list_upnp_changed_onevent); \
+ free_all_list_upnp_param_track(&list_upnp_changed_onalarm); \
+ free_all_list_upnp_param_track(&list_upnp_changed_version); \
+ } while(0)
+
+#define DM_ENTRY_UPNP_LOAD_TRACKED_PARAMETERS() \
+ do { \
+ struct dmctx dmctx_trk = {0}; \
+ dm_ctx_init(&dmctx_trk, DM_UPNP, AMD_2, INSTANCE_MODE_NUMBER); \
+ dm_entry_upnp_load_tracked_parameters(&dmctx_trk); \
+ dm_ctx_clean(&dmctx_trk); \
+ } while(0)
+#endif
+
+#endif
diff --git a/dmjson.c b/dmjson.c
new file mode 100644
index 00000000..4577f519
--- /dev/null
+++ b/dmjson.c
@@ -0,0 +1,286 @@
+#include
+#include
+#include
+#include
+#include "dmjson.h"
+#include "dmmem.h"
+
+static json_object *dmjson_jobj = NULL;
+
+void dm_add_json_obj(json_object *json_obj_out, char *object, char *string)
+{
+ json_object *json_obj_tmp = json_object_new_string(string);
+ json_object_object_add(json_obj_out, object, json_obj_tmp);
+}
+
+static void inline __dmjson_fprintf(FILE *fp, int argc, struct dmjson_arg dmarg[])
+{
+ int i;
+ char *arg;
+ json_object *json_obj_out = json_object_new_object();
+ if (json_obj_out == NULL)
+ return;
+
+ if (argc) {
+ for (i = 0; i < argc; i++) {
+ dm_add_json_obj(json_obj_out, dmarg[i].key, dmarg[i].val);
+ }
+ arg = (char *)json_object_to_json_string(json_obj_out);
+ fprintf(fp, "%s\n", arg);
+ }
+
+ json_object_put(json_obj_out);
+}
+
+void dmjson_fprintf(FILE *fp, int argc, struct dmjson_arg dmarg[])
+{
+ __dmjson_fprintf(fp, argc, dmarg);
+}
+
+void dmjson_parse_init(char *msg)
+{
+ if (dmjson_jobj) {
+ json_object_put(dmjson_jobj);
+ dmjson_jobj = NULL;
+ }
+ dmjson_jobj = json_tokener_parse(msg);
+}
+
+void dmjson_parse_fini(void)
+{
+ if (dmjson_jobj) {
+ json_object_put(dmjson_jobj);
+ dmjson_jobj = NULL;
+ }
+}
+
+static char *dmjson_print_value(json_object *jobj)
+{
+ enum json_type type;
+ char *ret = "";
+
+ if (!jobj)
+ return ret;
+
+ type = json_object_get_type(jobj);
+ switch (type) {
+ case json_type_boolean:
+ case json_type_double:
+ case json_type_int:
+ case json_type_string:
+ ret = (char *)json_object_get_string(jobj);
+ break;
+ }
+ return ret;
+}
+
+char *____dmjson_get_value_in_obj(json_object *mainjobj, char *argv[])
+{
+ json_object *jobj = NULL;
+ char *value = "";
+
+ jobj = dmjson_select_obj(mainjobj, argv);
+ value = dmjson_print_value(jobj);
+
+ return value;
+}
+
+char *__dmjson_get_value_in_obj(json_object *mainjobj, int argc, ...)
+{
+ va_list arg;
+ char *argv[64], *v;
+ int i;
+
+ va_start(arg, argc);
+ for (i = 0; i < argc; i++)
+ {
+ argv[i] = va_arg(arg, char *);
+ }
+ argv[argc] = NULL;
+ va_end(arg);
+ v = ____dmjson_get_value_in_obj(mainjobj, argv);
+ return v;
+}
+
+json_object *__dmjson_get_obj(json_object *mainjobj, int argc, ...)
+{
+ va_list arg;
+ char *argv[64];
+ int i;
+
+ va_start(arg, argc);
+ for (i = 0; i < argc; i++)
+ {
+ argv[i] = va_arg(arg, char *);
+ }
+ argv[argc] = NULL;
+ va_end(arg);
+ return dmjson_select_obj(mainjobj, argv);
+ //return v;
+}
+
+
+json_object *dmjson_select_obj(json_object * jobj, char *argv[])
+{
+ int i;
+ for (i = 0; argv[i]; i++) {
+ if (jobj == NULL)
+ return NULL;
+ json_object_object_get_ex(jobj, argv[i], &jobj);
+ }
+ return jobj;
+}
+
+
+json_object *____dmjson_select_obj_in_array_idx(json_object *mainjobj, json_object **arrobj, int index, char *argv[])
+{
+ json_object *jobj = NULL;
+ int i;
+
+ if (arrobj == NULL || *arrobj == NULL) {
+ jobj = dmjson_select_obj(mainjobj, argv);
+ if (arrobj)
+ *arrobj = jobj;
+ if (jobj && json_object_get_type(jobj) == json_type_array) {
+ jobj = json_object_array_get_idx(jobj, index);
+ return jobj;
+ }
+ else {
+ return NULL;
+ }
+ }
+ else {
+ jobj = json_object_array_get_idx(*arrobj, index);
+ return jobj;
+ }
+
+ return NULL;
+}
+
+json_object *__dmjson_select_obj_in_array_idx(json_object *mainjobj, json_object **arrobj, int index, int argc, ...)
+{
+ va_list arg;
+ json_object *jobj;
+ char *argv[64];
+ int i;
+
+ if (mainjobj == NULL)
+ return NULL;
+
+ va_start(arg, argc);
+ for (i = 0; i < argc; i++)
+ {
+ argv[i] = va_arg(arg, char *);
+ }
+ argv[argc] = NULL;
+ va_end(arg);
+ jobj = ____dmjson_select_obj_in_array_idx(mainjobj, arrobj, index, argv);
+ return jobj;
+}
+
+char *____dmjson_get_value_in_array_idx(json_object *mainjobj, json_object **arrobj, int index, char *argv[])
+{
+ json_object *jobj = NULL;
+ char *value = NULL;
+ int i;
+
+ if (arrobj == NULL || *arrobj == NULL) {
+ jobj = dmjson_select_obj(mainjobj, argv);
+ if (arrobj)
+ *arrobj = jobj;
+ if (jobj && json_object_get_type(jobj) == json_type_array) {
+ jobj = json_object_array_get_idx(jobj, index);
+ if (jobj == NULL)
+ return NULL;
+ value = dmjson_print_value(jobj);
+ return value;
+ }
+ }
+ else {
+ jobj = json_object_array_get_idx(*arrobj, index);
+ if (jobj == NULL)
+ return NULL;
+ value = dmjson_print_value(jobj);
+ return value;
+ }
+
+ return value;
+}
+
+char *__dmjson_get_value_in_array_idx(json_object *mainjobj, json_object **arrobj, char *defret, int index, int argc, ...)
+{
+ va_list arg;
+ char *argv[64], *v;
+ int i;
+
+ if (mainjobj == NULL)
+ return defret;
+
+ va_start(arg, argc);
+ for (i = 0; i < argc; i++)
+ {
+ argv[i] = va_arg(arg, char *);
+ }
+ argv[argc] = NULL;
+ va_end(arg);
+ v = ____dmjson_get_value_in_array_idx(mainjobj, arrobj, index, argv);
+ return (v ? v : defret) ;
+}
+
+char *____dmjson_get_value_array_all(json_object *mainjobj, char *delim, char *argv[])
+{
+ json_object *arrobj;
+ char *v, *ret = "";
+ int i, dlen;
+
+ delim = (delim) ? delim : ",";
+ dlen = strlen(delim);
+
+ for (i = 0, arrobj = NULL, v = ____dmjson_get_value_in_array_idx(mainjobj, &arrobj, i, argv);
+ v;
+ v = ____dmjson_get_value_in_array_idx(mainjobj, &arrobj, ++i, argv)) {
+
+ if (*ret == '\0') {
+ ret = dmstrdup(v);
+ }
+ else if (*v) {
+ ret = dmrealloc(ret, strlen(ret) + dlen + strlen(v) + 1);
+ strcat(ret, delim);
+ strcat(ret, v);
+ }
+ }
+ return ret;
+}
+
+char *__dmjson_get_value_array_all(json_object *mainjobj, char *delim, int argc, ...)
+{
+ char *argv[64], *ret;
+ va_list arg;
+ int i;
+
+ va_start(arg, argc);
+ for (i = 0; i < argc; i++)
+ {
+ argv[i] = va_arg(arg, char *);
+ }
+ argv[argc] = NULL;
+ va_end(arg);
+ ret = ____dmjson_get_value_array_all(mainjobj, delim, argv);
+ return ret;
+}
+
+void dmjson_get_var(char *jkey, char **jval)
+{
+ enum json_type type;
+ *jval = "";
+
+ if (dmjson_jobj == NULL)
+ return;
+
+ json_object_object_foreach(dmjson_jobj, key, val) {
+ if (strcmp(jkey, key) == 0) {
+ *jval = dmjson_print_value(val);
+ return;
+ }
+ }
+}
diff --git a/dmjson.h b/dmjson.h
new file mode 100644
index 00000000..6a1702ea
--- /dev/null
+++ b/dmjson.h
@@ -0,0 +1,50 @@
+#ifndef __DMJSON_H
+#define __DMJSON_H
+
+#include
+#include
+#include
+#include "dmcwmp.h"
+
+struct dmjson_arg {
+ char *key;
+ char *val;
+};
+
+#define DMJSON_ARGS (struct dmjson_arg[])
+
+void dm_add_json_obj(json_object *json_obj_out, char *object, char *string);
+void dmjson_printf(int argc, struct dmjson_arg dmarg[]);
+void dmjson_fprintf(FILE *fp, int argc, struct dmjson_arg dmarg[]);
+void dmjson_parse_init(char *msg);
+void dmjson_parse_fini(void);
+void dmjson_get_var(char *jkey, char **jval);
+json_object *dmjson_select_obj(json_object * jobj, char *argv[]);
+json_object *__dmjson_get_obj(json_object *mainjobj, int argc, ...);
+char *____dmjson_get_value_in_obj(json_object *mainjobj, char *argv[]);
+char *__dmjson_get_value_in_obj(json_object *mainjobj, int argc, ...);
+json_object *__dmjson_select_obj_in_array_idx(json_object *mainjobj, json_object **arrobj, int index, int argc, ...);
+
+char *____dmjson_get_value_array_all(json_object *mainjobj, char *delim, char *argv[]);
+char *__dmjson_get_value_array_all(json_object *mainjobj, char *delim, int argc, ...);
+
+#define dmjson_get_value(JOBJ,ARGC,args...) \
+ __dmjson_get_value_in_obj(JOBJ, ARGC, ##args)
+#define dmjson_get_obj(JOBJ,ARGC,args...) \
+ __dmjson_get_obj(JOBJ, ARGC, ##args)
+
+#define dmjson_get_value_in_array_idx(MAINJOBJ,INDEX,ARGC,args...) \
+ __dmjson_get_value_in_array_idx(MAINJOBJ, NULL, "", INDEX, ARGC, ##args)
+
+#define dmjson_select_obj_in_array_idx(MAINJOBJ,INDEX,ARGC,args...) \
+ __dmjson_select_obj_in_array_idx(MAINJOBJ, NULL, INDEX, ARGC, ##args)
+
+#define dmjson_get_value_array_all(MAINJOBJ,DELIM,ARGC,args...) \
+ __dmjson_get_value_array_all(MAINJOBJ, DELIM, ARGC, ##args);
+
+#define dmjson_foreach_value_in_array(MAINJOBJ,ARROBJ,VAL,INDEX,ARGC,args...) \
+ for (INDEX = 0, ARROBJ = NULL, VAL = __dmjson_get_value_in_array_idx(MAINJOBJ, &(ARROBJ), NULL, INDEX, ARGC, ##args);\
+ VAL; \
+ VAL = __dmjson_get_value_in_array_idx(MAINJOBJ, &(ARROBJ), NULL, ++INDEX, 0))
+
+#endif
diff --git a/dmmem.c b/dmmem.c
new file mode 100644
index 00000000..252a5d7e
--- /dev/null
+++ b/dmmem.c
@@ -0,0 +1,152 @@
+#include "dmmem.h"
+
+#ifdef WITH_MEMLEACKSEC
+LIST_HEAD(memhead);
+
+inline void *__dmmalloc
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+size_t size
+)
+{
+ struct dmmem *m = malloc(sizeof(struct dmmem) + size);
+ if (m == NULL) return NULL;
+ list_add(&m->list, &memhead);
+#ifdef WITH_MEMTRACK
+ m->file = (char *)file;
+ m->func = (char *)func;
+ m->line = line;
+#endif /*WITH_MEMTRACK*/
+ return (void *)m->mem;
+}
+
+inline void *__dmcalloc
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+int n, size_t size
+)
+{
+ struct dmmem *m = calloc(n, sizeof(struct dmmem) + size);
+ if (m == NULL) return NULL;
+ list_add(&m->list, &memhead);
+#ifdef WITH_MEMTRACK
+ m->file = (char *)file;
+ m->func = (char *)func;
+ m->line = line;
+#endif /*WITH_MEMTRACK*/
+ return (void *)m->mem;
+}
+
+inline void *__dmrealloc
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+void *old, size_t size
+)
+{
+ struct dmmem *m = NULL;
+ if (old != NULL) {
+ m = container_of(old, struct dmmem, mem);
+ list_del(&m->list);
+ }
+ m = realloc(m, sizeof(struct dmmem) + size);
+ if (m == NULL) return NULL;
+ list_add(&m->list, &memhead);
+#ifdef WITH_MEMTRACK
+ m->file = (char *)file;
+ m->func = (char *)func;
+ m->line = line;
+#endif /*WITH_MEMTRACK*/
+ return (void *)m->mem;
+}
+
+inline void dmfree(void *m)
+{
+ if (m == NULL) return;
+ struct dmmem *rm;
+ rm = container_of(m, struct dmmem, mem);
+ list_del(&rm->list);
+ free(rm);
+}
+
+void dmcleanmem()
+{
+ struct dmmem *dmm;
+ while (memhead.next != &memhead) {
+ dmm = list_entry(memhead.next, struct dmmem, list);
+#ifdef WITH_MEMTRACK
+ fprintf(stderr, "Allocated memory in {%s, %s(), line %d} is not freed\n", dmm->file, dmm->func, dmm->line);
+#endif /*WITH_MEMTRACK*/
+ list_del(&dmm->list);
+ free(dmm);
+ }
+}
+
+char *__dmstrdup
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+const char *s
+)
+{
+ size_t len = strlen(s) + 1;
+#ifdef WITH_MEMTRACK
+ void *new = __dmmalloc(file, func, line, len);
+#else
+ void *new = __dmmalloc(len);
+#endif /*WITH_MEMTRACK*/
+ if (new == NULL) return NULL;
+ return (char *) memcpy(new, s, len);
+}
+#endif /*WITH_MEMLEACKSEC*/
+
+int __dmasprintf
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+char **s, const char *format, ...
+)
+{
+ char buf[512];
+ va_list arg;
+ int ret;
+ va_start(arg,format);
+ ret = vsprintf(buf, format, arg);
+ va_end(arg);
+#ifdef WITH_MEMTRACK
+ *s = __dmstrdup(file, func, line, buf);
+#else
+ *s = __dmstrdup(buf);
+#endif /*WITH_MEMTRACK*/
+ if (*s == NULL) return -1;
+ return 0;
+}
+
+int __dmastrcat
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+char **s, char *obj, char *lastname
+)
+{
+ char buf[512];
+ int olen = strlen(obj);
+ memcpy(buf, obj, olen);
+ int llen = strlen(lastname) + 1;
+ memcpy(buf + olen, lastname, llen);
+#ifdef WITH_MEMTRACK
+ *s = __dmstrdup(file, func, line, buf);
+#else
+ *s = __dmstrdup(buf);
+#endif /*WITH_MEMTRACK*/
+ if (*s == NULL) return -1;
+ return 0;
+}
\ No newline at end of file
diff --git a/dmmem.h b/dmmem.h
new file mode 100644
index 00000000..2312e8c7
--- /dev/null
+++ b/dmmem.h
@@ -0,0 +1,110 @@
+#include
+#include
+#include
+#include
+#include
+#ifndef __DMMEM_H
+#define __DMMEM_H
+
+void dmfree(void *m);
+static inline void dm_empty_func()
+{
+}
+
+#define WITH_MEMLEACKSEC 1
+//#define WITH_MEMTRACK 1
+
+#ifndef WITH_MEMLEACKSEC
+#undef WITH_MEMTRACK
+#endif
+
+#ifdef WITH_MEMLEACKSEC
+struct dmmem {
+ struct list_head list;
+#ifdef WITH_MEMTRACK
+ char *file;
+ char *func;
+ int line;
+#endif /*WITH_MEMTRACK*/
+ char mem[0];
+};
+
+void *__dmmalloc
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+size_t size
+);
+
+void *__dmcalloc
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+int n, size_t size
+);
+
+void *__dmrealloc
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+void *n, size_t size
+);
+
+char *__dmstrdup
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+const char *s
+);
+
+void dmcleanmem();
+#endif /*WITH_MEMLEACKSEC*/
+int __dmasprintf
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+char **s, const char *format, ...
+);
+
+int __dmastrcat
+(
+#ifdef WITH_MEMTRACK
+const char *file, const char *func, int line,
+#endif /*WITH_MEMTRACK*/
+char **s, char *obj, char *lastname
+);
+
+#ifdef WITH_MEMLEACKSEC
+#ifdef WITH_MEMTRACK
+#define dmmalloc(x) __dmmalloc(__FILE__, __func__, __LINE__, x)
+#define dmcalloc(n, x) __dmcalloc(__FILE__, __func__, __LINE__, n, x)
+#define dmrealloc(x, n) __dmrealloc(__FILE__, __func__, __LINE__, x, n)
+#define dmstrdup(x) __dmstrdup(__FILE__, __func__, __LINE__, x)
+#define dmasprintf(s, format, ...) __dmasprintf(__FILE__, __func__, __LINE__, s, format, ## __VA_ARGS__)
+#define dmastrcat(s, b, m) __dmastrcat(__FILE__, __func__, __LINE__, s, b, m)
+#else
+#define dmmalloc(x) __dmmalloc(x)
+#define dmcalloc(n, x) __dmcalloc(n, x)
+#define dmrealloc(x, n) __dmrealloc(x, n)
+#define dmstrdup(x) __dmstrdup(x)
+#define dmasprintf(s, format, ...) __dmasprintf(s, format, ## __VA_ARGS__)
+#define dmastrcat(s, b, m) __dmastrcat(s, b, m)
+#endif /*WITH_MEMTRACK*/
+#else
+#define dmmalloc(x) malloc(x)
+#define dmcalloc(n, x) calloc(n, x)
+#define __dmstrdup(x) strdup(x)
+#define dmstrdup(x) strdup(x)
+#define dmasprintf(s, format, ...) __dmasprintf(s, format, ## __VA_ARGS__)
+#define dmastrcat(s, b, m) __dmastrcat(s, b, m)
+#define dmfree(x) free(x)
+#define dmcleanmem() dm_empty_func()
+#endif /*WITH_MEMLEACKSEC*/
+
+#define DMFREE(x) do { dmfree(x); x = NULL; } while (0);
+#endif
diff --git a/dmoperate.c b/dmoperate.c
new file mode 100644
index 00000000..1926d2e8
--- /dev/null
+++ b/dmoperate.c
@@ -0,0 +1,865 @@
+/*
+ * dmoperate.c: Operate handler for uspd
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
+ *
+ * Author: Vivek Dutta
+ * Author: Yashvardhan
+ * Author: Amin Ben Ramdhane
+ *
+ * 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
+#include
+#include
+#include
+#include "dmcwmp.h"
+#include "dmubus.h"
+#include "dmuci.h"
+#include "dmjson.h"
+#include "dmentry.h"
+#include "dmcommon.h"
+#include "dmoperate.h"
+#include "dmdiagnostics.h"
+
+#define GLOB_EXPR "[=><]+"
+
+bool match(const char *string, const char *pattern)
+{
+ regex_t re;
+ if (regcomp(&re, pattern, REG_EXTENDED) != 0) return 0;
+ int status = regexec(&re, string, 0, NULL, 0);
+ regfree(&re);
+ if (status != 0) return false;
+ return true;
+}
+
+bool is_str_eq(const char *s1, const char *s2)
+{
+ if(0==strcmp(s1, s2))
+ return true;
+
+ return false;
+}
+
+static void cwmp_init(struct dmctx *dm_ctx, char *path)
+{
+ char *uci_amd = NULL, *uci_instance = NULL;
+ int amd = AMD_2, instance = INSTANCE_MODE_ALIAS;
+
+ if(match(path, "[[]+")) {
+ if(!match(path, GLOB_EXPR)) {
+ amd = AMD_5;
+ }
+ } else {
+ dmuci_get_option_value_string("cwmp", "cpe", "amd_version", &uci_amd);
+ if(uci_amd) {
+ amd = atoi(uci_amd);
+ free(uci_amd);
+ }
+ dmuci_get_option_value_string("cwmp", "cpe", "instance_mode", &uci_instance);
+ if(uci_instance) {
+ if(!is_str_eq(uci_instance, "InstanceAlias"))
+ instance = INSTANCE_MODE_NUMBER;
+ free(uci_instance);
+ }
+ }
+ printf("amd |%d| instance|%d|\n", amd, instance);
+ dm_ctx_init(dm_ctx, DM_CWMP, amd, instance);
+}
+
+static void cwmp_cleanup(struct dmctx *dm_ctx)
+{
+ dm_ctx_clean(dm_ctx);
+}
+
+static bool cwmp_get(int operation, char *path, struct dmctx *dm_ctx)
+{
+ int fault = 0;
+
+ printf("Entry |%s| operation|%d| \n", path, operation);
+ 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:
+ printf("Operation not supported yet!\n");
+ return false;
+ }
+
+ if (dm_ctx->list_fault_param.next != &dm_ctx->list_fault_param) {
+ return false;
+ }
+ if (fault) {
+ return false;
+ }
+ return true;
+}
+
+static bool cwmp_set_value(char *path, char *value)
+{
+ int fault = 0, res;
+ struct dmctx dm_ctx = {0};
+ struct dmctx *p_dmctx = &dm_ctx;
+
+ cwmp_init(&dm_ctx, path);
+ printf("Entry path|%s|, value|%s|", path, value);
+ 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;
+
+ cwmp_cleanup(&dm_ctx);
+ return res;
+}
+
+
+char *cwmp_get_value_by_id(char *id)
+{
+ struct dmctx dm_ctx = {0};
+ struct dm_parameter *n;
+ char *value = NULL;
+
+ printf("Entry id |%s|", id);
+ cwmp_init(&dm_ctx, id);
+ if(cwmp_get(CMD_GET_VALUE, id, &dm_ctx)) {
+ list_for_each_entry(n, &dm_ctx.list_parameter, list) {
+ printf("value |%s| \n", n->name);
+ value = dmstrdup(n->data);
+ break;
+ }
+ }
+ cwmp_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 = cwmp_get_value_by_id(node);
+ return val;
+}
+
+// Operate function definitions
+static opr_ret_t reboot_device(struct dmctx *dmctx, char *path, char *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, char *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, char *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 {
+ printf("Network not reachable |%s|", cmd);
+ return FAIL;
+ }
+ printf("cmd |%s|", cmd);
+ 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, char *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, char *input)
+{
+ char *wpakey = NULL;
+ char node[MAXNAMLEN] = {'\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, MAXNAMLEN);
+ 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, MAXNAMLEN);
+
+ // Get Default wpakey
+ db_get_value_string("hw", "board", "wpaKey", &wpakey);
+
+ // PreSharedKey and KeyPassphrase are kept same
+ strncpy(reset_params[1].value, wpakey, MAXNAMLEN);
+ strncpy(reset_params[2].value, wpakey, MAXNAMLEN);
+
+ for (i = 0; i < len; i++) {
+ cwmp_set_value(reset_params[i].node, reset_params[i].value);
+ }
+ return SUCCESS;
+}
+
+static opr_ret_t dhcp_client_renew(struct dmctx *dmctx, char *path, char *input)
+{
+ if(SUCCESS == cwmp_set_value(path, "true"))
+ return SUCCESS;
+ else
+ return FAIL;
+}
+
+static opr_ret_t vendor_conf_backup(struct dmctx *dmctx, char *path, char *input)
+{
+ struct file_server fserver = {0};
+ json_object *json_res = NULL;
+ char *vcf_name = NULL;
+
+ vcf_name = get_param_val_from_op_cmd(path, "Name");
+ if (vcf_name[0] == '\0')
+ return FAIL;
+
+ json_res = json_tokener_parse((const char *)input);
+ fserver.url = dmstrdup(dmjson_get_value(json_res, 1, "URL"));
+ if(fserver.url[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+
+ fserver.user = dmstrdup(dmjson_get_value(json_res, 1, "Username"));
+ if(fserver.user[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+
+ fserver.pass = dmjson_get_value(json_res, 1, "Password");
+ if(fserver.pass[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+
+ 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, char *input)
+{
+ struct file_server fserver = {0};
+ json_object *json_res = NULL;
+ char *file_size = NULL;
+
+ json_res = json_tokener_parse((const char *)input);
+ fserver.url = dmjson_get_value(json_res, 1, "URL");
+ if(fserver.url[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+
+ fserver.user = dmjson_get_value(json_res, 1, "Username");
+ if(fserver.user[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+
+ fserver.pass = dmjson_get_value(json_res, 1, "Password");
+ if(fserver.pass[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+
+ file_size = dmjson_get_value(json_res, 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, *obj;
+ struct neighboring_wiFi_diagnostic neighboring = {0};
+ char *ssid, *bssid, *channel, *frequency, *signal_stregth, *noise;
+
+ dmubus_call(ROUTER_WIRELESS_UBUS_PATH, "scanresults", UBUS_ARGS{{"radio", radio, String}}, 1, &res);
+
+ if(!json_object_object_get_ex(res,"access_points", &obj)) {
+ return;
+ }
+
+ uint8_t len = json_object_array_length(obj);
+ for (uint8_t j = 0; j < len; j++ ) {
+ 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, "frequency");
+ neighboring.signal_strength = dmjson_get_value(array_obj, 1, "rssi");
+ neighboring.noise = dmjson_get_value(array_obj, 1, "snr");
+
+ dmasprintf(&ssid, "Result.%d.SSID", j+1);
+ dmasprintf(&bssid, "Result.%d.BSSID", j+1);
+ dmasprintf(&channel, "Result.%d.Channel", j+1);
+ dmasprintf(&frequency, "Result.%d.OperatingFrequencyBand", j+1);
+ dmasprintf(&signal_stregth, "Result.%d.SignalStrength", j+1);
+ dmasprintf(&noise, "Result.%d.Noise", j+1);
+
+ add_list_paramameter(dmctx, ssid, neighboring.ssid, "string", NULL, 0);
+ add_list_paramameter(dmctx, bssid, neighboring.bssid, "string", NULL, 0);
+ add_list_paramameter(dmctx, channel, neighboring.channel, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, frequency, neighboring.frequency, "string", NULL, 0);
+ add_list_paramameter(dmctx, signal_stregth, neighboring.signal_strength, "int", NULL, 0);
+ add_list_paramameter(dmctx, noise, neighboring.noise, "int", NULL, 0);
+ }
+}
+
+static opr_ret_t fetch_neighboring_wifi_diagnostic(struct dmctx *dmctx, char *path, char *input)
+{
+ json_object *res;
+
+ dmubus_call(ROUTER_WIRELESS_UBUS_PATH, "radios", UBUS_ARGS{}, 0, &res);
+ json_object_object_foreach(res, key, val) {
+ fill_wireless_scan_results(dmctx, key);
+ }
+
+ return SUCCESS;
+}
+
+static opr_ret_t ip_diagnostics_ipping(struct dmctx *dmctx, char *path, char *input)
+{
+ json_object *json_res = NULL;
+ struct ipping_diagnostics ipping = {0};
+
+ json_res = json_tokener_parse((const char *)input);
+ ipping.host = dmjson_get_value(json_res, 1, "Host");
+ if(ipping.host[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+ ipping.interface = dmjson_get_value(json_res, 1, "Interface");
+ ipping.proto = dmjson_get_value(json_res, 1, "ProtocolVersion");
+ ipping.nbofrepetition = dmjson_get_value(json_res, 1, "NumberOfRepetitions");
+ ipping.timeout = dmjson_get_value(json_res, 1, "Timeout");
+ ipping.datablocksize = dmjson_get_value(json_res, 1, "DataBlockSize");
+ ipping.dscp = dmjson_get_value(json_res, 1, "DSCP");
+
+ set_param_diagnostics("ippingdiagnostic", "Host", ipping.host);
+ set_param_diagnostics("ippingdiagnostic", "interface", ipping.interface);
+ set_param_diagnostics("ippingdiagnostic", "ProtocolVersion", ipping.proto);
+ set_param_diagnostics("ippingdiagnostic", "NumberOfRepetitions", ipping.nbofrepetition);
+ set_param_diagnostics("ippingdiagnostic", "Timeout", ipping.timeout);
+ set_param_diagnostics("ippingdiagnostic", "DataBlockSize", ipping.datablocksize);
+ set_param_diagnostics("ippingdiagnostic", "DSCP", ipping.dscp);
+
+ //Free uci_varstate_ctx
+ end_uci_varstate_ctx();
+
+ dmcmd("/bin/sh", 3, IPPING_PATH, "run", "usp");
+
+ //Allocate uci_varstate_ctx
+ init_uci_varstate_ctx();
+
+ ipping.success_count = get_param_diagnostics("ippingdiagnostic", "SuccessCount");
+ ipping.failure_count = get_param_diagnostics("ippingdiagnostic", "FailureCount");
+ ipping.average_response_time = get_param_diagnostics("ippingdiagnostic", "AverageResponseTime");
+ ipping.minimum_response_time = get_param_diagnostics("ippingdiagnostic", "MinimumResponseTime");
+ ipping.maximum_response_time = get_param_diagnostics("ippingdiagnostic", "MaximumResponseTime");
+ ipping.average_response_time_detailed = get_param_diagnostics("ippingdiagnostic", "AverageResponseTimeDetailed");
+ ipping.minimum_response_time_detailed = get_param_diagnostics("ippingdiagnostic", "MinimumResponseTimeDetailed");
+ ipping.maximum_response_time_detailed = get_param_diagnostics("ippingdiagnostic", "MaximumResponseTimeDetailed");
+
+ char *param_success_count = dmstrdup("SuccessCount");
+ char *param_failure_count = dmstrdup("FailureCount");
+ char *param_average_response_time = dmstrdup("AverageResponseTime");
+ char *param_minimum_response_time = dmstrdup("MinimumResponseTime");
+ char *param_maximum_response_time = dmstrdup("MaximumResponseTime");
+ char *param_average_response_time_detailed = dmstrdup("AverageResponseTimeDetailed");
+ char *param_minimum_response_time_detailed = dmstrdup("MinimumResponseTimeDetailed");
+ char *param_maximum_response_time_detailed = dmstrdup("MaximumResponseTimeDetailed");
+
+ add_list_paramameter(dmctx, param_success_count, ipping.success_count, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_failure_count, ipping.failure_count, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_average_response_time, ipping.average_response_time, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_minimum_response_time, ipping.minimum_response_time, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_maximum_response_time, ipping.maximum_response_time, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_average_response_time_detailed, ipping.average_response_time_detailed, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_minimum_response_time_detailed, ipping.minimum_response_time_detailed, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_maximum_response_time_detailed, ipping.maximum_response_time_detailed, "unsignedInt", NULL, 0);
+
+ return SUCCESS;
+}
+
+static opr_ret_t ip_diagnostics_traceroute(struct dmctx *dmctx, char *path, char *input)
+{
+ json_object *json_res = NULL;
+ struct traceroute_diagnostics traceroute = {0};
+ struct uci_section *s = NULL;
+ char *host, *host_address, *errorcode, *rttimes;
+ int i = 1;
+
+ json_res = json_tokener_parse((const char *)input);
+ traceroute.host = dmjson_get_value(json_res, 1, "Host");
+ if(traceroute.host[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+ traceroute.interface = dmjson_get_value(json_res, 1, "Interface");
+ traceroute.proto = dmjson_get_value(json_res, 1, "ProtocolVersion");
+ traceroute.nboftries = dmjson_get_value(json_res, 1, "NumberOfTries");
+ traceroute.timeout = dmjson_get_value(json_res, 1, "Timeout");
+ traceroute.datablocksize = dmjson_get_value(json_res, 1, "DataBlockSize");
+ traceroute.dscp = dmjson_get_value(json_res, 1, "DSCP");
+ traceroute.maxhops = dmjson_get_value(json_res, 1, "MaxHopCount");
+
+ set_param_diagnostics("traceroutediagnostic", "Host", traceroute.host);
+ set_param_diagnostics("traceroutediagnostic", "interface", traceroute.interface);
+ set_param_diagnostics("traceroutediagnostic", "ProtocolVersion", traceroute.proto);
+ set_param_diagnostics("traceroutediagnostic", "NumberOfTries", traceroute.nboftries);
+ set_param_diagnostics("traceroutediagnostic", "Timeout", traceroute.timeout);
+ set_param_diagnostics("traceroutediagnostic", "DataBlockSize", traceroute.datablocksize);
+ set_param_diagnostics("traceroutediagnostic", "DSCP", traceroute.dscp);
+ set_param_diagnostics("traceroutediagnostic", "MaxHops", traceroute.maxhops);
+
+ //Free uci_varstate_ctx
+ end_uci_varstate_ctx();
+
+ dmcmd("/bin/sh", 3, TRACEROUTE_PATH, "run", "usp");
+
+ //Allocate uci_varstate_ctx
+ init_uci_varstate_ctx();
+
+ traceroute.response_time = get_param_diagnostics("traceroutediagnostic", "ResponseTime");
+ char *param_response_time = dmstrdup("ResponseTime");
+ add_list_paramameter(dmctx, param_response_time, traceroute.response_time, "unsignedInt", NULL, 0);
+
+ uci_foreach_sections_state("cwmp", "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_paramameter(dmctx, host, traceroute.host_name, "string", NULL, 0);
+ add_list_paramameter(dmctx, host_address, traceroute.host_address, "string", NULL, 0);
+ add_list_paramameter(dmctx, errorcode, "0", "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, rttimes, traceroute.rttimes, "string", NULL, 0);
+ i++;
+ }
+
+ return SUCCESS;
+}
+
+static opr_ret_t ip_diagnostics_download(struct dmctx *dmctx, char *path, char *input)
+{
+ json_object *json_res = NULL;
+ struct download_diagnostics download = {0};
+
+ json_res = json_tokener_parse((const char *)input);
+ download.download_url = dmjson_get_value(json_res, 1, "DownloadURL");
+ if(download.download_url[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+ download.interface = dmjson_get_value(json_res, 1, "Interface");
+ download.dscp = dmjson_get_value(json_res, 1, "DSCP");
+ download.ethernet_priority = dmjson_get_value(json_res, 1, "EthernetPriority");
+ download.proto = dmjson_get_value(json_res, 1, "ProtocolVersion");
+ download.num_of_connections = dmjson_get_value(json_res, 1, "NumberOfConnections");
+ download.enable_per_connection_results = dmjson_get_value(json_res, 1, "EnablePerConnectionResults");
+
+ set_param_diagnostics("downloaddiagnostic", "url", download.download_url);
+ set_param_diagnostics("downloaddiagnostic", "device", download.interface);
+ set_param_diagnostics("downloaddiagnostic", "DSCP", download.dscp);
+ set_param_diagnostics("downloaddiagnostic", "ethernetpriority", download.ethernet_priority);
+ set_param_diagnostics("downloaddiagnostic", "ProtocolVersion", download.proto);
+ set_param_diagnostics("downloaddiagnostic", "NumberOfConnections", download.num_of_connections);
+ set_param_diagnostics("downloaddiagnostic", "EnablePerConnection", download.enable_per_connection_results);
+
+ if(start_upload_download_diagnostic(DOWNLOAD_DIAGNOSTIC) == -1)
+ return FAIL;
+
+ download.romtime = get_param_diagnostics("downloaddiagnostic", "ROMtime");
+ download.bomtime = get_param_diagnostics("downloaddiagnostic", "BOMtime");
+ download.eomtime = get_param_diagnostics("downloaddiagnostic", "EOMtime");
+ download.test_bytes_received = get_param_diagnostics("downloaddiagnostic", "TestBytesReceived");
+ download.total_bytes_received = get_param_diagnostics("downloaddiagnostic", "TotalBytesReceived");
+ download.total_bytes_sent = get_param_diagnostics("downloaddiagnostic", "TotalBytesSent");
+ download.test_bytes_received_under_full_loading = get_param_diagnostics("downloaddiagnostic", "TestBytesReceived");
+ download.total_bytes_received_under_full_loading = get_param_diagnostics("downloaddiagnostic", "TotalBytesReceived");
+ download.total_bytes_sent_under_full_loading = get_param_diagnostics("downloaddiagnostic", "TotalBytesSent");
+ download.period_of_full_loading = get_param_diagnostics("downloaddiagnostic", "PeriodOfFullLoading");
+ download.tcp_open_request_time = get_param_diagnostics("downloaddiagnostic", "TCPOpenRequestTimes");
+ download.tcp_open_response_time = get_param_diagnostics("downloaddiagnostic", "TCPOpenResponseTime");
+
+ char *param_rom_time = dmstrdup("ROMTime");
+ char *param_bom_time = dmstrdup("BOMTime");
+ char *param_eom_time = dmstrdup("EOMTime");
+ char *param_test_bytes_received = dmstrdup("TestBytesReceived");
+ char *param_total_bytes_received = dmstrdup("TotalBytesReceived");
+ char *param_total_bytes_sent = dmstrdup("TotalBytesSent");
+ char *param_test_bytes_received_under_full_loading = dmstrdup("TestBytesReceivedUnderFullLoading");
+ char *param_total_bytes_received_under_full_loading = dmstrdup("TotalBytesReceivedUnderFullLoading");
+ char *param_total_bytes_sent_under_full_loading = dmstrdup("TotalBytesSentUnderFullLoading");
+ char *param_period_of_full_loading = dmstrdup("PeriodOfFullLoading");
+ char *param_tcp_open_request_time = dmstrdup("TCPOpenRequestTime");
+ char *param_tcp_open_response_time = dmstrdup("TCPOpenResponseTime");
+
+ add_list_paramameter(dmctx, param_rom_time, download.romtime, "dateTime", NULL, 0);
+ add_list_paramameter(dmctx, param_bom_time, download.bomtime, "dateTime", NULL, 0);
+ add_list_paramameter(dmctx, param_eom_time, download.eomtime, "dateTime", NULL, 0);
+ add_list_paramameter(dmctx, param_test_bytes_received, download.test_bytes_received, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_total_bytes_received, download.total_bytes_received, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_total_bytes_sent, download.total_bytes_sent, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_test_bytes_received_under_full_loading, download.test_bytes_received_under_full_loading, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_total_bytes_received_under_full_loading, download.total_bytes_received_under_full_loading, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_total_bytes_sent_under_full_loading, download.total_bytes_sent_under_full_loading, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_period_of_full_loading, download.period_of_full_loading, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_tcp_open_request_time, download.tcp_open_request_time, "dateTime", NULL, 0);
+ add_list_paramameter(dmctx, param_tcp_open_response_time, download.tcp_open_response_time, "dateTime", NULL, 0);
+
+ return SUCCESS;
+}
+
+static opr_ret_t ip_diagnostics_upload(struct dmctx *dmctx, char *path, char *input)
+{
+ json_object *json_res = NULL;
+ struct upload_diagnostics upload = {0};
+
+ json_res = json_tokener_parse((const char *)input);
+ upload.upload_url = dmjson_get_value(json_res, 1, "UploadURL");
+ if(upload.upload_url[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+ upload.test_file_length = dmjson_get_value(json_res, 1, "TestFileLength");
+ if(upload.test_file_length[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+ upload.interface = dmjson_get_value(json_res, 1, "Interface");
+ upload.dscp = dmjson_get_value(json_res, 1, "DSCP");
+ upload.ethernet_priority = dmjson_get_value(json_res, 1, "EthernetPriority");
+ upload.proto = dmjson_get_value(json_res, 1, "ProtocolVersion");
+ upload.num_of_connections = dmjson_get_value(json_res, 1, "NumberOfConnections");
+ upload.enable_per_connection_results = dmjson_get_value(json_res, 1, "EnablePerConnectionResults");
+
+ set_param_diagnostics("uploaddiagnostic", "url", upload.upload_url);
+ set_param_diagnostics("uploaddiagnostic", "TestFileLength", upload.test_file_length);
+ set_param_diagnostics("uploaddiagnostic", "device", upload.interface);
+ set_param_diagnostics("uploaddiagnostic", "DSCP", upload.dscp);
+ set_param_diagnostics("uploaddiagnostic", "ethernetpriority", upload.ethernet_priority);
+ set_param_diagnostics("uploaddiagnostic", "ProtocolVersion", upload.proto);
+ set_param_diagnostics("uploaddiagnostic", "NumberOfConnections", upload.num_of_connections);
+ set_param_diagnostics("uploaddiagnostic", "EnablePerConnection", upload.enable_per_connection_results);
+
+ if(start_upload_download_diagnostic(UPLOAD_DIAGNOSTIC) == -1)
+ return FAIL;
+
+ upload.romtime = get_param_diagnostics("uploaddiagnostic", "ROMtime");
+ upload.bomtime = get_param_diagnostics("uploaddiagnostic", "BOMtime");
+ upload.eomtime = get_param_diagnostics("uploaddiagnostic", "EOMtime");
+ upload.test_bytes_sent = get_param_diagnostics("uploaddiagnostic", "TestBytesSent");
+ upload.total_bytes_received = get_param_diagnostics("uploaddiagnostic", "TotalBytesReceived");
+ upload.total_bytes_sent = get_param_diagnostics("uploaddiagnostic", "TotalBytesSent");
+ upload.test_bytes_sent_under_full_loading = get_param_diagnostics("uploaddiagnostic", "TestBytesSent");
+ upload.total_bytes_received_under_full_loading = get_param_diagnostics("uploaddiagnostic", "TotalBytesReceived");
+ upload.total_bytes_sent_under_full_loading = get_param_diagnostics("uploaddiagnostic", "TotalBytesSent");
+ upload.period_of_full_loading = get_param_diagnostics("uploaddiagnostic", "PeriodOfFullLoading");
+ upload.tcp_open_request_time = get_param_diagnostics("uploaddiagnostic", "TCPOpenRequestTimes");
+ upload.tcp_open_response_time = get_param_diagnostics("uploaddiagnostic", "TCPOpenResponseTime");
+
+ char *param_rom_time = dmstrdup("ROMTime");
+ char *param_bom_time = dmstrdup("BOMTime");
+ char *param_eom_time = dmstrdup("EOMTime");
+ char *param_test_bytes_sent = dmstrdup("TestBytesSent");
+ char *param_total_bytes_received = dmstrdup("TotalBytesReceived");
+ char *param_total_bytes_sent = dmstrdup("TotalBytesSent");
+ char *param_test_bytes_sent_under_full_loading = dmstrdup("TestBytesSentUnderFullLoading");
+ char *param_total_bytes_received_under_full_loading = dmstrdup("TotalBytesReceivedUnderFullLoading");
+ char *param_total_bytes_sent_under_full_loading = dmstrdup("TotalBytesSentUnderFullLoading");
+ char *param_period_of_full_loading = dmstrdup("PeriodOfFullLoading");
+ char *param_tcp_open_request_time = dmstrdup("TCPOpenRequestTime");
+ char *param_tcp_open_response_time = dmstrdup("TCPOpenResponseTime");
+
+ add_list_paramameter(dmctx, param_rom_time, upload.romtime, "dateTime", NULL, 0);
+ add_list_paramameter(dmctx, param_bom_time, upload.bomtime, "dateTime", NULL, 0);
+ add_list_paramameter(dmctx, param_eom_time, upload.eomtime, "dateTime", NULL, 0);
+ add_list_paramameter(dmctx, param_test_bytes_sent, upload.test_bytes_sent, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_total_bytes_received, upload.total_bytes_received, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_total_bytes_sent, upload.total_bytes_sent, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_test_bytes_sent_under_full_loading, upload.test_bytes_sent_under_full_loading, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_total_bytes_received_under_full_loading, upload.total_bytes_received_under_full_loading, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_total_bytes_sent_under_full_loading, upload.total_bytes_sent_under_full_loading, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_period_of_full_loading, upload.period_of_full_loading, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_tcp_open_request_time, upload.tcp_open_request_time, "dateTime", NULL, 0);
+ add_list_paramameter(dmctx, param_tcp_open_response_time, upload.tcp_open_response_time, "dateTime", NULL, 0);
+
+ return SUCCESS;
+}
+
+static opr_ret_t ip_diagnostics_udpecho(struct dmctx *dmctx, char *path, char *input)
+{
+ json_object *json_res = NULL;
+ struct udpecho_diagnostics udpecho = {0};
+
+ json_res = json_tokener_parse((const char *)input);
+ udpecho.host = dmjson_get_value(json_res, 1, "Host");
+ if(udpecho.host[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+ udpecho.port = dmjson_get_value(json_res, 1, "Port");
+ if(udpecho.port[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+
+ udpecho.interface = dmjson_get_value(json_res, 1, "Interface");
+ udpecho.proto = dmjson_get_value(json_res, 1, "ProtocolVersion");
+ udpecho.nbofrepetition = dmjson_get_value(json_res, 1, "NumberOfRepetitions");
+ udpecho.timeout = dmjson_get_value(json_res, 1, "Timeout");
+ udpecho.datablocksize = dmjson_get_value(json_res, 1, "DataBlockSize");
+ udpecho.dscp = dmjson_get_value(json_res, 1, "DSCP");
+ udpecho.inter_transmission_time = dmjson_get_value(json_res, 1, "InterTransmissionTime");
+
+ set_param_diagnostics("udpechodiagnostic", "Host", udpecho.host);
+ set_param_diagnostics("udpechodiagnostic", "port", udpecho.port);
+ set_param_diagnostics("udpechodiagnostic", "interface", udpecho.interface);
+ set_param_diagnostics("udpechodiagnostic", "ProtocolVersion", udpecho.proto);
+ set_param_diagnostics("udpechodiagnostic", "NumberOfRepetitions", udpecho.nbofrepetition);
+ set_param_diagnostics("udpechodiagnostic", "Timeout", udpecho.timeout);
+ set_param_diagnostics("udpechodiagnostic", "DataBlockSize", udpecho.datablocksize);
+ set_param_diagnostics("udpechodiagnostic", "DSCP", udpecho.dscp);
+ set_param_diagnostics("udpechodiagnostic", "InterTransmissionTime", udpecho.inter_transmission_time);
+
+ //Free uci_varstate_ctx
+ end_uci_varstate_ctx();
+
+ dmcmd("/bin/sh", 3, UDPECHO_PATH, "run", "usp");
+
+ //Allocate uci_varstate_ctx
+ init_uci_varstate_ctx();
+
+ udpecho.success_count = get_param_diagnostics("udpechodiagnostic", "SuccessCount");
+ udpecho.failure_count = get_param_diagnostics("udpechodiagnostic", "FailureCount");
+ udpecho.average_response_time = get_param_diagnostics("udpechodiagnostic", "AverageResponseTime");
+ udpecho.minimum_response_time = get_param_diagnostics("udpechodiagnostic", "MinimumResponseTime");
+ udpecho.maximum_response_time = get_param_diagnostics("udpechodiagnostic", "MaximumResponseTime");
+
+ char *param_success_count = dmstrdup("SuccessCount");
+ char *param_failure_count = dmstrdup("FailureCount");
+ char *param_average_response_time = dmstrdup("AverageResponseTime");
+ char *param_minimum_response_time = dmstrdup("MinimumResponseTime");
+ char *param_maximum_response_time = dmstrdup("MaximumResponseTime");
+
+ add_list_paramameter(dmctx, param_success_count, udpecho.success_count, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_failure_count, udpecho.failure_count, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_average_response_time, udpecho.average_response_time, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_minimum_response_time, udpecho.minimum_response_time, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_maximum_response_time, udpecho.maximum_response_time, "unsignedInt", NULL, 0);
+
+ return SUCCESS;
+}
+
+static opr_ret_t ip_diagnostics_serverselection(struct dmctx *dmctx, char *path, char *input)
+{
+
+ json_object *json_res = NULL;
+ struct serverselection_diagnostics serverselection = {0};
+
+ json_res = json_tokener_parse((const char *)input);
+ serverselection.hostlist = dmjson_get_value(json_res, 1, "HostList");
+ if(serverselection.hostlist[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+ serverselection.port = dmjson_get_value(json_res, 1, "Port");
+ serverselection.proto = dmjson_get_value(json_res, 1, "Protocol");
+ if (strcmp(serverselection.proto, "ICMP")) {
+ if(serverselection.port[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+ }
+ serverselection.protocol_version = dmjson_get_value(json_res, 1, "ProtocolVersion");
+ serverselection.interface = dmjson_get_value(json_res, 1, "Interface");
+ serverselection.nbofrepetition = dmjson_get_value(json_res, 1, "NumberOfRepetitions");
+ serverselection.timeout = dmjson_get_value(json_res, 1, "Timeout");
+
+ set_param_diagnostics("serverselectiondiagnostic", "HostList", serverselection.hostlist);
+ set_param_diagnostics("serverselectiondiagnostic", "interface", serverselection.interface);
+ set_param_diagnostics("serverselectiondiagnostic", "ProtocolVersion", serverselection.proto);
+ set_param_diagnostics("serverselectiondiagnostic", "NumberOfRepetitions", serverselection.nbofrepetition);
+ set_param_diagnostics("serverselectiondiagnostic", "port", serverselection.port);
+ set_param_diagnostics("serverselectiondiagnostic", "Protocol", serverselection.proto);
+
+ //Free uci_varstate_ctx
+ end_uci_varstate_ctx();
+
+ dmcmd("/bin/sh", 3, SERVERSELECTION_PATH, "run", "usp");
+
+ //Allocate uci_varstate_ctx
+ init_uci_varstate_ctx();
+
+ serverselection.fasthost = get_param_diagnostics("serverselectiondiagnostic", "AverageResponseTimeDetailed");
+ serverselection.average_response_time = get_param_diagnostics("serverselectiondiagnostic", "AverageResponseTime");
+ serverselection.minimum_response_time = get_param_diagnostics("serverselectiondiagnostic", "MinimumResponseTime");
+ serverselection.maximum_response_time = get_param_diagnostics("serverselectiondiagnostic", "MaximumResponseTime");
+
+
+ char *param_fastest_host = dmstrdup("FastestHost");
+ char *param_average_response_time = dmstrdup("AverageResponseTime");
+ char *param_minimum_response_time = dmstrdup("MinimumResponseTime");
+ char *param_maximum_response_time = dmstrdup("MaximumResponseTime");
+
+ add_list_paramameter(dmctx, param_fastest_host, serverselection.fasthost, "string", NULL, 0);
+ add_list_paramameter(dmctx, param_average_response_time, serverselection.average_response_time, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_minimum_response_time, serverselection.minimum_response_time, "unsignedInt", NULL, 0);
+ add_list_paramameter(dmctx, param_maximum_response_time, serverselection.maximum_response_time, "unsignedInt", NULL, 0);
+
+ return SUCCESS;
+}
+
+static opr_ret_t ip_diagnostics_nslookup(struct dmctx *dmctx, char *path, char *input)
+{
+ json_object *json_res = NULL;
+ struct nslookup_diagnostics nslookup = {0};
+ struct uci_section *s = NULL;
+ char *status, *answertype, *hostname, *ipaddress, *dnsserverip, *responsetime;
+ int i = 1;
+
+ json_res = json_tokener_parse((const char *)input);
+ nslookup.hostname = dmjson_get_value(json_res, 1, "HostName");
+ if(nslookup.hostname[0] == '\0')
+ return UBUS_INVALID_ARGUMENTS;
+ nslookup.interface = dmjson_get_value(json_res, 1, "Interface");
+ nslookup.dnsserver = dmjson_get_value(json_res, 1, "DNSServer");
+ nslookup.timeout = dmjson_get_value(json_res, 1, "Timeout");
+ nslookup.nbofrepetition = dmjson_get_value(json_res, 1, "NumberOfRepetitions");
+
+ set_param_diagnostics("nslookupdiagnostic", "HostName", nslookup.hostname);
+ set_param_diagnostics("nslookupdiagnostic", "interface", nslookup.interface);
+ set_param_diagnostics("nslookupdiagnostic", "DNSServer", nslookup.dnsserver);
+ set_param_diagnostics("nslookupdiagnostic", "Timeout", nslookup.timeout);
+ set_param_diagnostics("nslookupdiagnostic", "NumberOfRepetitions", nslookup.nbofrepetition);
+
+ //Free uci_varstate_ctx
+ end_uci_varstate_ctx();
+
+ dmcmd("/bin/sh", 3, NSLOOKUP_PATH, "run", "usp");
+
+ //Allocate uci_varstate_ctx
+ init_uci_varstate_ctx();
+
+ nslookup.success_count = get_param_diagnostics("nslookupdiagnostic", "SuccessCount");
+ char *param_success_count = dmstrdup("SuccessCount");
+ add_list_paramameter(dmctx, param_success_count, nslookup.success_count, "unsignedInt", NULL, 0);
+
+ uci_foreach_sections_state("cwmp", "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_paramameter(dmctx, status, nslookup.status, "string", NULL, 0);
+ add_list_paramameter(dmctx, answertype, nslookup.answer_type, "string", NULL, 0);
+ add_list_paramameter(dmctx, hostname, nslookup.hostname_returned, "string", NULL, 0);
+ add_list_paramameter(dmctx, ipaddress, nslookup.ip_addresses, "string", NULL, 0);
+ add_list_paramameter(dmctx, dnsserverip, nslookup.dns_server_ip, "string", NULL, 0);
+ add_list_paramameter(dmctx, responsetime, nslookup.response_time, "unsignedInt", NULL, 0);
+ i++;
+ }
+
+ return SUCCESS;
+}
+
+static struct op_cmd operate_helper[] = {
+ {"Device.Reboot", reboot_device},
+ {"Device.FactoryReset", factory_reset},
+ {"Device.IP.Interface.*.Reset", network_interface_reset},
+ {"Device.PPP.Interface.*.Reset", network_interface_reset},
+ {"Device.WiFi.Reset", wireless_reset},
+ {"Device.WiFi.AccessPoint.*.Security.Reset", ap_security_reset},
+ {"Device.DHCPv4.Client.*.Renew", dhcp_client_renew},
+ {"Device.DHCPv6.Client.*.Renew", dhcp_client_renew},
+ {"Device.DeviceInfo.VendorConfigFile.*.Backup", vendor_conf_backup},
+ {"Device.DeviceInfo.VendorConfigFile.*.Restore", vendor_conf_restore},
+ {"Device.WiFi.NeighboringWiFiDiagnostic", fetch_neighboring_wifi_diagnostic},
+ //{"Device.DeviceInfo.VendorLogFile.*.Upload", blob_parser},
+ {"Device.IP.Diagnostics.IPPing", ip_diagnostics_ipping},
+ {"Device.IP.Diagnostics.TraceRoute", ip_diagnostics_traceroute},
+ {"Device.IP.Diagnostics.DownloadDiagnostics", ip_diagnostics_download},
+ {"Device.IP.Diagnostics.UploadDiagnostics", ip_diagnostics_upload},
+ {"Device.IP.Diagnostics.UDPEchoDiagnostics", ip_diagnostics_udpecho},
+ {"Device.IP.Diagnostics.ServerSelectionDiagnostics", ip_diagnostics_serverselection},
+ {"Device.DNS.Diagnostics.NSLookupDiagnostics", ip_diagnostics_nslookup}
+};
+
+int operate_on_node(struct dmctx *dmctx, char *path, char *input)
+{
+ uint8_t len = 0;
+
+ len = ARRAY_SIZE(operate_helper);
+ for(uint8_t i=0; i
+ * Author: Yashvardhan
+ * Author: Amin Ben Ramdhane
+ *
+ * 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
+ */
+
+#ifndef __DMOPERATE_H__
+#define __DMOPERATE_H__
+
+#include
+
+#define SYSTEM_UBUS_PATH "system"
+#define NETWORK_INTERFACE_UBUS_PATH "network.interface"
+#define NETWORK_WIRELESS_UBUS_PATH "network.wireless"
+#define ROUTER_WIRELESS_UBUS_PATH "router.wireless"
+#define ICWMP_SCRIPT "/usr/sbin/icwmp"
+#define VCF_FILE_TYPE "3"
+
+enum operate_ret_status{
+ UBUS_INVALID_ARGUMENTS,
+ SUCCESS,
+ FAIL,
+ CMD_NOT_FOUND,
+ __STATUS_MAX,
+};
+
+typedef enum operate_ret_status opr_ret_t;
+
+typedef opr_ret_t (*operation) (struct dmctx *dmctx, char *p, char *input);
+
+struct wifi_security_params {
+ char node[MAXNAMLEN];
+ char *param;
+ char value[MAXNAMLEN];
+};
+
+struct file_server {
+ char *url;
+ char *user;
+ char *pass;
+};
+
+struct neighboring_wiFi_diagnostic {
+ char *radio;
+ char *ssid;
+ char *bssid;
+ char *channel;
+ char *frequency;
+ char *encryption_mode;
+ char *operating_frequency_band;
+ char *supported_standards;
+ char *operating_standards;
+ char *operating_channel_bandwidth;
+ char *signal_strength;
+ char *noise;
+};
+
+struct ipping_diagnostics {
+ char *host;
+ char *interface;
+ char *proto;
+ char *nbofrepetition;
+ char *timeout;
+ char *datablocksize;
+ char *dscp;
+ char *success_count;
+ char *failure_count;
+ char *average_response_time;
+ char *minimum_response_time;
+ char *maximum_response_time;
+ char *average_response_time_detailed;
+ char *minimum_response_time_detailed;
+ char *maximum_response_time_detailed;
+};
+
+struct traceroute_diagnostics {
+ char *host;
+ char *interface;
+ char *proto;
+ char *nboftries;
+ char *timeout;
+ char *datablocksize;
+ char *dscp;
+ char *maxhops;
+ char *response_time;
+ char *host_name;
+ char *host_address;
+ char *rttimes;
+};
+
+struct download_diagnostics {
+ char *interface;
+ char *download_url;
+ char *dscp;
+ char *ethernet_priority;
+ char *proto;
+ char *num_of_connections;
+ char *enable_per_connection_results;
+
+ char *romtime;
+ char *bomtime;
+ char *eomtime;
+ char *test_bytes_received;
+ char *total_bytes_received;
+ char *total_bytes_sent;
+ char *test_bytes_received_under_full_loading;
+ char *total_bytes_received_under_full_loading;
+ char *total_bytes_sent_under_full_loading;
+ char *period_of_full_loading;
+ char *tcp_open_request_time;
+ char *tcp_open_response_time;
+
+ char *per_conn_romtime;
+ char *per_conn_bomtime;
+ char *per_conn_eomtime;
+ char *per_conn_test_bytes_received;
+ char *per_conn_total_bytes_received;
+ char *per_conn_total_bytes_sent;
+ char *per_conn_period_of_full_loading;
+ char *per_conn_tcp_open_request_time;
+ char *per_conn_tcp_open_response_time;
+};
+
+struct upload_diagnostics {
+ char *interface;
+ char *upload_url;
+ char *dscp;
+ char *ethernet_priority;
+ char *test_file_length;
+ char *proto;
+ char *num_of_connections;
+ char *enable_per_connection_results;
+
+ char *romtime;
+ char *bomtime;
+ char *eomtime;
+ char *test_bytes_sent;
+ char *total_bytes_received;
+ char *total_bytes_sent;
+ char *test_bytes_sent_under_full_loading;
+ char *total_bytes_received_under_full_loading;
+ char *total_bytes_sent_under_full_loading;
+ char *period_of_full_loading;
+ char *tcp_open_request_time;
+ char *tcp_open_response_time;
+
+ char *per_conn_romtime;
+ char *per_conn_bomtime;
+ char *per_conn_eomtime;
+ char *per_conn_test_bytes_sent;
+ char *per_conn_total_bytes_received;
+ char *per_conn_total_bytes_sent;
+ char *per_conn_period_of_full_loading;
+ char *per_conn_tcp_open_request_time;
+ char *per_conn_tcp_open_response_time;
+};
+
+struct udpecho_diagnostics {
+ char *host;
+ char *interface;
+ char *port;
+ char *nbofrepetition;
+ char *timeout;
+ char *datablocksize;
+ char *dscp;
+ char *inter_transmission_time;
+ char *response_time;
+ char *proto;
+ char *success_count;
+ char *failure_count;
+ char *average_response_time;
+ char *minimum_response_time;
+ char *maximum_response_time;
+};
+
+struct serverselection_diagnostics {
+ char *interface;
+ char *protocol_version;
+ char *proto;
+ char *hostlist;
+ char *port;
+ char *nbofrepetition;
+ char *timeout;
+ char *fasthost;
+ char *average_response_time;
+ char *minimum_response_time;
+ char *maximum_response_time;
+};
+
+struct nslookup_diagnostics {
+ char *interface;
+ char *hostname;
+ char *dnsserver;
+ char *timeout;
+ char *nbofrepetition;
+ char *success_count;
+ char *status;
+ char *answer_type;
+ char *hostname_returned;
+ char *ip_addresses;
+ char *dns_server_ip;
+ char *response_time;
+};
+
+struct op_cmd {
+ char *name;
+ operation opt;
+};
+
+int operate_on_node(struct dmctx *dmctx, char *path, char *input);
+
+#endif
diff --git a/dmtree/tr064/upnp_common.c b/dmtree/tr064/upnp_common.c
new file mode 100755
index 00000000..20b80465
--- /dev/null
+++ b/dmtree/tr064/upnp_common.c
@@ -0,0 +1,173 @@
+#include "upnp_common.h"
+#include "dmcwmp.h"
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmjson.h"
+#include "dmcommon.h"
+#include
+
+#include
+#include
+#include
+
+int upnp_get_NetworkInterfaceNumberOfEntries(){
+ int n = 0;
+ struct uci_section *s = NULL;
+ uci_foreach_sections("network", "interface", s) {
+ n++;
+ }
+ return n;
+}
+
+int upnp_get_IPInterfaceNumberOfEntries(){
+ char *value1 = NULL, *value2 = NULL;
+ int n = 0;
+ struct uci_section *s = NULL;
+
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "ipaddr", &value1);
+ if(value1 !=NULL && strlen(value1)>0) {
+ n++;
+ continue;
+ }
+ dmuci_get_value_by_section_string(s, "proto", &value2);
+ if(value2 !=NULL && strlen(value2)>0 && strstr(value2, "dhcp") != NULL) {
+ n++;
+ continue;
+ }
+ }
+ return n;
+}
+
+char *upnp_get_softwareversion()
+{
+ char *v=NULL, *tmp=NULL, *val=NULL;
+
+ db_get_value_string("hw", "board", "iopVersion", &v);
+ tmp = dmstrdup(v);// MEM WILL BE FREED IN DMMEMCLEAN
+ if(!tmp) return NULL;
+ val = tmp;
+ return val;
+}
+
+void upnp_getMacAddress(char *interfaceName, char **macAddress){
+ json_object *res = NULL, *res1 =NULL;
+ int length;
+
+ char *device = NULL;
+ char **devices =NULL;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interfaceName}}, 1, &res);
+ if(!(res)) goto not_found;
+ device = dmjson_get_value(res, 1, "device");
+ devices = strsplit(device, " ", &length);
+ dmubus_call("network.device", "status", UBUS_ARGS{{}}, 0, &res1);
+ if(!(res1)) goto not_found;
+ *macAddress = dmjson_get_value(res1, 2, devices[0], "macaddr");
+ not_found:
+ return;
+}
+
+void upnp_getInterfaceStatus(char *interfaceName, char **status){
+ json_object *res= NULL;
+ char *up= NULL;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interfaceName}}, 1, &res);
+ if (res == NULL) {
+ *status = NULL;
+ goto end_bloc;
+ }
+ up = dm_ubus_get_value(res, 1, "up");
+ if(up == NULL) {
+ *status = NULL;
+ goto end_bloc;
+ }
+ if(!strcmp(up,"true")) dmasprintf(status, "UP"); else dmasprintf(status, "DOWN");
+
+ end_bloc:
+ return;
+}
+
+int upnp_getInterfaceTotalPacketSent(char *interfaceName, char **totalPktSent){
+ json_object *res= NULL, *res1= NULL, *res2= NULL;
+ char *device = NULL, *tx_packets = NULL;
+ int length;
+ char **devices = NULL;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interfaceName}}, 1, &res);
+ if(res == NULL) {
+ *totalPktSent = NULL;
+ goto end_bloc;
+ }
+ device = dmjson_get_value(res, 1, "device");
+ if(device == NULL || strlen(device)<=0){
+ *totalPktSent = NULL;
+ goto end_bloc;
+ }
+ devices = strsplit(device, " ", &length);
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", devices[0]}}, 1, &res1);
+ if(res1 == NULL){
+ *totalPktSent = NULL;
+ goto end_bloc;
+ }
+ DM_ASSERT(res1, *totalPktSent = "");
+ *totalPktSent = dmjson_get_value(res1, 2, "statistics", "tx_packets");
+
+ end_bloc:
+ return 0;
+}
+
+int upnp_getInterfaceTotalPacketReceived(char *interfaceName, char **totalPktReceived){
+ json_object *res= NULL, *res1= NULL, *res2= NULL;
+ char *device = NULL, *rx_packets = NULL;
+ int length;
+ char **devices = NULL;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interfaceName}}, 1, &res);
+ if(res == NULL){
+ *totalPktReceived = NULL;
+ goto end_bloc;
+ }
+ device = dmjson_get_value(res, 1, "device");
+ if(device == NULL || strlen(device)<=0){
+ *totalPktReceived = NULL;
+ goto end_bloc;
+ }
+ devices = strsplit(device, " ", &length);
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", devices[0]}}, 1, &res1);
+ if(res1 == NULL){
+ *totalPktReceived = NULL;
+ goto end_bloc;
+ }
+ DM_ASSERT(res1, *totalPktReceived = "");
+ *totalPktReceived = dmjson_get_value(res1, 2, "statistics", "rx_packets");
+
+ end_bloc:
+ return 0;
+}
+
+char *upnp_get_deviceid_manufactureroui()
+{
+ char *v = NULL;
+ char str[16];
+ char *mac = NULL;
+ json_object *res= NULL;
+ size_t ln;
+
+ dmubus_call("router.system", "info", UBUS_ARGS{{}}, 0, &res);
+ if(!(res)) goto not_found;
+ mac = dmjson_get_value(res, 2, "system", "basemac");
+ if(mac)
+ {
+ ln = strlen(mac);
+ if (ln<17) goto not_found;
+ sscanf (mac,"%2c:%2c:%2c",str,str+2,str+4);
+ str[6] = '\0';
+ v = dmstrdup(str); // MEM WILL BE FREED IN DMMEMCLEAN
+ return v;
+ }
+not_found:
+ v = "";
+ return v;
+}
diff --git a/dmtree/tr064/upnp_common.h b/dmtree/tr064/upnp_common.h
new file mode 100755
index 00000000..70b2b337
--- /dev/null
+++ b/dmtree/tr064/upnp_common.h
@@ -0,0 +1,11 @@
+#ifndef UPNP_COMMON_H
+#define UPNP_COMMON_H
+char *upnp_get_softwareversion();
+int upnp_get_NetworkInterfaceNumberOfEntries();
+int upnp_get_IPInterfaceNumberOfEntries();
+void upnp_getMacAddress(char *interfaceName, char **macAddress);
+void upnp_getInterfaceStatus(char *interfaceName, char **status);
+int upnp_getInterfaceTotalPacketSent(char *interfaceName, char **totalPktSent);
+int upnp_getInterfaceTotalPacketReceived(char *interfaceName, char **totalPktReceived);
+char *upnp_get_deviceid_manufactureroui();
+#endif
diff --git a/dmtree/tr064/upnp_configuration.c b/dmtree/tr064/upnp_configuration.c
new file mode 100755
index 00000000..369a8dbd
--- /dev/null
+++ b/dmtree/tr064/upnp_configuration.c
@@ -0,0 +1,307 @@
+#include "dmcwmp.h"
+#include "upnp_configuration.h"
+#include "upnp_common.h"
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcommon.h"
+#include "dmjson.h"
+#include
+#include
+
+#define DELIMITOR ","
+/**************************************************************************
+*
+* /UPnP/DM/Configuration/ datamodel tree
+*
+***************************************************************************/
+
+/*** /UPnP/DM/Configuration/ objects ***/
+DMOBJ upnpConfigurationObj[] = {
+{"Network",&DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, upnpConfigurationNetworkObj, upnpConfigurationNetworkParams, NULL},
+{0}
+};
+
+/*** /UPnP/DM/Configuration/Network objects ***/
+DMOBJ upnpConfigurationNetworkObj[] = {
+{"IPInterface",&DMWRITE, upnp_configuration_ipinterface_createinstance, upnp_configuration_ipinterface_deleteinstance, NULL, upnp_browseIPInterfaceInst, &DMFINFRM, &DMNONE, upnpConfigurationNetworkIPInterfaceObj, upnpConfigurationNetworkIPInterfaceParams, NULL},
+{0}
+};
+
+/*** /UPnP/DM/Configuration/Network parameters ***/
+DMLEAF upnpConfigurationNetworkParams[]= {
+{"HostName", &DMWRITE, DMT_STRING, upnp_configuration_get_hostname, upnp_configuration_set_hostname, &DMFINFRM, NULL},
+{"IPInterfaceNumberOfEntries", &DMREAD, DMT_UNINT, upnp_configuration_get_IPInterfaceNumberOfEntries, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+/*** /UPnP/DM/Configuration/Network/IPInterface/#/ objects ***/
+DMOBJ upnpConfigurationNetworkIPInterfaceObj[]= {
+{"IPv4",&DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, NULL, upnpConfigurationNetworkIPInterfaceIpv4Params, NULL},
+{0}
+};
+
+/*** /UPnP/DM/Configuration/Network/IPInterface/#/ parameters ***/
+DMLEAF upnpConfigurationNetworkIPInterfaceParams[]= {
+{"SystemName", &DMREAD, DMT_STRING, upnp_configuration_get_SystemName, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+/*** /UPnP/DM/Configuration/Network/IPInterface/#/IPv4/ parameters ***/
+DMLEAF upnpConfigurationNetworkIPInterfaceIpv4Params[]= {
+{"IPAddress", &DMWRITE, DMT_STRING, upnp_configuration_get_ipv4_IPAddress, upnp_configuration_set_ipv4_IPAddress, &DMFINFRM, NULL},
+{"AddressingType", &DMWRITE, DMT_STRING, upnp_configuration_get_ipv4_addressingtype, upnp_configuration_set_ipv4_addressingtype, &DMFINFRM, NULL},
+{"DNSServers", &DMWRITE, DMT_STRING, upnp_configuration_get_ipv4_dnssevers, upnp_configuration_set_ipv4_dnssevers, &DMFINFRM, NULL},
+{"SubnetMask", &DMWRITE, DMT_STRING, upnp_configuration_get_ipv4_subnetmask, upnp_configuration_set_ipv4_subnetmask, &DMFINFRM, NULL},
+{"DefaultGateway", &DMWRITE, DMT_STRING, upnp_configuration_get_ipv4_defaultgateway, upnp_configuration_set_ipv4_defaultgateway, &DMFINFRM, NULL},
+{0}
+};
+
+/**************************************************************************
+*
+* /UPnP/DM/Configuration/* parameters functions
+*
+***************************************************************************/
+
+int upnp_configuration_get_hostname(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) {
+ return 0;
+}
+
+int upnp_configuration_get_IPInterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ int n = upnp_get_IPInterfaceNumberOfEntries();
+ dmasprintf(value, "%d", n);
+ return 0;
+}
+
+int upnp_configuration_get_SystemName(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ if(upnp_configargs->systemName !=NULL && strlen(upnp_configargs->systemName)>0) dmasprintf(value, "%s", upnp_configargs->systemName);
+ return 0;
+}
+
+int upnp_configuration_get_ipv4_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ char *ipv4addr=NULL;
+ dmuci_get_value_by_section_string(upnp_configargs->upnpConfiguration_sec, "ipaddr", &ipv4addr);
+ if(ipv4addr!=NULL && strlen(ipv4addr)> 0) dmasprintf(value, "%s", ipv4addr);
+ return 0;
+}
+
+int upnp_configuration_get_ipv4_addressingtype(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ char *proto=NULL;
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ dmuci_get_value_by_section_string(upnp_configargs->upnpConfiguration_sec, "proto", &proto);
+
+ if(proto!=NULL && strlen(proto)>0 && strstr(proto,"dhcp")) dmasprintf(value, "%s", "DHCP");
+ else dmasprintf(value, "%s", "Static");
+ return 0;
+}
+
+int upnp_configuration_get_ipv4_dnssevers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ json_object *res= NULL;
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ char *iface_name = section_name(upnp_configargs->upnpConfiguration_sec);
+ if(iface_name==NULL || strlen(iface_name)<=0) {
+ *value = NULL;
+ return 0;
+ }
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", iface_name}}, 1, &res);
+ if(res == NULL) {
+ *value = NULL;
+ return 0;
+ }
+ DM_ASSERT(res, *value = "");
+
+ *value = dmjson_get_value_array_all(res, DELIMITOR, 1, "dns-server");
+ if ((*value)[0] == '\0') {
+ dmuci_get_value_by_section_string(upnp_configargs->upnpConfiguration_sec, "dns", value);
+ *value = dmstrdup(*value); // MEM WILL BE FREED IN DMMEMCLEAN
+ char *p = *value;
+ while (*p) {
+ if (*p == ' ' && p != *value && *(p-1) != ',')
+ *p++ = ',';
+ else
+ p++;
+ }
+ }
+ return 0;
+}
+
+int upnp_configuration_get_ipv4_subnetmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ char *netmask = NULL;
+ dmuci_get_value_by_section_string(upnp_configargs->upnpConfiguration_sec, "netmask", &netmask);
+
+ if(netmask!=NULL && strlen(netmask)>0) dmasprintf(value, "%s", netmask);
+ else *value =NULL;
+ return 0;
+}
+
+int upnp_configuration_get_ipv4_defaultgateway(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ FILE* fp = NULL;
+ struct proc_routing proute = {0};
+ char line[MAX_PROC_ROUTING];
+ fp = fopen(ROUTING_FILE, "r");
+ if ( fp != NULL)
+ {
+ fgets(line, MAX_PROC_ROUTING, fp);
+ while (fgets(line, MAX_PROC_ROUTING, fp) != NULL )
+ {
+ if (line[0] == '\n')
+ continue;
+ parse_proc_route_line(line, &proute);
+ if(!strcmp(proute.iface, upnp_configargs->systemName)) {
+ if(proute.gateway!=NULL && strlen(proute.gateway)>0) dmasprintf(value, "%s", proute.gateway);
+ return 0;
+ }
+ else continue;
+ }
+ fclose(fp) ;
+ }
+ return 0;
+}
+
+int upnp_configuration_set_hostname(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ return 0;
+}
+
+int upnp_configuration_set_ipv4_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ char *proto= NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(upnp_configargs->upnpConfiguration_sec, "proto", &proto);
+ if(proto == NULL || strlen(proto)<=0) return 0;
+ if(strcmp(proto, "static") == 0)
+ dmuci_set_value_by_section(upnp_configargs->upnpConfiguration_sec, "ipaddr", value);
+ return 0;
+ }
+ return 0;
+}
+
+int upnp_configuration_set_ipv4_addressingtype(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ char *proto= NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if(strcasecmp(value, "static") == 0) {
+ dmuci_set_value_by_section(upnp_configargs->upnpConfiguration_sec, "proto", "static");
+ dmuci_set_value_by_section(upnp_configargs->upnpConfiguration_sec, "ipaddr", "0.0.0.0");
+ }
+ if(strcasecmp(value, "dhcp") == 0) {
+ dmuci_set_value_by_section(upnp_configargs->upnpConfiguration_sec, "proto", "dhcp");
+ dmuci_set_value_by_section(upnp_configargs->upnpConfiguration_sec, "ipaddr", "");
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int upnp_configuration_set_ipv4_dnssevers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ char *dup= NULL, *p= NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dup = dmstrdup(value);
+ p = dup;
+ while (*p) {
+ if (*p == ',')
+ *p++ = ' ';
+ else
+ p++;
+ }
+ dmuci_set_value_by_section(upnp_configargs->upnpConfiguration_sec, "dns", dup);
+ dmfree(dup);
+ return 0;
+ }
+ return 0;
+}
+
+int upnp_configuration_set_ipv4_subnetmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ char *proto = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(upnp_configargs->upnpConfiguration_sec, "proto", &proto);
+ if(proto == NULL || strlen(proto)<=0) return 0;
+ if(strcmp(proto, "static") == 0)
+ dmuci_set_value_by_section(upnp_configargs->upnpConfiguration_sec, "netmask", value);
+ return 0;
+ }
+ return 0;
+}
+
+int upnp_configuration_set_ipv4_defaultgateway(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(upnp_configargs->upnpConfiguration_sec, "gateway", value);
+ return 0;
+ }
+ return 0;
+}
+
+
+int upnp_configuration_ipinterface_createinstance(char *refparam, struct dmctx *ctx, void *data, char **instance){
+ char *value=NULL;
+ char *iface_instance=NULL, ib[8], ip_name[32];
+ char *p = ip_name;
+ struct uci_section *iface_sec = NULL;
+ iface_instance = get_last_instance("network","interface","upnp_ip_iface_instance");
+ sprintf(ib, "%d", iface_instance ? atoi(iface_instance)+1 : 1);
+ dmstrappendstr(p, "ip_interface_");
+ dmstrappendstr(p, ib);
+ dmstrappendend(p);
+ dmuci_add_section_and_rename("network", "interface", &iface_sec, &value);
+ dmuci_set_value("network", ip_name, "", "interface");
+ dmuci_set_value("network", ip_name, "proto", "dhcp");
+ *instance = update_instance(iface_sec, iface_instance, "upnp_ip_iface_instance");
+ return 0;
+}
+
+int upnp_configuration_ipinterface_deleteinstance(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action){
+ struct upnp_configuration_args *upnp_configargs = (struct upnp_configuration_args *)data;
+ switch (del_action) {
+ case DEL_INST:
+ if(upnp_configargs->upnpConfiguration_sec == NULL) return FAULT_9005;
+ dmuci_delete_by_section(upnp_configargs->upnpConfiguration_sec, NULL, NULL);
+ break;
+ case DEL_ALL:
+ return FAULT_9005;
+ }
+ return 0;
+}
+
+int upnp_browseIPInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance){
+ char *value1, *value2;
+ struct uci_section *net_sec = NULL;
+ char *iface_int = NULL, *iface_int_last = NULL;
+ struct upnp_configuration_args currUpnpConfigurationArgs = {0};
+ char *type=NULL, *ipv4addr = "", *ipv6addr = "", *proto, *inst;
+ char *value= NULL, *netmask = NULL;
+ json_object *res = NULL, *res1 = NULL;
+
+ uci_foreach_sections("network", "interface", net_sec) {
+ currUpnpConfigurationArgs.upnpConfiguration_sec = net_sec;
+ currUpnpConfigurationArgs.systemName = section_name(net_sec);
+ dmuci_get_value_by_section_string(net_sec, "netmask", &netmask);
+
+ iface_int = handle_update_instance(1, dmctx, &iface_int_last, update_instance_alias, 3, net_sec, "upnp_ip_iface_instance", "upnp_ip_iface_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&currUpnpConfigurationArgs, iface_int) == DM_STOP) break;
+
+ }
+ return 0;
+}
diff --git a/dmtree/tr064/upnp_configuration.h b/dmtree/tr064/upnp_configuration.h
new file mode 100755
index 00000000..ae73b7cb
--- /dev/null
+++ b/dmtree/tr064/upnp_configuration.h
@@ -0,0 +1,59 @@
+#ifndef UPNP_CONFIGURATION_H
+#define UPNP_CONFIGURATION_H
+#include "dmcwmp.h"
+
+struct upnp_configuration_args{
+ struct uci_section *upnpConfiguration_sec;
+ char *systemName;
+ char *ipv4address;
+ char *ipv6address;
+ char *addressingType;
+ char *ipAddressType;
+ char *prefix;
+ char **dnsservers;
+ char *netmask;
+ char *gateway;
+ int numberOfEntries;
+};
+
+int upnp_configuration_get_hostname(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_IPInterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_SystemName(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv4_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv4_addressingtype(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv4_dnssevers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv4_subnetmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv4_defaultgateway(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv6_addressnumberofentries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv6_dnsservers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv6_defaultgateway(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv6_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv6_IPAddressType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv6_addressingtype(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_configuration_get_ipv6_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int upnp_configuration_set_hostname(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int upnp_configuration_set_ipv4_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int upnp_configuration_set_ipv4_addressingtype(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int upnp_configuration_set_ipv4_dnssevers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int upnp_configuration_set_ipv4_subnetmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int upnp_configuration_set_ipv4_defaultgateway(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int upnp_configuration_ipinterface_createinstance(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int upnp_configuration_ipinterface_deleteinstance(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int upnp_configuration_address_createinstance(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int upnp_configuration_address_deleteinstance(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int upnp_browseIPInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int upnp_browseIPv6Address(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+extern DMOBJ upnpConfigurationNetworkObj[];
+extern DMLEAF upnpConfigurationNetworkParams[];
+extern DMLEAF upnpConfigurationNetworkObjParams[];
+extern DMOBJ upnpConfigurationNetworkIPInterfaceObj[];
+extern DMLEAF upnpConfigurationNetworkIPInterfaceParams[];
+extern DMLEAF upnpConfigurationNetworkIPInterfaceIpv4Params[];
+extern DMOBJ upnpConfigurationNetworkIPInterfaceIpv6Obj[];
+extern DMLEAF upnpConfigurationNetworkIPInterfaceIpv6Params[];
+extern DMOBJ upnpConfigurationNetworkIPInterfaceIpv6AddressParams[];
+extern DMOBJ upnpConfigurationObj[];
+#endif
diff --git a/dmtree/tr064/upnp_device.c b/dmtree/tr064/upnp_device.c
new file mode 100644
index 00000000..00b1d342
--- /dev/null
+++ b/dmtree/tr064/upnp_device.c
@@ -0,0 +1,264 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Imen Bhiri
+* Author: Anis Ellouze
+* Author: Amin Ben Ramdhane
+*/
+
+#include "dmuci.h"
+#include "dmcwmp.h"
+#include "upnp_device.h"
+#include "deviceinfo.h"
+#include "managementserver.h"
+#include "times.h"
+#include "upnp.h"
+#if BBF_TR104
+#include "voice_services.h"
+#endif
+#include "x_iopsys_eu_ice.h"
+#include "x_iopsys_eu_igmp.h"
+#include "x_iopsys_eu_ipacccfg.h"
+#include "x_iopsys_eu_logincfg.h"
+#include "x_iopsys_eu_power_mgmt.h"
+#include "x_iopsys_eu_syslog.h"
+#include "softwaremodules.h"
+#include "xmpp.h"
+#include "x_iopsys_eu_owsd.h"
+#include "x_iopsys_eu_dropbear.h"
+#include "x_iopsys_eu_buttons.h"
+#include "x_iopsys_eu_wifilife.h"
+#include "ip.h"
+#include "ethernet.h"
+#include "bridging.h"
+#include "wifi.h"
+#include "atm.h"
+#include "ptm.h"
+#include "dhcpv4.h"
+#include "hosts.h"
+#include "nat.h"
+#include "ppp.h"
+#include "routing.h"
+#include "userinterface.h"
+#include "landevice.h"
+#include "wandevice.h"
+#include "ippingdiagnostics.h"
+#include "lan_interfaces.h"
+#include "layer_3_forwarding.h"
+#include "x_iopsys_eu_wifi.h"
+#include "layer_2_bridging.h"
+#include "downloaddiagnostic.h"
+#include "uploaddiagnostic.h"
+#include "deviceconfig.h"
+#include "firewall.h"
+#include "dns.h"
+#include "users.h"
+#include "dsl.h"
+#include "dhcpv6.h"
+#include "interfacestack.h"
+#include "qos.h"
+
+#ifdef BBF_TR064
+#include "upnp_deviceinfo.h"
+#include "upnp_configuration.h"
+#include "upnp_monitoring.h"
+#endif
+
+/*** UPNP ***/
+#ifdef BBF_TR064
+DMOBJ tEntry098ObjUPNP[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{(char *)&dmroot, &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, tRoot098ObjUPNP, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMOBJ tRoot098ObjUPNP[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"BBF", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, tRoot098ObjUPNPBBF, NULL, NULL, BBFDM_BOTH},
+{"UPnP", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, tRoot098ObjUPNPDMROOT, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMOBJ tRoot098ObjUPNPDMROOT[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"DM", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, tRoot098ObjUPNPDM, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMOBJ tRoot098ObjUPNPDM[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"DeviceInfo", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,upnpDeviceInfoObj, upnpDeviceInfoParams, NULL, BBFDM_BOTH},
+{"Configuration", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,upnpConfigurationObj, NULL, NULL, BBFDM_BOTH},
+{"Monitoring", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,upnpMonitoringObj, upnpMonitoringParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMOBJ tRoot098ObjUPNPBBF[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"DeviceInfo", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,tDeviceInfoObj, tDeviceInfoParams, NULL, BBFDM_BOTH},
+{"ManagementServer", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,NULL, tManagementServerParams, NULL, BBFDM_BOTH},
+{"Time", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tTimeParams, NULL, BBFDM_BOTH},
+{"UPnP", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,tUPnPObj, NULL, NULL, BBFDM_BOTH},
+#if BBF_TR104
+{"VoiceService", &DMREAD, NULL, NULL, NULL, browseVoiceServiceInst, NULL, NULL, tVoiceServiceObj, tVoiceServiceParam, NULL, BBFDM_BOTH},
+#endif
+{CUSTOM_PREFIX"ICE", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_IceParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"IGMP", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_IgmpParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"IpAccCfg", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,tSe_IpAccObj, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"LoginCfg", &DMREAD, NULL, NULL, NULL, NULL,NULL, &DMNONE,NULL, tSe_LoginCfgParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"PowerManagement", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_PowerManagementParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"SyslogCfg", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_SyslogCfgParam, NULL, BBFDM_BOTH},
+{"SoftwareModules", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,tSoftwareModulesObj, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"Owsd", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,XIopsysEuOwsdObj, XIopsysEuOwsdParams, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"Dropbear", &DMWRITE, add_dropbear_instance, delete_dropbear_instance, NULL, browseXIopsysEuDropbear, NULL, &DMNONE, NULL, X_IOPSYS_EU_DropbearParams, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"Buttons", &DMREAD, NULL, NULL, NULL, browseXIopsysEuButton, NULL, &DMNONE, NULL, X_IOPSYS_EU_ButtonParams, NULL, BBFDM_BOTH},
+{"LANDevice", &DMREAD, NULL, NULL, NULL, browselandeviceInst, &DMFINFRM, &DMNONE,tLANDeviceObj, tLANDeviceParam, NULL, BBFDM_BOTH},
+{"WANDevice", &DMREAD, NULL, NULL, NULL, browsewandeviceInst, &DMFINFRM, &DMWANConnectionDevicenotif,tWANDeviceObj, tWANDeviceParam, NULL, BBFDM_BOTH},
+{"LANInterfaces", &DMREAD, NULL, NULL, check_laninterfaces, NULL, &DMFINFRM, &DMNONE,tLANInterfacesObj, tLANInterfacesParam, NULL, BBFDM_BOTH},
+{"IPPingDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,NULL, tIPPingDiagnosticsParam, NULL, BBFDM_BOTH},
+{"Layer3Forwarding", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,tLayer3ForwardingObj, tLayer3ForwardingParam, NULL, BBFDM_BOTH},
+{"Layer2Bridging", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,tLayer2BridgingObj, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"Wifi", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,tsewifiObj, NULL, NULL, BBFDM_BOTH},
+{"DownloadDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,NULL, tDownloadDiagnosticsParam, NULL, BBFDM_BOTH},
+{"UploadDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,NULL, tUploadDiagnosticsParam, NULL, BBFDM_BOTH},
+{"XMPP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL,tXMPPObj, tXMPPParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMOBJ tEntry181ObjUPNP[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{(char *)&dmroot, &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, tRoot181ObjUPNP, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMOBJ tRoot181ObjUPNP[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"BBF", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, tRoot181ObjUPNPBBF, NULL, NULL, BBFDM_BOTH},
+{"UPnP", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, tRoot181ObjUPNPDMROOT, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMOBJ tRoot181ObjUPNPDMROOT[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"DM", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, tRoot181ObjUPNPDM, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMOBJ tRoot181ObjUPNPDM[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"DeviceInfo", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,upnpDeviceInfoObj, upnpDeviceInfoParams, NULL, BBFDM_BOTH},
+{"Configuration", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,upnpConfigurationObj, NULL, NULL, BBFDM_BOTH},
+{"Monitoring", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,upnpMonitoringObj, upnpMonitoringParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMOBJ tRoot181ObjUPNPBBF[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"DeviceInfo", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,tDeviceInfoObj, tDeviceInfoParams, NULL, BBFDM_BOTH},
+{"ManagementServer", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,NULL, tManagementServerParams, NULL, BBFDM_BOTH},
+{"Time", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tTimeParams, NULL, BBFDM_BOTH, BBFDM_BOTH},
+{"UPnP", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,tUPnPObj, NULL, NULL, BBFDM_BOTH},
+#if BBF_TR104
+{"VoiceService", &DMREAD, NULL, NULL, NULL, browseVoiceServiceInst, NULL, NULL, tVoiceServiceObj, tVoiceServiceParam, NULL, BBFDM_BOTH},
+#endif
+{CUSTOM_PREFIX"ICE", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_IceParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"IGMP", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_IgmpParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"IpAccCfg", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,tSe_IpAccObj, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"LoginCfg", &DMREAD, NULL, NULL, NULL, NULL,NULL, &DMNONE,NULL, tSe_LoginCfgParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"PowerManagement", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_PowerManagementParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"SyslogCfg", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_SyslogCfgParam, NULL, BBFDM_BOTH},
+{"SoftwareModules", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,tSoftwareModulesObj, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"Owsd", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,XIopsysEuOwsdObj, XIopsysEuOwsdParams, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"Dropbear", &DMWRITE, add_dropbear_instance, delete_dropbear_instance, NULL, browseXIopsysEuDropbear, NULL, &DMNONE, NULL, X_IOPSYS_EU_DropbearParams, NULL, BBFDM_BOTH, BBFDM_BOTH},
+{CUSTOM_PREFIX"Buttons", &DMREAD, NULL, NULL, NULL, browseXIopsysEuButton, NULL, &DMNONE, NULL, X_IOPSYS_EU_ButtonParams, NULL, BBFDM_BOTH},
+{"Bridging",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tBridgingObj, NULL, NULL, BBFDM_BOTH},
+{"WiFi",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tWifiObj, NULL, NULL, BBFDM_BOTH},
+{"IP",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPObj, NULL, NULL, BBFDM_BOTH},
+{"Ethernet", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tEthernetObj, NULL, NULL, BBFDM_BOTH},
+{"DSL",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDslObj, NULL, NULL, BBFDM_BOTH},
+{"ATM",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tAtmObj, NULL, NULL, BBFDM_BOTH},
+{"PTM", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tPtmObj, NULL, NULL, BBFDM_BOTH},
+{"DHCPv4", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDhcpv4Obj, NULL, NULL, BBFDM_BOTH},
+{"Hosts", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, thostsObj, thostsParam, NULL, BBFDM_BOTH},
+{"NAT", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tnatObj, NULL, NULL, BBFDM_BOTH},
+{"PPP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tpppObj, NULL, NULL, BBFDM_BOTH},
+{"Routing", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tRoutingObj, tRoutingParam, NULL, BBFDM_BOTH},
+{"XMPP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL,tXMPPObj, tXMPPParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+UPNP_SUPPORTED_DM tUPNPSupportedDM[];
+UPNP_SUPPORTED_DM tUPNPSupportedDM_098[] = {
+{"/UPnP/DM/DeviceInfo/", "urn:UPnP:Parent Device:1:ConfigurationManagement:2", DMROOT_URL_098, "UPnP DeviceInfo from "DMROOT_DESC_098, ""},
+{"/UPnP/DM/Configuration/", "urn:UPnP:Parent Device:1:ConfigurationManagement:2", DMROOT_URL_098, "Configuration from "DMROOT_DESC_098, ""},
+{"/UPnP/DM/Monitoring/", "urn:UPnP:Parent Device:1:ConfigurationManagement:2", DMROOT_URL_098, "Monitoring from "DMROOT_DESC_098, ""},
+{"/BBF/DeviceInfo/", DMROOT_URI_098, DMROOT_URL_098, "DeviceInfo from "DMROOT_DESC_098, ""},
+{"/BBF/ManagementServer/", DMROOT_URI_098, DMROOT_URL_098, "ManagementServer from "DMROOT_DESC_098, ""},
+{"/BBF/Time/", DMROOT_URI_098, DMROOT_URL_098, "Time from "DMROOT_DESC_098, ""},
+{"/BBF/UPnP/", DMROOT_URI_098, DMROOT_URL_098, "UPnP from "DMROOT_DESC_098, ""},
+{"/BBF/VoiceService/", "urn:broadband-forum-org:wt-104-2-0-0", "https://www.broadband-forum.org/cwmp/tr-104-2-0-0.html", "TR-104 Voice:2 Service Object definition", ""},
+{"/BBF/"CUSTOM_PREFIX"ICE/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for ICE", ""},
+{"/BBF/"CUSTOM_PREFIX"IGMP/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for ICE", ""},
+{"/BBF/"CUSTOM_PREFIX"IpAccCfg/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for IGMP", ""},
+{"/BBF/"CUSTOM_PREFIX"LoginCfg/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for LoginCfg", ""},
+{"/BBF/"CUSTOM_PREFIX"PowerManagement/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for PowerManagement", ""},
+{"/BBF/"CUSTOM_PREFIX"SyslogCfg/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for SyslogCfg", ""},
+{"/BBF/SoftwareModules/", DMROOT_URI_098, DMROOT_URL_098, "SoftwareModules from "DMROOT_DESC_098, ""},
+{"/BBF/"CUSTOM_PREFIX"Owsd/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for Owsd", ""},
+{"/BBF/"CUSTOM_PREFIX"Dropbear/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for Dropbear", ""},
+{"/BBF/"CUSTOM_PREFIX"Buttons/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for Buttons", ""},
+{"/BBF/LANDevice/", DMROOT_URI_098, DMROOT_URL_098, "LANDevice from "DMROOT_DESC_098, ""},
+{"/BBF/WANDevice/", DMROOT_URI_098, DMROOT_URL_098, "WANDevice from "DMROOT_DESC_098, ""},
+{"/BBF/LANInterfaces/", DMROOT_URI_098, DMROOT_URL_098, "LANInterfaces from "DMROOT_DESC_098, ""},
+{"/BBF/IPPingDiagnostics/", DMROOT_URI_098, DMROOT_URL_098, "IPPingDiagnostics from "DMROOT_DESC_098, ""},
+{"/BBF/Layer3Forwarding/", DMROOT_URI_098, DMROOT_URL_098, "Layer3Forwarding from "DMROOT_DESC_098, ""},
+{"/BBF/Layer2Bridging/", DMROOT_URI_098, DMROOT_URL_098, "Layer2Bridging from "DMROOT_DESC_098, ""},
+{"/BBF/"CUSTOM_PREFIX"Wifi/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for WiFi", ""},
+{"/BBF/DownloadDiagnostics/", DMROOT_URI_098, DMROOT_URL_098, "DownloadDiagnostics from "DMROOT_DESC_098, ""},
+{"/BBF/UploadDiagnostics/", DMROOT_URI_098, DMROOT_URL_098, "UploadDiagnostics from "DMROOT_DESC_098, ""},
+{"/BBF/XMPP/", DMROOT_URI_098, DMROOT_URL_098, "XMPP from "DMROOT_DESC_098, ""},
+{0}
+};
+
+UPNP_SUPPORTED_DM tUPNPSupportedDM_181[] = {
+{"/UPnP/DM/DeviceInfo/", "urn:UPnP:Parent Device:1:ConfigurationManagement:2", DMROOT_URL_181, "UPnP DeviceInfo from "DMROOT_DESC_181, ""},
+{"/UPnP/DM/Configuration/", "urn:UPnP:Parent Device:1:ConfigurationManagement:2", DMROOT_URL_181, "Configuration from "DMROOT_DESC_181, ""},
+{"/UPnP/DM/Monitoring/", "urn:UPnP:Parent Device:1:ConfigurationManagement:2", DMROOT_URL_181, "Monitoring from "DMROOT_DESC_181, ""},
+{"/BBF/DeviceInfo/", DMROOT_URI_181, DMROOT_URL_181, "DeviceInfo from "DMROOT_DESC_181, ""},
+{"/BBF/ManagementServer/", DMROOT_URI_181, DMROOT_URL_181, "ManagementServer from "DMROOT_DESC_181, ""},
+{"/BBF/Time/", DMROOT_URI_181, DMROOT_URL_181, "Time from "DMROOT_DESC_181, ""},
+{"/BBF/UPnP/", DMROOT_URI_181, DMROOT_URL_181, "UPnP from "DMROOT_DESC_181, ""},
+{"/BBF/VoiceService/", "urn:broadband-forum-org:wt-104-2-0-0", "https://www.broadband-forum.org/cwmp/tr-104-2-0-0.html", "TR-104 Voice:2 Service Object definition", ""},
+{"/BBF/"CUSTOM_PREFIX"ICE/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for ICE", ""},
+{"/BBF/"CUSTOM_PREFIX"IGMP/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for ICE", ""},
+{"/BBF/"CUSTOM_PREFIX"IpAccCfg/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for IGMP", ""},
+{"/BBF/"CUSTOM_PREFIX"LoginCfg/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for LoginCfg", ""},
+{"/BBF/"CUSTOM_PREFIX"PowerManagement/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for PowerManagement", ""},
+{"/BBF/"CUSTOM_PREFIX"SyslogCfg/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for SyslogCfg", ""},
+{"/BBF/SoftwareModules/", DMROOT_URI_181, DMROOT_URL_181, "SoftwareModules from "DMROOT_DESC_181, ""},
+{"/BBF/"CUSTOM_PREFIX"Owsd/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for Owsd", ""},
+{"/BBF/"CUSTOM_PREFIX"Dropbear/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for Dropbear", ""},
+{"/BBF/"CUSTOM_PREFIX"Buttons/", "urn:intenogroup-com:na", "https://www.intenogroup.com/", "Inteno extension for Buttons", ""},
+{"/BBF/Bridging/", DMROOT_URI_181, DMROOT_URL_181, "Bridging from "DMROOT_DESC_181, ""},
+{"/BBF/WiFi/", DMROOT_URI_181, DMROOT_URL_181, "WiFi from "DMROOT_DESC_181, ""},
+{"/BBF/IP/", DMROOT_URI_181, DMROOT_URL_181, "IP from "DMROOT_DESC_181, ""},
+{"/BBF/Ethernet/", DMROOT_URI_181, DMROOT_URL_181, "Ethernet from "DMROOT_DESC_181, ""},
+{"/BBF/DSL/", DMROOT_URI_181, DMROOT_URL_181, "DSL from "DMROOT_DESC_181, ""},
+{"/BBF/ATM/", DMROOT_URI_181, DMROOT_URL_181, "ATM from "DMROOT_DESC_181, ""},
+{"/BBF/PTM/", DMROOT_URI_181, DMROOT_URL_181, "PTM from "DMROOT_DESC_181, ""},
+{"/BBF/DHCPv4/", DMROOT_URI_181, DMROOT_URL_181, "DHCPv4 from "DMROOT_DESC_181, ""},
+{"/BBF/Hosts/", DMROOT_URI_181, DMROOT_URL_181, "Hosts from "DMROOT_DESC_181, ""},
+{"/BBF/NAT/", DMROOT_URI_181, DMROOT_URL_181, "NAT from "DMROOT_DESC_181, ""},
+{"/BBF/PPP/", DMROOT_URI_181, DMROOT_URL_181, "PPP from "DMROOT_DESC_181, ""},
+{"/BBF/Routing/", DMROOT_URI_181, DMROOT_URL_181, "Routing from "DMROOT_DESC_181, ""},
+{"/BBF/XMPP/", DMROOT_URI_181, DMROOT_URL_181, "XMPP from "DMROOT_DESC_181, ""},
+{0}
+};
+
+size_t tr98_size = sizeof(tUPNPSupportedDM_098);
+size_t tr181_size = sizeof(tUPNPSupportedDM_181);
+#endif
diff --git a/dmtree/tr064/upnp_device.h b/dmtree/tr064/upnp_device.h
new file mode 100644
index 00000000..6fe18289
--- /dev/null
+++ b/dmtree/tr064/upnp_device.h
@@ -0,0 +1,44 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Imen Bhiri
+* Author: Anis Ellouze
+* Author: Amin Ben Ramdhane
+*/
+
+#ifndef __UPNPDEVICE_H
+#define __UPNPDEVICE_H
+
+#ifdef BBF_TR064
+extern DMOBJ tEntry098ObjUPNP[];
+extern DMOBJ tRoot098ObjUPNP[];
+extern DMOBJ tRoot098ObjUPNPDMROOT[];
+extern DMOBJ tRoot098ObjUPNPDM[];
+extern DMOBJ tRoot098ObjUPNPBBF[];
+extern DMOBJ tEntry181ObjUPNP[];
+extern DMOBJ tRoot181ObjUPNP[];
+extern DMOBJ tRoot181ObjUPNPDMROOT[];
+extern DMOBJ tRoot181ObjUPNPDM[];
+extern DMOBJ tRoot181ObjUPNPBBF[];
+extern UPNP_SUPPORTED_DM tUPNPSupportedDM[];
+extern UPNP_SUPPORTED_DM tUPNPSupportedDM_098[];
+extern UPNP_SUPPORTED_DM tUPNPSupportedDM_181[];
+extern size_t tr98_size;
+extern size_t tr181_size;
+
+#define UPNP_SUPPORTED_PARAMETERS_VERSION 1 //Should be incremented each time the Parameters are updated
+#define UPNP_SUPPORTED_DATAMODEL_VERSION 1 //Should be incremented each time the tUPNPSupportedDM array is updated
+
+#define DMROOT_URI_098 "urn:broadband-forum-org:tr-098-1-8-0"
+#define DMROOT_URL_098 "https://www.broadband-forum.org/cwmp/tr-098-1-8-0.html"
+#define DMROOT_DESC_098 "TR-098 InternetGatewayDevice:1 Root Object definition"
+#define DMROOT_URI_181 "urn:broadband-forum-org:tr-181-2-11-0"
+#define DMROOT_URL_181 "https://www.broadband-forum.org/cwmp/tr-181-2-11-0.html"
+#define DMROOT_DESC_181 "TR-181 Device:2 Root Object definition"
+
+#endif
+#endif
diff --git a/dmtree/tr064/upnp_deviceinfo.c b/dmtree/tr064/upnp_deviceinfo.c
new file mode 100755
index 00000000..df8d9066
--- /dev/null
+++ b/dmtree/tr064/upnp_deviceinfo.c
@@ -0,0 +1,266 @@
+#include
+#include "dmcwmp.h"
+#include "upnp_deviceinfo.h"
+#include
+#include "dmuci.h"
+#include "dmmem.h"
+#include "dmcommon.h"
+#include
+#include "upnp_common.h"
+#include
+
+int upnp_browseNetworkInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+/**************************************************************************
+*
+* /UPnP/DM/DeviceInfo/ datamodel tree
+*
+***************************************************************************/
+
+/*** /UPnP/DM/DeviceInfo/ objects ***/
+DMOBJ upnpDeviceInfoObj[] ={
+{"PhysicalDevice", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,upnpPhysicalDeviceObj, upnpPhysicalDeviceParams, NULL},
+{"OperatingSystem",&DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,NULL, upnpOperatingSystemParams, NULL},
+{"ExecutionEnvironment",&DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,NULL, upnpExecutionEnvironmentParams, NULL},
+{0}
+};
+
+/*** /UPnP/DM/DeviceInfo/ parameters ***/
+DMLEAF upnpDeviceInfoParams[] = {
+{"ProvisioningCode", &DMWRITE, DMT_STRING, upnp_deviceinfo_get_provisionning_code, upnp_deviceinfo_set_provisionning_code, &DMFINFRM, NULL},
+{"SoftwareVersion", &DMREAD, DMT_STRING, upnp_deviceinfo_get_software_version, NULL, &DMFINFRM, NULL},
+{"SoftwareDescription", &DMREAD, DMT_STRING, upnp_deviceinfo_get_software_description, NULL, &DMFINFRM, NULL},
+{"UpTime", &DMREAD, DMT_UNINT, upnp_deviceinfo_get_up_time, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+/*** /UPnP/DM/DeviceInfo/PhysicalDevice/ objects ***/
+DMOBJ upnpPhysicalDeviceObj[] = {
+{"DeviceID", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,NULL, upnpDeviceIdParams, NULL},
+{0}
+};
+
+/*** /UPnP/DM/DeviceInfo/PhysicalDevice/ parameters ***/
+DMLEAF upnpPhysicalDeviceParams[] = {
+{"HardwareVersion", &DMREAD, DMT_STRING, upnp_deviceinfo_get_hardware_version, NULL, &DMFINFRM, NULL},
+{"NetworkInterfaceNumberOfEntries", &DMREAD, DMT_UNINT, upnp_deviceinfo_get_network_interface_number_entries, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+/*** /UPnP/DM/DeviceInfo/OperatingSystem/ parameters ***/
+DMLEAF upnpOperatingSystemParams[] = {
+{"SoftwareVersion", &DMREAD, DMT_STRING, upnp_deviceinfo_get_software_version, NULL, &DMFINFRM, NULL},
+{"SoftwareDescription", &DMREAD, DMT_STRING, upnp_deviceinfo_get_software_description, NULL, &DMFINFRM, NULL},
+{"UpTime", &DMREAD, DMT_UNINT, upnp_deviceinfo_get_up_time, NULL, &DMFINFRM, NULL},
+{"WillReboot", &DMREAD, DMT_BOOL, upnp_deviceinfo_get_will_reboot, NULL, &DMFINFRM, NULL},
+{"WillBaselineReset", &DMREAD, DMT_BOOL, upnp_deviceinfo_get_will_base_line_reset, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+/*** /UPnP/DM/DeviceInfo/ExecutionEnvironment/ parameters ***/
+DMLEAF upnpExecutionEnvironmentParams[] = {
+{"Status", &DMREAD, DMT_STRING, upnp_deviceinfo_get_status, NULL, &DMFINFRM, NULL},
+{"Uptime", &DMREAD, DMT_UNINT, upnp_deviceinfo_get_up_time, NULL, &DMFINFRM, NULL},
+{"SoftwareVersion", &DMREAD, DMT_STRING, upnp_deviceinfo_get_software_version, NULL, &DMFINFRM, NULL},
+{"SoftwareDescription", &DMREAD, DMT_STRING, upnp_deviceinfo_get_software_description, NULL, &DMFINFRM, NULL},
+{"WillReboot", &DMREAD, DMT_BOOL, upnp_deviceinfo_get_will_reboot, NULL, &DMFINFRM, NULL},
+{"WillBaselineReset", &DMREAD, DMT_BOOL, upnp_deviceinfo_get_will_base_line_reset, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+/*** /UPnP/DM/DeviceInfo/DeviceID/ parameters ***/
+DMLEAF upnpDeviceIdParams[] = {
+{"ManufacturerOUI", &DMREAD, DMT_HEXBIN, upnp_deviceinfo_get_manufacturer_oui, NULL, &DMFINFRM, NULL},
+{"ProductClass", &DMREAD, DMT_STRING, upnp_deviceinfo_get_product_class, NULL, &DMFINFRM, NULL},
+{"SerialNumber", &DMREAD, DMT_STRING, upnp_deviceinfo_get_serial_number, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+
+/**************************************************************************
+*
+* /UPnP/DM/DeviceInfo/* parameters functions
+*
+***************************************************************************/
+
+int upnp_deviceinfo_get_provisionning_code(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ dmuci_get_option_value_string("cwmp", "cpe", "provisioning_code", value);
+ return 0;
+}
+
+int upnp_deviceinfo_get_software_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ char *v = NULL, *tmp = NULL, *val = NULL;
+
+ db_get_value_string("hw", "board", "iopVersion", &v);
+ if(v == NULL || strlen(v)<=0) {
+ *value = NULL;
+ return 0;
+ }
+ tmp = dmstrdup(v);// MEM WILL BE FREED IN DMMEMCLEAN
+ *value = tmp;
+ return 0;
+}
+
+int upnp_deviceinfo_get_software_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct utsname unameData;
+ uname(&unameData);
+
+ dmasprintf(value, "GNU/%s",unameData.sysname);
+ return 0;
+}
+
+int upnp_deviceinfo_get_up_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ FILE* fp = NULL;
+ char *pch = NULL, *spch = NULL;
+ char buf[64];
+ *value = "0";
+
+ fp = fopen("/proc/uptime", "r");
+ if (fp != NULL) {
+ fgets(buf, 64, fp);
+ pch = strtok_r(buf, ".", &spch);
+ if (pch)
+ *value = dmstrdup(pch); // MEM WILL BE FREED IN DMMEMCLEAN
+ fclose(fp);
+ }
+ return 0;
+}
+
+int upnp_deviceinfo_get_hardware_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ db_get_value_string("hw", "board", "hardwareVersion", value);
+ return 0;
+}
+
+int upnp_deviceinfo_get_network_interface_number_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ int n = upnp_get_NetworkInterfaceNumberOfEntries();
+ dmasprintf(value, "%d",n);
+ return 0;
+}
+
+int upnp_deviceinfo_get_manufacturer_oui(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ dmuci_get_option_value_string("cwmp", "cpe", "override_oui", value);
+ if(*value == NULL || strlen(value)<=0) {
+ *value = NULL;
+ return 0;
+ }
+ if (*value[0] == '\0')
+ *value = upnp_get_deviceid_manufactureroui();
+ return 0;
+}
+
+
+int upnp_deviceinfo_get_product_class(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ char *v = NULL, *tmp = NULL, *val = NULL;
+
+ db_get_value_string("hw", "board", "iopVerBoard", &v);
+ if(v == NULL || strlen(v)<=NULL){
+ *value = NULL;
+ return 0;
+ }
+ tmp = dmstrdup(v);// MEM WILL BE FREED IN DMMEMCLEAN
+ val = tmp;
+ return 0;
+}
+
+int upnp_deviceinfo_get_serial_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ db_get_value_string("hw", "board", "serialNumber", value);
+ return 0;
+}
+
+int upnp_deviceinfo_get_system_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ return 0;
+}
+
+int upnp_deviceinfo_get_mac_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ return 0;
+}
+
+int upnp_deviceinfo_get_interface_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ return 0;
+}
+
+int upnp_deviceinfo_get_will_reboot(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ return 0;
+}
+
+int upnp_deviceinfo_get_will_base_line_reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ return 0;
+}
+
+int upnp_deviceinfo_get_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ return 0;
+}
+
+
+int upnp_deviceinfo_set_provisionning_code(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp", "cpe", "provisioning_code", value);
+ return 0;
+ }
+ return 0;
+}
+
+
+/*************************************************
+ *
+ * MultiInstance objects browsing functions
+ *
+ *************************************************/
+
+int upnp_deviceinfo_networkinterface_createinstance(char *refparam, struct dmctx *ctx, void *data, char **instance){
+ char *value = NULL;
+ char *iface_instance = NULL, ib[8], ip_name[32];
+ char *p = ip_name;
+ struct uci_section *iface_sec = NULL;
+
+ iface_instance = get_last_instance("network","interface","upnp_iface_int_instance");
+ sprintf(ib, "%d", iface_instance ? atoi(iface_instance)+1 : 1);
+ dmstrappendstr(p, "ip_interface_");
+ dmstrappendstr(p, ib);
+ dmstrappendend(p);
+ sprintf(ib, "%d", iface_instance ? atoi(iface_instance)+1 : 1);
+ dmuci_add_section_and_rename("network", "interface", &iface_sec, &value);
+ dmuci_set_value("network", ip_name, "", "interface");
+ dmuci_set_value("network", ip_name, "proto", "dhcp");
+ *instance = update_instance(iface_sec, iface_instance, "upnp_iface_int_instance");
+ return 0;
+}
+
+int upnp_deviceinfo_networkinterface_deleteinstance(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action){
+ switch (del_action) {
+ case DEL_INST:
+ dmuci_set_value_by_section(((struct upnp_dvinf_args *)data)->upnp_deviceinfo_sec, "proto", "");
+ dmuci_set_value_by_section(((struct upnp_dvinf_args *)data)->upnp_deviceinfo_sec, "type", "");
+ dmuci_set_value_by_section(((struct upnp_dvinf_args *)data)->upnp_deviceinfo_sec, "bridge_instance", "");
+ dmuci_set_value_by_section(((struct upnp_dvinf_args *)data)->upnp_deviceinfo_sec, "ip_int_instance", "");
+ dmuci_set_value_by_section(((struct upnp_dvinf_args *)data)->upnp_deviceinfo_sec, "ipv4_instance", "");
+ dmuci_set_value_by_section(((struct upnp_dvinf_args *)data)->upnp_deviceinfo_sec, "ipv6_instance", "");
+ dmuci_set_value_by_section(((struct upnp_dvinf_args *)data)->upnp_deviceinfo_sec, "ifname", "");
+ dmuci_set_value_by_section(((struct upnp_dvinf_args *)data)->upnp_deviceinfo_sec, "ipaddr", "");
+ dmuci_set_value_by_section(((struct upnp_dvinf_args *)data)->upnp_deviceinfo_sec, "ip6addr", "");
+ break;
+ case DEL_ALL:
+ return FAULT_9005;
+ }
+ return 0;
+}
+
+int upnp_browseNetworkInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance){
+ struct uci_section *net_sec = NULL;
+ char *iface_int = NULL, *iface_int_last = NULL, *interfaceType = NULL, *macAddress = NULL;
+ struct upnp_dvinf_args curr_upnp_deviceinfo_args = {0};
+ uci_foreach_sections("network", "interface", net_sec) {
+ curr_upnp_deviceinfo_args.upnp_deviceinfo_sec = net_sec;
+ dmuci_get_value_by_section_string(net_sec, "type", &interfaceType);
+ upnp_getMacAddress(section_name(net_sec), &macAddress);
+ dmasprintf(&curr_upnp_deviceinfo_args.systemName, "%s", section_name(net_sec));
+ dmasprintf(&curr_upnp_deviceinfo_args.macAddress, "%s", macAddress);
+ dmasprintf(&curr_upnp_deviceinfo_args.interfaceType, "%s", interfaceType);
+ iface_int = handle_update_instance(1, dmctx, &iface_int_last, update_instance_alias, 3, net_sec, "upnp_iface_int_instance", "upnp_iface_int_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_upnp_deviceinfo_args, iface_int) == DM_STOP) break;
+ }
+}
diff --git a/dmtree/tr064/upnp_deviceinfo.h b/dmtree/tr064/upnp_deviceinfo.h
new file mode 100755
index 00000000..ea4dc109
--- /dev/null
+++ b/dmtree/tr064/upnp_deviceinfo.h
@@ -0,0 +1,41 @@
+#ifndef UPNP_DEVICEINFO_H
+#define UPNP_DEVICEINFO_H
+#include "dmcwmp.h"
+
+struct upnp_dvinf_args
+{
+ struct uci_section *upnp_deviceinfo_sec;
+ char* systemName;
+ char* macAddress;
+ char* interfaceType;
+};
+
+int upnp_deviceinfo_get_provisionning_code(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_software_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_software_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_up_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_hardware_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_network_interface_number_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_manufacturer_oui(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_product_class(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_serial_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_system_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_mac_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_interface_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_will_reboot(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_will_base_line_reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_deviceinfo_get_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int upnp_deviceinfo_set_provisionning_code(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int upnp_deviceinfo_networkinterface_createinstance(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int upnp_deviceinfo_networkinterface_deleteinstance(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+extern DMLEAF upnpDeviceIdParams[];
+extern DMLEAF upnpNetworkInterfaceParams[];
+extern DMOBJ upnpPhysicalDeviceObj[];
+extern DMLEAF upnpPhysicalDeviceParams[];
+extern DMLEAF upnpOperatingSystemParams[];
+extern DMLEAF upnpExecutionEnvironmentParams[];
+extern DMOBJ upnpDeviceInfoObj[];
+extern DMLEAF upnpDeviceInfoParams[];
+#endif
diff --git a/dmtree/tr064/upnp_monitoring.c b/dmtree/tr064/upnp_monitoring.c
new file mode 100755
index 00000000..0025d80a
--- /dev/null
+++ b/dmtree/tr064/upnp_monitoring.c
@@ -0,0 +1,145 @@
+#include "dmcwmp.h"
+#include "upnp_monitoring.h"
+#include "upnp_common.h"
+#include "dmubus.h"
+#include "dmcommon.h"
+#include "dmjson.h"
+#include
+
+/**************************************************************************
+*
+* /UPnP/DM/Monitoring/ datamodel tree
+*
+***************************************************************************/
+
+/*** /UPnP/DM/Monitoring/ objects ***/
+DMOBJ upnpMonitoringObj[] = {
+{"OperatingSystem",&DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, NULL, upnpMonitoringOperatingSystemParams, NULL},
+{"ExecutionEnvironment",&DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, NULL, upnpMonitoringExecutionEnvironmentParams, NULL},
+{"IPUsage",&DMREAD, NULL, NULL, NULL, upnp_BrowseIPUsage, &DMFINFRM, &DMNONE, NULL, upnpMonitoringIPUsageParams, NULL},
+{0}
+};
+
+/*** /UPnP/DM/Monitoring/ parameters ***/
+DMLEAF upnpMonitoringParams[] = {
+{"IPUsageNumberOfEntries", &DMREAD, DMT_UNINT, upnp_monitoring_get_IPUsageNumberOfEntries, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+/*** /UPnP/DM/Monitoring/OperatingSystem parameters ***/
+DMLEAF upnpMonitoringOperatingSystemParams[] = {
+{"CurrentTime", &DMREAD, DMT_TIME, upnp_monitoring_get_CurrentTime, NULL, &DMFINFRM, NULL},
+{"CPUUsage", &DMREAD, DMT_UNINT, upnp_monitoring_get_CPUUsage, NULL, &DMFINFRM, NULL},
+{"MemoryUsage", &DMREAD, DMT_UNINT, upnp_monitoring_get_MemoryUsage, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+/*** /UPnP/DM/Monitoring/ExecutionEnvironement parameters ***/
+ DMLEAF upnpMonitoringExecutionEnvironmentParams[] = {
+{"CPUUsage", &DMREAD, DMT_UNINT, upnp_monitoring_get_CPUUsage, NULL, &DMFINFRM, NULL},
+{"MemoryUsage", &DMREAD, DMT_UNINT, upnp_monitoring_get_MemoryUsage, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+/*** /UPnP/DM/Monitoring/Usage parameters ***/
+DMLEAF upnpMonitoringIPUsageParams[] = {
+{"SystemName", &DMREAD, DMT_STRING, upnp_monitoring_get_SystemName, NULL, &DMFINFRM, NULL},
+{"Status", &DMREAD, DMT_STRING, upnp_monitoring_get_Status, NULL, &DMFINFRM, NULL},
+{"TotalPacketsSent", &DMREAD, DMT_UNINT, upnp_monitoring_get_TotalPacketsSent, NULL, &DMFINFRM, NULL},
+{"TotalPacketsReceived", &DMREAD, DMT_UNINT, upnp_monitoring_get_TotalPacketsReceived, NULL, &DMFINFRM, NULL},
+{0}
+};
+
+/**************************************************************************
+*
+* /UPnP/DM/Monitoring/* parameters functions
+*
+***************************************************************************/
+int upnp_monitoring_get_IPUsageNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ int n = upnp_get_IPInterfaceNumberOfEntries();
+ dmasprintf(value, "%d", n);
+ return 0;
+}
+
+
+int upnp_monitoring_get_CurrentTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ time_t rawtime;
+ struct tm * timeinfo = NULL;
+
+ time ( &rawtime );
+ timeinfo = localtime ( &rawtime );
+ dmasprintf(value, "%d:%d:%d", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
+ return 0;
+}
+
+int upnp_monitoring_get_CPUUsage(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ return 0;
+}
+
+int upnp_monitoring_get_MemoryUsage(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ json_object *res = NULL;
+ char *totalmemory = NULL, *freememory = NULL;
+ int total, free;
+
+ dmubus_call("system", "info", UBUS_ARGS{{}}, 0, &res);
+ if(res == NULL) {
+ *value = NULL;
+ return 0;
+ }
+ DM_ASSERT(res, freememory = "");
+ DM_ASSERT(res, totalmemory = "");
+ totalmemory = dmjson_get_value(res, 2, "memory", "total");
+ freememory = dmjson_get_value(res, 2, "memory", "freememory");
+ total = atoi(totalmemory);
+ free = atoi(freememory);
+ dmasprintf(value, "%d", total - free);
+ return 0;
+}
+
+int upnp_monitoring_get_SystemName(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct upnp_ip_usage_args *ipusage_args = (struct upnp_ip_usage_args *)data;
+ if(ipusage_args->systemName != NULL && strlen(ipusage_args->systemName)>0)
+ dmasprintf(value, "%s", ipusage_args->systemName);
+ return 0;
+}
+
+int upnp_monitoring_get_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct upnp_ip_usage_args *ipusage_args = (struct upnp_ip_usage_args *)data;
+ if(ipusage_args->status != NULL && strlen(ipusage_args->status)>0)
+ dmasprintf(value, "%s", ipusage_args->status);
+ return 0;
+}
+
+int upnp_monitoring_get_TotalPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct upnp_ip_usage_args *ipusage_args = (struct upnp_ip_usage_args *)data;
+ if(ipusage_args->totalpacketsent != NULL && strlen(ipusage_args->totalpacketsent)>0)
+ dmasprintf(value, "%s", ipusage_args->totalpacketsent);
+ return 0;
+}
+
+int upnp_monitoring_get_TotalPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct upnp_ip_usage_args *ipusage_args = (struct upnp_ip_usage_args *)data;
+ if(ipusage_args->totalpacketreceived != NULL && strlen(ipusage_args->totalpacketreceived)>0)
+ dmasprintf(value, "%s", ipusage_args->totalpacketreceived);
+ return 0;
+}
+
+int upnp_BrowseIPUsage(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance){
+ struct uci_section *net_sec = NULL;
+ struct upnp_ip_usage_args curr_ip_usage_args = {0};
+ char *iface_int = NULL, *iface_int_last = NULL, *totalPktSnt = NULL, *totalPktRcvd= NULL, *status = NULL;
+ int i = 0;
+ uci_foreach_sections("network", "interface", net_sec) {
+ dmasprintf(&curr_ip_usage_args.systemName, "%s", section_name(net_sec));
+ upnp_getInterfaceStatus(section_name(net_sec), &status);
+ if(status !=NULL) dmasprintf(&curr_ip_usage_args.status, "%s", status); else dmasprintf(&curr_ip_usage_args.status, "");
+ upnp_getInterfaceTotalPacketSent(section_name(net_sec), &totalPktSnt);
+ if(totalPktSnt != NULL) dmasprintf(&curr_ip_usage_args.totalpacketsent, "%s", totalPktSnt); else dmasprintf(&curr_ip_usage_args.totalpacketsent, "");
+ upnp_getInterfaceTotalPacketReceived(section_name(net_sec), &totalPktRcvd);
+ if(totalPktRcvd !=NULL) dmasprintf(&curr_ip_usage_args.totalpacketreceived, "%s", totalPktRcvd); else dmasprintf(&curr_ip_usage_args.totalpacketreceived, "");
+ iface_int = handle_update_instance(1, dmctx, &iface_int_last, update_instance_alias, 3, net_sec, "upnp_ip_usage_instance", "upnp_ip_usage_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_ip_usage_args, iface_int) == DM_STOP) break;
+ i++;
+ }
+ return 0;
+}
diff --git a/dmtree/tr064/upnp_monitoring.h b/dmtree/tr064/upnp_monitoring.h
new file mode 100755
index 00000000..260da80a
--- /dev/null
+++ b/dmtree/tr064/upnp_monitoring.h
@@ -0,0 +1,34 @@
+#ifndef UPNP_MONITORING_H
+#define UPNP_MONITORING_H
+#include "dmcwmp.h"
+struct upnp_ip_usage_args{
+ char *systemName;
+ char *status;
+ char *totalpacketsent;
+ char *totalpacketreceived;
+};
+
+int upnp_monitoring_get_IPUsageNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_monitoring_get_StorageNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_monitoring_get_CurrentTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_monitoring_get_CPUUsage(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_monitoring_get_MemoryUsage(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_monitoring_get_SystemName(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_monitoring_get_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_monitoring_get_TotalPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int upnp_monitoring_get_TotalPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int upnp_BrowseIPUsage(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int upnp_CreateIPUsageInstance(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int upnp_DeleteIPUsageInstance(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int upnp_BrowseStorage(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int upnp_CreateStorageInstance(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int upnp_DeleteStorageInstance(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+
+extern DMLEAF upnpMonitoringOperatingSystemParams[];
+extern DMLEAF upnpMonitoringExecutionEnvironmentParams[];
+extern DMLEAF upnpMonitoringIPUsageParams[];
+extern DMLEAF upnpMonitoringStorageParams[];
+extern DMOBJ upnpMonitoringObj[];
+extern DMLEAF upnpMonitoringParams[];
+#endif
diff --git a/dmtree/tr104/voice_services.c b/dmtree/tr104/voice_services.c
new file mode 100644
index 00000000..34b36091
--- /dev/null
+++ b/dmtree/tr104/voice_services.c
@@ -0,0 +1,2459 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2012-2014 PIVA SOFTWARE (www.pivasoftware.com)
+ * Author: Imen Bhiri
+ * Author: Anis Ellouze
+ * Author: Omar Kallel
+ */
+
+#include
+#include
+#include
+#include "dmcwmp.h"
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcommon.h"
+#include "voice_services.h"
+#include "dmjson.h"
+
+/*** DMROOT.Services. ****/
+DMOBJ tServiceObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"VoiceService", &DMREAD, NULL, NULL, NULL, browseVoiceServiceInst, NULL, NULL, tVoiceServiceObj, tVoiceServiceParam, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}. ****/
+DMOBJ tVoiceServiceObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Capabilities", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tCapabilitiesObj, tCapabilitiesParams, NULL, BBFDM_BOTH},
+{"VoiceProfile", &DMWRITE, add_profile_object, delete_profile_object, NULL, browseProfileInst, NULL, NULL, tProfileObj, tProfileParam, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tVoiceServiceParam[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_service_alias, set_service_alias, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.Capabilities. ****/
+DMOBJ tCapabilitiesObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"SIP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tSIPParams, NULL, BBFDM_BOTH},
+{"Codecs", &DMREAD, NULL, NULL, NULL, browseCodecsInst, NULL, NULL, NULL, tCodecsParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tCapabilitiesParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"MaxProfileCount", &DMREAD, DMT_UNINT, get_max_profile_count, NULL, NULL, NULL, BBFDM_BOTH},
+{"MaxLineCount", &DMREAD, DMT_UNINT, get_max_line_count, NULL, NULL, NULL, BBFDM_BOTH},
+{"MaxSessionsPerLine", &DMREAD, DMT_UNINT, get_true_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"MaxSessionCount", &DMREAD, DMT_UNINT, get_max_session_count, NULL, NULL, NULL, BBFDM_BOTH},
+{"SignalingProtocols", &DMREAD, DMT_STRING, get_signal_protocols, NULL, NULL, NULL, BBFDM_BOTH},
+{"Regions", &DMREAD, DMT_STRING, get_regions, NULL, NULL, NULL, BBFDM_BOTH},
+{"RTCP", &DMREAD, DMT_BOOL, get_true_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"SRTP", &DMREAD, DMT_BOOL, get_true_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"RTPRedundancy", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"PSTNSoftSwitchOver", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"FaxT38", &DMREAD, DMT_BOOL, get_true_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"FaxPassThrough", &DMREAD, DMT_BOOL, get_true_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"ModemPassThrough", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"ToneGeneration", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"ToneDescriptionsEditable", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"PatternBasedToneGeneration", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"FileBasedToneGeneration", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"ToneFileFormats", &DMREAD, DMT_STRING, get_empty, NULL, NULL, NULL, BBFDM_BOTH},
+{"RingGeneration", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"RingDescriptionsEditable", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"PatternBasedRingGeneration", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"RingPatternEditable", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"FileBasedRingGeneration", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"RingFileFormats", &DMREAD, DMT_STRING, get_empty, NULL, NULL, NULL, BBFDM_BOTH},
+{"DigitMap", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"NumberingPlan", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"ButtonMap", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"VoicePortTests", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.Capabilities.SIP. ****/
+DMLEAF tSIPParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Role", &DMREAD, DMT_STRING, get_sip_role, NULL, NULL, NULL, BBFDM_BOTH},
+{"Extensions", &DMREAD, DMT_STRING, get_sip_extension, NULL, NULL, NULL, BBFDM_BOTH},
+{"Transports", &DMREAD, DMT_STRING, get_sip_transport, NULL, NULL, NULL, BBFDM_BOTH},
+{"URISchemes", &DMREAD, DMT_STRING, get_empty, NULL, NULL, NULL, BBFDM_BOTH},
+{"EventSubscription", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"ResponseMap", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"TLSAuthenticationProtocols", &DMREAD, DMT_STRING, get_sip_tls_auth_protocols, NULL, NULL, NULL, BBFDM_BOTH},
+{"TLSEncryptionProtocols", &DMREAD, DMT_STRING, get_sip_tls_enc_protocols, NULL, NULL, NULL, BBFDM_BOTH},
+{"TLSKeyExchangeProtocols", &DMREAD, DMT_STRING, get_sip_tls_key_protocols, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.Capabilities.Codecs.{i}. ****/
+DMLEAF tCodecsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_cap_codec_alias, set_cap_codec_alias, NULL, NULL, BBFDM_BOTH},
+{"EntryID", &DMREAD, DMT_UNINT, get_entry_id, NULL, NULL, NULL, BBFDM_BOTH},
+{"Codec", &DMREAD, DMT_STRING, get_capabilities_sip_codec, NULL, NULL, NULL, BBFDM_BOTH},
+{"BitRate", &DMREAD, DMT_UNINT, get_capabilities_sip_bitrate, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketizationPeriod", &DMREAD, DMT_STRING, get_capabilities_sip_pperiod, NULL, NULL, NULL, BBFDM_BOTH},
+{"SilenceSuppression", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}. ****/
+DMOBJ tProfileObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"SIP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tProfileSIPParams, NULL, BBFDM_BOTH},
+{"ServiceProviderInfo", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tServiceProviderInfoParams, NULL, BBFDM_BOTH},
+{"FaxT38", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tFaxT38Params, NULL, BBFDM_BOTH},
+{"RTP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tRTPObj, tRTPParams, NULL, BBFDM_BOTH},
+{"Line", &DMWRITE, add_line_object, delete_line_object, NULL, browseLineInst, NULL, NULL, tLineObj, tLineParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tProfileParam[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_voice_profile_alias, set_voice_profile_alias, NULL, NULL, BBFDM_BOTH},
+{"Enable", &DMWRITE, DMT_STRING, get_voice_profile_enable, set_voice_profile_enable, NULL, NULL, BBFDM_BOTH},
+{"Reset", &DMWRITE, DMT_BOOL, get_false_value, set_voice_profile_reset, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_voice_profile_name, NULL, NULL, NULL, BBFDM_BOTH},
+{"SignalingProtocol", &DMWRITE, DMT_STRING, get_voice_profile_signalprotocol, set_voice_profile_signaling_protocol, NULL, NULL, BBFDM_BOTH},
+{"MaxSessions", &DMREAD, DMT_UNINT, get_voice_profile_max_sessions, NULL, NULL, NULL, BBFDM_BOTH},
+{"NumberOfLines", &DMREAD, DMT_UNINT, get_voice_profile_number_of_lines, NULL, NULL, NULL, BBFDM_BOTH},
+{"DTMFMethod", &DMWRITE, DMT_STRING, get_voice_profile_sip_dtmfmethod, set_voice_profile_sip_dtmfmethod, NULL, NULL, BBFDM_BOTH},
+{"Region", &DMWRITE, DMT_STRING, get_sip_profile_region, set_sip_profile_region, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.SIP. ***/
+DMLEAF tProfileSIPParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"ProxyServer", &DMWRITE, DMT_STRING, get_voice_profile_sip_proxyserver, set_voice_profile_sip_proxyserver, NULL, NULL, BBFDM_BOTH},
+{"ProxyServerPort", &DMWRITE, DMT_UNINT, get_empty, set_sip_proxy_server_port, NULL, NULL, BBFDM_BOTH},
+{"ProxyServerTransport", &DMWRITE, DMT_STRING, get_sip_proxy_server_transport, set_sip_proxy_server_transport, NULL, NULL, BBFDM_BOTH},
+{"RegistrarServer", &DMWRITE, DMT_STRING, get_voice_profile_sip_registerserver, set_voice_profile_sip_registerserver, NULL, NULL, BBFDM_BOTH},
+{"RegistrarServerPort", &DMWRITE, DMT_UNINT, get_voice_profile_sip_registerserverport, set_voice_profile_sip_registerserverport, NULL, NULL, BBFDM_BOTH},
+{"RegistrarServerTransport", &DMWRITE, DMT_STRING, get_sip_registrar_server_transport, set_sip_registrar_server_transport, NULL, NULL, BBFDM_BOTH},
+{"UserAgentDomain", &DMWRITE, DMT_STRING, get_sip_user_agent_domain, set_sip_user_agent_domain, NULL, NULL, BBFDM_BOTH},
+{"UserAgentPort", &DMWRITE, DMT_UNINT, get_sip_user_agent_port, set_sip_user_agent_port, NULL, NULL, BBFDM_BOTH},
+{"UserAgentTransport", &DMWRITE, DMT_STRING, get_sip_user_agent_transport, set_sip_user_agent_transport, NULL, NULL, BBFDM_BOTH},
+{"OutboundProxy", &DMWRITE, DMT_STRING, get_sip_outbound_proxy, set_sip_outbound_proxy, NULL, NULL, BBFDM_BOTH},
+{"OutboundProxyPort", &DMWRITE, DMT_UNINT, get_sip_outbound_proxy_port, set_sip_outbound_proxy_port, NULL, NULL, BBFDM_BOTH},
+{"RegistrationPeriod", &DMWRITE, DMT_UNINT, get_sip_registration_period, set_sip_registration_period, NULL, NULL, BBFDM_BOTH, BBFDM_BOTH},
+{"ReInviteExpires", &DMWRITE, DMT_UNINT, get_sip_re_invite_expires, set_sip_re_invite_expires, NULL, NULL, BBFDM_BOTH},
+{"RegisterExpires", &DMWRITE, DMT_UNINT, get_sip_re_invite_expires, set_sip_re_invite_expires, NULL, NULL, BBFDM_BOTH},
+{"RegisterRetryInterval", &DMWRITE, DMT_UNINT, get_sip_re_invite_expires, set_sip_re_invite_expires, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"CallLines", &DMWRITE, DMT_STRING, get_sip_call_lines, set_sip_call_lines, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.ServiceProviderInfo. ***/
+DMLEAF tServiceProviderInfoParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Name", &DMWRITE, DMT_STRING, get_voice_service_serviceproviderinfo_name, set_voice_service_serviceproviderinfo_name, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.FaxT38. ***/
+DMLEAF tFaxT38Params[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_sip_fax_t38_enable, set_sip_fax_t38_enable, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.RTP. ***/
+DMOBJ tRTPObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"RTCP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tRTCPParams, NULL, BBFDM_BOTH},
+{"SRTP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tSRTPParam, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tRTPParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"LocalPortMin", &DMWRITE, DMT_UNINT, get_voice_service_vp_rtp_portmin, set_voice_service_vp_rtp_portmin, NULL, NULL, BBFDM_BOTH},
+{"LocalPortMax", &DMWRITE, DMT_UNINT, get_voice_service_vp_rtp_portmax, set_voice_profile_rtp_localportmax, NULL, NULL, BBFDM_BOTH},
+{"DSCPMark", &DMWRITE, DMT_UNINT, get_voice_service_vp_rtp_dscp, set_voice_service_vp_rtp_dscp, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.RTP.RTCP. ***/
+DMLEAF tRTCPParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMREAD, DMT_BOOL, get_voice_service_vp_rtp_rtcp_enable, NULL, NULL, NULL, BBFDM_BOTH},
+{"TxRepeatInterval", &DMWRITE, DMT_UNINT, get_voice_service_vp_rtp_rtcp_txrepeatinterval, set_voice_service_vp_rtp_rtcp_txrepeatinterval, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.RTP.SRTP. ***/
+DMLEAF tSRTPParam[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_voice_service_vp_rtp_srtp_enable, set_voice_service_vp_rtp_srtp_enable, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.Line.{i}. ***/
+DMOBJ tLineObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"VoiceProcessing", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tVoiceProcessingParams, NULL, BBFDM_BOTH},
+{"CallingFeatures", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tCallingFeaturesParams, NULL, BBFDM_BOTH},
+{"SIP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tLineSIPParams, NULL, BBFDM_BOTH},
+{"Codec", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tLineCodecObj, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tLineParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_line_alias, set_line_alias, NULL, NULL, BBFDM_BOTH},
+{"Enable", &DMWRITE, DMT_STRING, get_voice_profile_line_enable, set_voice_profile_line_enable, NULL, NULL, BBFDM_BOTH},
+{"DirectoryNumber", &DMWRITE, DMT_STRING, get_line_directory_number, set_line_directory_number, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_voice_profile_line_status, set_line_alias, NULL, NULL, BBFDM_BOTH},
+{"CallState", &DMREAD, DMT_STRING, get_voice_profile_line_callstate, set_line_alias, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"LineProfile", &DMWRITE, DMT_STRING, get_line_line_profile, set_line_line_profile, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"TELLine", &DMWRITE, DMT_STRING, get_line_tel_line, set_line_tel_line, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"Confort_Noise_Enable", &DMWRITE, DMT_BOOL, get_line_confort_noise_enable, set_line_confort_noise_enable, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.Line.{i}.VoiceProcessing. ***/
+DMLEAF tVoiceProcessingParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"EchoCancellationEnable", &DMWRITE, DMT_BOOL, get_line_voice_processing_cancellation_enable, set_line_voice_processing_cancellation_enable, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.Line.{i}.CallingFeatures. ***/
+DMLEAF tCallingFeaturesParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"CallerIDName", &DMWRITE, DMT_STRING, get_line_calling_features_caller_id_name, set_line_calling_features_caller_id_name, NULL, NULL, BBFDM_BOTH},
+{"CallWaitingEnable", &DMWRITE, DMT_BOOL, get_line_calling_features_callwaiting, set_line_calling_features_callwaiting, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.Line.{i}.SIP. ***/
+DMLEAF tLineSIPParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"AuthUserName", &DMWRITE, DMT_STRING, get_line_sip_auth_username, set_line_sip_auth_username, NULL, NULL, BBFDM_BOTH},
+{"AuthPassword", &DMWRITE, DMT_STRING, get_empty, set_line_sip_auth_password, NULL, NULL, BBFDM_BOTH},
+{"URI", &DMWRITE, DMT_STRING, get_line_sip_uri, set_line_sip_uri, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.Line.{i}.Codec. ***/
+DMOBJ tLineCodecObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"List", &DMREAD, NULL, NULL, NULL, browseLineCodecListInst, NULL, NULL, NULL, tLineCodecListParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** VoiceService.{i}.VoiceProfile.{i}.Line.{i}.Codec.List.{i}. ***/
+DMLEAF tLineCodecListParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_line_codec_list_alias, set_line_codec_list_alias, NULL, NULL, BBFDM_BOTH},
+{"EntryID", &DMREAD, DMT_UNINT, get_codec_entry_id, NULL, NULL, NULL, BBFDM_BOTH},
+{"Codec", &DMREAD, DMT_STRING, capabilities_sip_codecs_get_codec, NULL, NULL, NULL, BBFDM_BOTH},
+{"BitRate", &DMREAD, DMT_UNINT, capabilities_sip_codecs_get_bitrate, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketizationPeriod", &DMWRITE, DMT_STRING, get_capabilities_sip_codecs_pperiod, set_line_codec_list_packetization, NULL, NULL, BBFDM_BOTH},
+{"SilenceSuppression", &DMREAD, DMT_BOOL, get_false_value, NULL, NULL, NULL, BBFDM_BOTH},
+{"Enable", &DMWRITE, DMT_BOOL, get_line_codec_list_enable, set_line_codec_list_enable, NULL, NULL, BBFDM_BOTH},
+{"Priority", &DMWRITE, DMT_UNINT, get_line_codec_list_priority, set_line_codec_list_priority, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+#define MAX_ALLOWED_SIP_CODECS 20
+int available_sip_codecs = 0;
+struct allow_sip_codec allowed_sip_codecs[MAX_ALLOWED_SIP_CODECS];
+char *codec_option_array[5] = {"codec0", "codec1", "codec2", "codec3", "codec4"};
+struct cap_sip_codec capabilities_sip_codecs[] = {
+ {SIP_CODEC_G723, "g723", "G.723.1", "6451", "30-300", "30"},
+ {SIP_CODEC_GSM, "gsm", "GSM-FR", "13312", "20-300", "20"},
+ {SIP_CODEC_ULAW, "ulaw", "G.711MuLaw","65536", "10-150", "20"},
+ {SIP_CODEC_ALAW, "alaw", "G.711ALaw", "65536", "10-150", "20"},
+ {SIP_CODEC_G726AAL2, "g726aal2","g726aal2 ", "32768", "10-300", "20"},
+ {SIP_CODEC_ADPCM, "adpcm", "adpcm", "32768", "10-300", "20"},
+ {SIP_CODEC_SLIN, "slin", "slin", "0", "10-70", "20"},
+ {SIP_CODEC_LPC10, "lpc10", "lpc10", "2457", "20-20", "20"},
+ {SIP_CODEC_G729, "g729", "G.729a", "8192", "10-230", "20"},
+ {SIP_CODEC_SPEEX, "speex", "speex", "49152", "10-60", "20"},
+ {SIP_CODEC_ILBC, "ilbc", "iLBC", "8192", "30-30", "30"},
+ {SIP_CODEC_G726, "g726", "G.726", "32768", "10-300", "20"},
+ {SIP_CODEC_G722, "g722", "G.722", "65536", "0-0", "0"},
+ {SIP_CODEC_SIREN7, "siren7", "G.722.1", "32768", "0-0", "0"},
+ {SIP_CODEC_SIREN14, "siren14", "siren14 ", "0", "0-0", "0"},
+ {SIP_CODEC_SLIN16, "slin16", "slin16", "0", "0-0", "0"},
+ {SIP_CODEC_G719, "g719", "g719", "0", "0-0", "0"},
+ {SIP_CODEC_SPEEX16, "speex16", "speex16", "0", "0-0", "0"},
+ {SIP_CODEC_TESTLAW, "testlaw", "testlaw", "0", "0-0", "0"}
+};
+struct region capabilities_regions[] = {
+ {"AUS", "AU"},
+ {"BEL", "BE"},
+ {"BRA", "BR"},
+ {"CHL", "CL"},
+ {"CHN", "CN"},
+ {"CZE", "CZ"},
+ {"DNK", "DK"},
+ {"FIN", "FI"},
+ {"FRA", "FR"},
+ {"DEU", "DE"},
+ {"HUN", "HU"},
+ {"IND", "IN"},
+ {"ITA", "IT"},
+ {"JPN", "JP"},
+ {"NLD", "NL"},
+ {"NZL", "NZ"},
+ {"USA", "US"},
+ {"ESP", "ES"},
+ {"SWE", "SE"},
+ {"CHE", "CH"},
+ {"NOR", "NO"},
+ {"TWN", "TW"},
+ {"GBR", "GB"},
+ {"ARE", "AE"},
+ {"ETS", "ET"},
+ {"T57", "T5"}
+};
+struct rtp_tos list_rtp_tos[] = {
+ {"CS0", "0"},
+ {"CS1", "32"},
+ {"AF11", "40"},
+ {"AF12", "48"},
+ {"AF13", "56"},
+ {"CS2", "64"},
+ {"AF21", "72"},
+ {"AF22", "80"},
+ {"AF23", "88"},
+ {"CS3", "96"},
+ {"AF31", "104"},
+ {"AF32", "112"},
+ {"AF33", "120"},
+ {"CS4", "128"},
+ {"AF41", "136"},
+ {"AF42", "144"},
+ {"AF43", "152"},
+ {"CS5", "160"},
+ {"EF", "184"},
+ {"CS6", "192"},
+ {"CS7", "224"}
+};
+
+///////////////////////////////INIT ARGS//////////////////
+void wait_voice_service_up(void)
+{
+ json_object *res;
+ int i = 0;
+ while (i++ < 10) {
+ dmubus_call("voice.asterisk", "status", UBUS_ARGS{}, 0, &res);
+ if (res)
+ return;
+ }
+}
+
+static inline int init_allowed_sip_codecs()
+{
+ json_object *res = NULL;
+ char id[8], priority[24], ptime[24];
+ int i;
+ available_sip_codecs = 0;
+ dmubus_call("voice.asterisk", "codecs", UBUS_ARGS{}, 0, &res);
+ if(res) {
+ json_object_object_foreach(res, key, val) {
+ for (i = 0; i < ARRAY_SIZE(capabilities_sip_codecs); i++) {
+ if(strcmp(capabilities_sip_codecs[i].c1, key) == 0) {
+ allowed_sip_codecs[available_sip_codecs].enumid = capabilities_sip_codecs[i].enumid;
+ break;
+ }
+ }
+ sprintf(id, "%d", available_sip_codecs + 1);
+ sprintf(priority, "priority_%s", key);
+ sprintf(ptime, "ptime_%s", key);
+ allowed_sip_codecs[available_sip_codecs].id = dmstrdup(id);
+ allowed_sip_codecs[available_sip_codecs].allowed_cdc = key;
+ allowed_sip_codecs[available_sip_codecs].priority_cdc = dmstrdup(priority);
+ allowed_sip_codecs[available_sip_codecs].ptime_cdc = dmstrdup(ptime);
+ available_sip_codecs++;
+ }
+ }
+ return 0;
+}
+
+int init_sip_args(struct sip_args *args, struct uci_section *section, char *profile_num)
+{
+ args->sip_section = section;
+ args->profile_num = profile_num;
+ return 0;
+}
+
+int init_codec_args(struct codec_args *args, char *cdc, char *id, int enumid, struct uci_section *s)
+{
+ args->cdc = dmstrdup(cdc);
+ args->id = dmstrdup(id);
+ args->enumid = enumid;
+ args->codec_section = s;
+ return 0;
+}
+
+int fini_codec_args(struct codec_args *args)
+{
+ dmfree(args->cdc);
+ dmfree(args->id);
+ return 0;
+}
+
+int init_line_code_args(struct line_codec_args *args, int i, struct uci_section *s, struct uci_section *codec_sec)
+{
+ args->cdc = allowed_sip_codecs[i].allowed_cdc;
+ args->id = allowed_sip_codecs[i].id;
+ args->sip_section = s;
+ args->priority_cdc = allowed_sip_codecs[i].priority_cdc;
+ args->enumid = allowed_sip_codecs[i].enumid;
+ args->ptime_cdc = allowed_sip_codecs[i].ptime_cdc;
+ args->codec_sec = codec_sec;
+ return 0;
+}
+
+int init_tel_args(struct tel_args *args, struct uci_section *section, struct uci_section *section2, char *instance)
+{
+ args->tel_section = section;
+ args->sip_section = section2;
+ args->profile_num = instance;
+ return 0;
+}
+
+/**************************ADD/DEL OBJECT *********************************/
+int get_cfg_sipidx(void)
+{
+ char *si;
+ int idx = 0, max = -1;
+ struct uci_section *s = NULL;
+
+ uci_foreach_sections("voice_client", "sip_service_provider", s) {
+ si = section_name(s) + sizeof("sip") - 1;
+ idx = atoi(si);
+ if (idx > max)
+ max = idx;
+ }
+ return (max + 1);
+}
+
+int add_profile_object(char *refparam, struct dmctx *ctx, void *data, char **instancepara)
+{
+ char sname[8];
+ char account[16];
+ char bufinst[4];
+ int sipidx;
+ char *add_value, *instance, *max_instance, *v;
+ struct uci_section *voice_profile_section= NULL, *dmmap_voice_section= NULL;
+
+ check_create_dmmap_package("dmmap_voice_client");
+ sipidx = get_cfg_sipidx();
+ sprintf(sname, "sip%d", sipidx);
+ sprintf(account, "Account %d", sipidx);
+ dmuci_set_value("voice_client", sname, NULL, "sip_service_provider");
+ dmuci_set_value("voice_client", sname, "name", account);
+ dmuci_set_value("voice_client", sname, "enabled", "0");
+ dmuci_set_value("voice_client", sname, "codec0", "ulaw");
+ dmuci_set_value("voice_client", sname, "codec1", "alaw");
+ dmuci_set_value("voice_client", sname, "codec2", "g729");
+ dmuci_set_value("voice_client", sname, "codec3", "g726");
+ dmuci_set_value("voice_client", sname, "cfim_on", "*21*");
+ dmuci_set_value("voice_client", sname, "cfim_off", "#21#");
+ dmuci_set_value("voice_client", sname, "cfbs_on", "*61*");
+ dmuci_set_value("voice_client", sname, "cfbs_off", "#61#");
+ dmuci_set_value("voice_client", sname, "call_return", "*69");
+ dmuci_set_value("voice_client", sname, "redial", "*66");
+ dmuci_set_value("voice_client", sname, "cbbs_key", "5");
+ dmuci_set_value("voice_client", sname, "cbbs_maxretry", "5");
+ dmuci_set_value("voice_client", sname, "cbbs_retrytime", "300");
+ dmuci_set_value("voice_client", sname, "cbbs_waittime", "30");
+ instance = get_last_instance_icwmpd("dmmap_voice_client", "sip_service_provider", "profileinstance");
+
+ dmuci_add_section_icwmpd("dmmap_voice_client", "sip_service_provider", &dmmap_voice_section, &v);
+ dmuci_set_value_by_section(dmmap_voice_section, "section_name", sname);
+ *instancepara = update_instance_icwmpd(dmmap_voice_section, instance, "profileinstance");
+
+ return 0;
+}
+
+int delete_associated_line_instances(char *sip_id, char* profile_key)
+{
+ struct uci_section *s;
+ char *stmp;
+
+ uci_foreach_option_eq("voice_client", "tel_line", "sip_account", sip_id, s) {
+ dmuci_set_value_by_section(s, "sip_account", "-");
+ }
+ uci_path_foreach_option_eq_safe(icwmpd, "dmmap_voice_client", "tel_line", "voice_profile_key", profile_key, stmp, s) {
+ dmuci_delete_by_section(s, NULL, NULL);
+ }
+ return 0;
+}
+
+int delete_profile_object(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ int found = 0;
+ struct uci_section *s, *ss = NULL, *sss = NULL;
+ struct sip_args *sipargs = (struct sip_args *)data;
+ struct uci_section *dmmap_section;
+ char *v= NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ get_dmmap_section_of_config_section("dmmap_voice_client", "sip_service_provider", section_name(sipargs->sip_section), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "profileinstance", &v);
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ delete_associated_line_instances(section_name(sipargs->sip_section), v);
+ dmuci_delete_by_section(sipargs->sip_section, NULL, NULL);
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("voice_client", "sip_service_provider", s) {
+ if (found != 0) {
+ get_dmmap_section_of_config_section("dmmap_voice_client", "sip_service_provider", section_name(ss), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "profileinstance", &v);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ delete_associated_line_instances(section_name(ss), v);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL) {
+ get_dmmap_section_of_config_section("dmmap_voice_client", "sip_service_provider", section_name(ss), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "profileinstance", &v);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ delete_associated_line_instances(section_name(ss), v);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ uci_foreach_sections("voice_client", "tel_line", sss) {
+ dmuci_set_value_by_section(sss, "sip_account", "-");
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/*********/
+int get_line_max_instance(struct uci_section **tel_section)
+{
+ struct uci_section *s;
+ int line_number, i = 0, found = 0;
+ char *value;
+
+ line_number = get_voice_service_max_line();
+
+ uci_foreach_sections("voice_client", "tel_line", s) {
+ i++;
+ dmuci_get_value_by_section_string(s, "sip_account", &value);
+
+ if (strcmp(value, "-") == 0)
+ {
+ found=1;
+ break;
+ }
+ else if (i >= line_number) {
+ i = 0;
+ break;
+ }
+ }
+ if (found == 1)
+ *tel_section = s;
+ else {
+ i=0;
+ *tel_section = NULL;
+ }
+ return i;
+}
+
+char *update_vp_line_instance(struct uci_section *tel_s, char *sipx)
+{
+ struct uci_section *s = NULL, *dmmap_section= NULL, *dmmap_dup= NULL;
+ int last_instance = 0, i_instance;
+ char *instance, buf[8];
+ get_dmmap_section_of_config_section("dmmap_voice_client", "tel_line", section_name(tel_s), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "lineinstance", &instance);
+ if(instance[0] != '\0'){
+ return instance;
+ }
+ uci_foreach_option_eq("voice_client", "tel_line", "sip_account", sipx, s) {
+ get_dmmap_section_of_config_section("dmmap_voice_client", "tel_line", section_name(s), &dmmap_dup);
+ dmuci_get_value_by_section_string(dmmap_dup, "lineinstance", &instance);
+ if (instance[0] != '\0') {
+ i_instance = atoi(instance);
+ if ( i_instance > last_instance)
+ last_instance = i_instance;
+ }
+ }
+ sprintf(buf, "%d", last_instance + 1);
+ instance = dmuci_set_value_by_section(dmmap_section, "lineinstance", buf);
+ return instance;
+}
+
+char *update_vp_line_instance_alias(int action, char **last_inst, void *argv[])
+{
+ struct uci_section *s = NULL;
+ int last_instance = 0, i_instance;
+ char *instance, *alias, buf[64];
+
+ struct uci_section *tel_s = (struct uci_section *) argv[0];
+ char *sipx = (char *) argv[1];
+
+ dmuci_get_value_by_section_string(tel_s, "lineinstance", &instance);
+ if (instance[0] == '\0') {
+ uci_foreach_option_eq("voice_client", "tel_line", "sip_account", sipx, s) {
+ dmuci_get_value_by_section_string(s, "lineinstance", &instance);
+ if (instance[0] != '\0') {
+ i_instance = atoi(instance);
+ if ( i_instance > last_instance)
+ last_instance = i_instance;
+ }
+ }
+ sprintf(buf, "%d", last_instance + 1);
+ instance = dmuci_set_value_by_section(tel_s, "lineinstance", buf);
+ }
+ *last_inst = instance;
+ if (action == INSTANCE_MODE_ALIAS) {
+ dmuci_get_value_by_section_string(tel_s, "linealias", &alias);
+ if (alias[0] == '\0') {
+ sprintf(buf, "cpe-%s", instance);
+ alias = dmuci_set_value_by_section(tel_s, "linealias", buf);
+ }
+ sprintf(buf, "[%s]", alias);
+ instance = dmstrdup(buf);
+ }
+ return instance;
+}
+/*******/
+
+int add_line(struct uci_section *s, char *s_name)
+{
+ dmuci_set_value_by_section(s, "sip_account", s_name);
+ return 0;
+}
+
+int add_line_object(char *refparam, struct dmctx *ctx, void *data, char **instancepara)
+{
+ int i;
+ char *value, *v, *voice_profile_key;
+ char instance[4];
+ char call_lines[16] = {0};
+ struct uci_section *s = NULL;
+ struct sip_args *sipargs = (struct sip_args *)data;
+ struct uci_section *dmmap_voice_line_section, *dmmap_section;
+ int last_instance;
+
+ check_create_dmmap_package("dmmap_voice_client");
+ i = get_line_max_instance(&s);
+ if (i == 0)
+ return FAULT_9004;
+ add_line(s, section_name(sipargs->sip_section));
+ dmuci_add_section_icwmpd("dmmap_voice_client", "tel_line", &dmmap_voice_line_section, &v);
+ dmuci_set_value_by_section(dmmap_voice_line_section, "section_name", section_name(s));
+ get_dmmap_section_of_config_section("dmmap_voice_client", "sip_service_provider", section_name(sipargs->sip_section), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "profileinstance", &voice_profile_key);
+ dmuci_set_value_by_section(dmmap_voice_line_section, "voice_profile_key", voice_profile_key);
+ *instancepara = update_vp_line_instance(s, section_name(sipargs->sip_section)); //TODO: To Check
+ dmuci_get_value_by_section_string(sipargs->sip_section, "call_lines", &value);
+ if (value[0] == '\0') {
+ sprintf(call_lines, "%d", i - 1);
+ }
+ else {
+ sprintf(call_lines, "%s %d", value, i - 1);
+ }
+ dmuci_set_value_by_section(sipargs->sip_section, "call_lines", call_lines);
+ return 0;
+}
+
+int delete_line(struct uci_section *line_section, struct uci_section *sip_section)
+{
+ int len, found =0;
+ char *section_name, *line_id, *value = NULL;
+ char *pch, *spch, *call_lines, *p, new_call_lines[34] = {0};
+
+ section_name = section_name(line_section);
+ line_id = section_name + strlen(section_name) - 1;
+ dmuci_set_value_by_section(line_section, "sip_account", "-");
+ dmuci_set_value_by_section(line_section, "lineinstance", "");
+ dmuci_set_value_by_section(line_section, "linealias", "");
+ dmuci_get_value_by_section_string(sip_section, "call_lines", &value);
+ call_lines = dmstrdup(value);
+ pch = strtok_r(call_lines, " ", &spch);
+ p = new_call_lines;
+ while (pch != NULL) {
+ if (strcmp(pch, line_id) != 0) {
+ if (new_call_lines[0] == '\0') {
+ dmstrappendstr(p, pch);
+ }
+ else {
+ dmstrappendchr(p, ' ');
+ dmstrappendstr(p, pch);
+ }
+ }
+ pch = strtok_r(NULL, " ", &spch);
+ }
+ dmstrappendend(p);
+ dmuci_set_value_by_section(sip_section, "call_lines", new_call_lines);
+ return 0;
+}
+
+int delete_line_object(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ int found = 0;
+ char *s_name;
+ struct uci_section *s;
+ struct sip_args *sipargs;
+ struct tel_args *bargs; //profile_num must be added to tel_args
+ struct uci_section *dmmap_section;
+
+ switch (del_action) {
+ case DEL_INST:
+ bargs = (struct tel_args *)data;
+ get_dmmap_section_of_config_section("dmmap_voice_client", "tel_line", section_name(bargs->tel_section), &dmmap_section);
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ delete_line(bargs->tel_section, bargs->sip_section);
+ break;
+ case DEL_ALL:
+ sipargs = (struct sip_args *)data;
+ s_name = section_name(sipargs->sip_section);
+ uci_foreach_option_eq("voice_client", "tel_line", "sip_account", s_name, s) {
+ get_dmmap_section_of_config_section("dmmap_voice_client", "tel_line", section_name(s), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ delete_line(s, sipargs->sip_section);
+ }
+ break;
+ }
+
+ return 0;
+}
+/**************************Function for root entry *************************/
+int get_max_profile_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "8";
+ return 0;
+}
+
+int get_max_line_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "6";
+ return 0;
+}
+
+int get_max_session_per_line(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int get_max_session_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "6";
+ return 0;
+}
+
+int get_signal_protocols(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "SIP";
+ return 0;
+}
+
+int get_regions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "AU, BE, BR, CL, CN, CZ, DK, FI, FR, DE, HU, IN, IT, JP, NL, NZ, US, ES, SE, CH, NO, TW, GB, AE, ET, T5";
+ return 0;
+}
+
+int get_true_value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int get_false_value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ return 0;
+}
+/*******************end root ***************************/
+
+/**************SIP CAPABILITIES ************************/
+int get_sip_role (char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "BackToBackUserAgents";
+ return 0;
+}
+
+int get_sip_extension(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH";
+ return 0;
+}
+
+int get_sip_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "UDP, TCP, TLS";
+ return 0;
+}
+
+int get_sip_tls_auth_protocols(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "MD5";
+ return 0;
+}
+
+int get_sip_tls_enc_protocols(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "RC4, RC2, DES, 3DES";
+ return 0;
+}
+
+int get_sip_tls_key_protocols(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "RSA, DSS";
+ return 0;
+}
+/*******************Capabilities.Codecs.***********************************/
+int get_entry_id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct codec_args *codecs = (struct codec_args *)data;
+ *value = dmstrdup(codecs->id);
+ return 0;
+}
+
+int get_capabilities_sip_codec(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int i;
+ struct codec_args *cdcargs = (struct codec_args *)data;
+ bool sep = false;
+ for (i = 0; i < ARRAY_SIZE(capabilities_sip_codecs); i++) {
+ if(capabilities_sip_codecs[i].enumid == cdcargs->enumid) {
+ *value = capabilities_sip_codecs[i].c2;
+ break;
+ }
+ }
+ return 0;
+}
+
+int get_capabilities_sip_bitrate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int i;
+ struct codec_args *cdcargs = (struct codec_args *)data;
+ for (i = 0; i < ARRAY_SIZE(capabilities_sip_codecs); i++) {
+ if(capabilities_sip_codecs[i].enumid == cdcargs->enumid) {
+ *value = capabilities_sip_codecs[i].c3;
+ break;
+ }
+ }
+ return 0;
+}
+
+int get_capabilities_sip_pperiod(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int i;
+ struct codec_args *cdcargs = (struct codec_args *)data;
+ for (i = 0; i < ARRAY_SIZE(capabilities_sip_codecs); i++) {
+ if(capabilities_sip_codecs[i].enumid == cdcargs->enumid) {
+ *value = capabilities_sip_codecs[i].c4;
+ break;
+ }
+ }
+ return 0;
+}
+
+/*******************Voiceprofile END **********************************/
+int get_voice_service_max_line()
+{
+ char *num_lines = NULL;
+
+ db_get_value_string("hw", "board", "VoicePorts", &num_lines);
+ if(num_lines)
+ return atoi(num_lines);
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.Enable!UCI:voice_client/sip_service_provider,@i-1/enabled*/
+int get_voice_profile_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "enabled", &tmp);
+
+ if(strcmp(tmp, "0") == 0)
+ *value = "Disabled";
+ else
+ *value = "Enabled";
+ return 0;
+}
+
+int set_voice_profile_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if(strcmp(value, "Enabled") == 0)
+ dmuci_set_value_by_section(sipargs->sip_section, "enabled", "1");
+ else
+ dmuci_set_value_by_section(sipargs->sip_section, "enabled", "0");
+ return 0;
+ }
+ return 0;
+}
+
+int set_voice_profile_reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b) {
+ dmubus_call_set("uci", "commit", UBUS_ARGS{{"config", "voice_client"}}, 1);
+ return 0;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.Name!UCI:voice_client/sip_service_provider,@i-1/name*/
+int get_voice_profile_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+ dmuci_get_value_by_section_string(sipargs->sip_section, "name", value);
+ return 0;
+}
+
+int get_voice_profile_signalprotocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "SIP";
+ return 0;
+}
+
+int set_voice_profile_signaling_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.MaxSessions!UBUS:voice.asterisk/lines//num_lines*/
+int get_voice_profile_max_sessions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ char *sub_channel = NULL, *num_lines = NULL;
+ dmubus_call("voice.asterisk", "lines", UBUS_ARGS{}, 0, &res);
+ DM_ASSERT(res, *value = "");
+ sub_channel = dm_ubus_get_value(res, 1, "num_subchannels");
+ num_lines = dm_ubus_get_value(res, 1, "num_lines");
+ dmasprintf(value, "%d", atoi(sub_channel) * atoi(num_lines)); // MEM WILL BE FREED IN DMMEMCLEAN
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.NumberOfLines!UBUS:voice.asterisk/status//tel.@Name*/
+int get_voice_profile_number_of_lines(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int num = 0;
+ json_object *res = NULL, *jobj = NULL;
+ struct uci_section *b_section = NULL;
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ *value = "0";
+ dmubus_call("voice.asterisk", "status", UBUS_ARGS{}, 0, &res);
+ if (!res)
+ return 0;
+ uci_foreach_option_eq("voice_client", "tel_line", "sip_account", section_name(sipargs->sip_section), b_section) {
+ jobj = dmjson_get_obj(res, 2, "tel", section_name(b_section));
+ if (jobj)
+ num++;
+ }
+ dmasprintf(value, "%d", num); // MEM WILL BE FREED IN DMMEMCLEAN
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.ProxyServer!UCI:voice_client/sip_advanced,SIP/sip_proxy*/
+int get_voice_profile_sip_proxyserver(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("voice_client", "SIP", "sip_proxy", value);
+ return 0;
+}
+
+int set_voice_profile_sip_proxyserver(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("voice_client", "SIP", "sip_proxy", value);
+ return 0;
+ }
+ return 0;
+}
+
+int set_sip_proxy_server_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ //TODO: not implemented in old scripts
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.ProxyServerTransport!UCI:voice_client/sip_service_provider,@i-1/transport*/
+int get_sip_proxy_server_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "transport", value);
+ return 0;
+}
+
+int set_sip_proxy_server_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(sipargs->sip_section, "transport", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.RegistrarServer!UCI:voice_client/sip_service_provider,@i-1/host*/
+int get_voice_profile_sip_registerserver(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "host", value);
+ return 0;
+}
+
+int set_voice_profile_sip_registerserver(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(sipargs->sip_section, "host", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.RegistrarServerPort!UCI:voice_client/sip_service_provider,@i-1/port*/
+int get_voice_profile_sip_registerserverport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "port", value);
+ return 0;
+}
+
+int set_voice_profile_sip_registerserverport(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(sipargs->sip_section, "port", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.RegistrarServerTransport!UCI:voice_client/sip_service_provider,@i-1/transport*/
+int get_sip_registrar_server_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "transport", value);
+ return 0;
+}
+
+int set_sip_registrar_server_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(sipargs->sip_section, "transport", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.UserAgentDomain!UCI:voice_client/sip_service_provider,@i-1/domain*/
+int get_sip_user_agent_domain(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "domain", value);
+ return 0;
+}
+
+int set_sip_user_agent_domain(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(sipargs->sip_section, "domain", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.UserAgentPort!UCI:voice_client/sip_advanced,SIP/bindport*/
+int get_sip_user_agent_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("voice_client", "SIP", "bindport", value);
+ return 0;
+}
+
+int set_sip_user_agent_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("voice_client", "SIP", "bindport", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.UserAgentTransport!UCI:voice_client/sip_service_provider,@i-1/transport*/
+int get_sip_user_agent_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "transport", &tmp);
+ if (tmp[0] == '\0')
+ *value = "udp";
+ else
+ *value = tmp;
+ return 0;
+}
+
+int set_sip_user_agent_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcasecmp(value, "udp")==0) dmuci_set_value_by_section(sipargs->sip_section, "transport", "");
+ else dmuci_set_value_by_section(sipargs->sip_section, "transport", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.OutboundProxy!UCI:voice_client/sip_service_provider,@i-1/outboundproxy*/
+int get_sip_outbound_proxy(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "outboundproxy", value);
+ return 0;
+}
+
+int set_sip_outbound_proxy(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(sipargs->sip_section, "outboundproxy", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.OutboundProxyPort!UCI:voice_client/sip_service_provider,@i-1/outboundproxyport*/
+int get_sip_outbound_proxy_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "outboundproxyport", value);
+ return 0;
+}
+
+int set_sip_outbound_proxy_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(sipargs->sip_section, "outboundproxyport", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.RegistrationPeriod!UCI:voice_client/sip_advanced,SIP/defaultexpiry*/
+int get_sip_registration_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("voice_client", "SIP", "defaultexpiry", value);
+ return 0;
+}
+
+int set_sip_registration_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("voice_client", "SIP", "defaultexpiry", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.SIP.ReInviteExpires!UCI:voice_client/sip_advanced,SIP/registertimeout*/
+int get_sip_re_invite_expires(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("voice_client", "SIP", "registertimeout", value);
+ return 0;
+}
+
+int set_sip_re_invite_expires(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("voice_client", "SIP", "registertimeout", value);
+ return 0;
+ }
+ return 0;
+}
+
+
+int get_sip_call_lines(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "call_lines", value);
+ return 0;
+}
+
+int set_sip_call_lines(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(sipargs->sip_section, "call_lines", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.DTMFMethod!UCI:voice_client/sip_advanced,SIP/dtmfmode*/
+int get_voice_profile_sip_dtmfmethod(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+
+ dmuci_get_option_value_string("voice_client", "SIP", "dtmfmode", &tmp);
+ if(strcmp(tmp, "inband") == 0)
+ *value = "InBand";
+ else if(strcmp(tmp, "rfc2833") == 0)
+ *value = "RFC2833";
+ else if(strcmp(tmp, "info") == 0)
+ *value = "SIPInfo";
+ else
+ *value = tmp;
+ return 0;
+}
+
+int set_voice_profile_sip_dtmfmethod(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if(strcmp(value, "InBand") == 0)
+ dmuci_set_value("voice_client", "SIP", "dtmfmode", "inband");
+ else if(strcmp(value, "RFC2833") == 0)
+ dmuci_set_value("voice_client", "SIP", "dtmfmode", "rfc2833");
+ else if(strcmp(value, "SIPInfo") == 0)
+ dmuci_set_value("voice_client", "SIP", "dtmfmode", "info");
+ return 0;
+ }
+ return 0;
+}
+
+int get_sip_profile_region(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int i;
+
+ dmuci_get_option_value_string("voice_client", "TEL", "country", value);
+ for (i = 0; i < ARRAY_SIZE(capabilities_regions); i++) {
+ if(strcmp(*value, capabilities_regions[i].country) == 0){
+ *value = capabilities_regions[i].id;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int set_sip_profile_region(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ int i;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ for (i = 0; i < ARRAY_SIZE(capabilities_regions); i++) {
+ if(strcasecmp(value, capabilities_regions[i].id) == 0){
+ dmuci_set_value("voice_client", "TEL", "country", capabilities_regions[i].country);
+ break;
+ }
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_voice_service_serviceproviderinfo_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "provider_name", value);
+ if(*value[0] == '\0') {
+ dmuci_get_value_by_section_string(sipargs->sip_section, "domain", value);
+ }
+ return 0;
+}
+
+int set_voice_service_serviceproviderinfo_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(sipargs->sip_section, "provider_name", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_sip_fax_t38_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+ dmuci_get_value_by_section_string(sipargs->sip_section, "is_fax", value);
+ return 0;
+}
+
+int set_sip_fax_t38_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b)
+ value = "1";
+ else
+ value = "0";
+
+ dmuci_set_value_by_section(sipargs->sip_section, "is_fax", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_voice_service_vp_rtp_portmin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+
+ dmuci_get_option_value_string("voice_client", "SIP", "rtpstart", &tmp);
+ if(tmp[0] == '\0')
+ *value = "5000";
+ else
+ *value = tmp;
+ return 0;
+}
+
+int set_voice_service_vp_rtp_portmin(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("voice_client", "SIP", "rtpstart", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_voice_service_vp_rtp_portmax(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+
+ dmuci_get_option_value_string("voice_client", "SIP", "rtpend", &tmp);
+ if(tmp[0] == '\0')
+ *value = "31000";
+ else
+ *value = tmp;
+ return 0;
+}
+
+int set_voice_profile_rtp_localportmax(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("voice_client", "SIP", "rtpend", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_voice_service_vp_rtp_dscp(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int i;
+ char *tmp;
+ *value = "0";
+
+ dmuci_get_option_value_string("voice_client", "SIP", "tos_audio", &tmp);
+ for (i = 0; i < ARRAY_SIZE(list_rtp_tos); i++) {
+ if(strcmp(tmp, list_rtp_tos[i].key) == 0){
+ *value = list_rtp_tos[i].val;
+ break;
+ }
+ }
+ return 0;
+}
+
+int set_voice_service_vp_rtp_dscp(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ int i;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ for (i = 0; i < ARRAY_SIZE(list_rtp_tos); i++) {
+ if(strcmp(value, list_rtp_tos[i].val) == 0){
+ dmuci_set_value("voice_client", "SIP", "tos_audio", list_rtp_tos[i].key);
+ break;
+ }
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_voice_service_vp_rtp_rtcp_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ pid_t pid;
+
+ pid = get_pid("asterisk");
+ if(pid < 0)
+ *value = "0";
+ else
+ *value = "1";
+ return 0;
+}
+
+int get_voice_service_vp_rtp_rtcp_txrepeatinterval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+
+ dmuci_get_option_value_string("voice_client", "SIP", "rtcpinterval", &tmp);
+ if(tmp[0] == '\0')
+ *value = "5000";
+ else
+ *value = tmp;
+ return 0;
+}
+
+int set_voice_service_vp_rtp_rtcp_txrepeatinterval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("voice_client", "SIP", "rtcpinterval", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_voice_service_vp_rtp_srtp_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ dmuci_get_value_by_section_string(sipargs->sip_section, "encryption", &tmp);
+ if(strcasecmp(tmp, "yes") == 0)
+ *value = "1";
+ else
+ *value = "0";
+ return 0;
+}
+
+int set_voice_service_vp_rtp_srtp_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct sip_args *sipargs = (struct sip_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b)
+ dmuci_set_value_by_section(sipargs->sip_section, "encryption", "yes");
+ else
+ dmuci_set_value_by_section(sipargs->sip_section, "encryption", "");
+ return 0;
+ }
+ return 0;
+}
+
+/*******************LINE **********************************/
+int get_voice_profile_line_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ dmuci_get_value_by_section_string(telargs->sip_section, "enabled", &tmp);
+
+ if(strcmp(tmp, "0") == 0)
+ *value = "Disabled";
+ else
+ *value = "Enabled";
+ return 0;
+}
+
+int set_voice_profile_line_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if(strcmp(value, "Enabled") == 0)
+ dmuci_set_value_by_section(telargs->sip_section, "enabled", "1");
+ else
+ dmuci_set_value_by_section(telargs->sip_section, "enabled", "0");
+ return 0;
+ }
+ return 0;
+}
+
+int get_line_directory_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ dmuci_get_value_by_section_string(telargs->tel_section, "extension", value);
+ return 0;
+}
+
+int set_line_directory_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(telargs->tel_section, "extension", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_voice_profile_line_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *status, *sip_name, *q;
+ json_object *res;
+ char buf[64];
+ struct tel_args *telargs = (struct tel_args *)data;
+ *value = "Disabled";
+ sip_name = section_name(telargs->sip_section);
+ q = buf;
+ dmstrappendstr(q, "asterisk");
+ dmstrappendchr(q, '.');
+ dmstrappendstr(q, "sip");
+ dmstrappendchr(q, '.');
+ dmstrappendstr(q, section_name(telargs->sip_section) + 3);
+ dmstrappendend(q);
+ dmubus_call(buf, "status", UBUS_ARGS{}, 0, &res);
+ DM_ASSERT(res, *value = "Disabled");
+ if(res) {
+ status = dmjson_get_value(res, 1, "registered");
+ if (strcasecmp(status, "true") == 0) {
+ *value = "Up";
+ }
+ else {
+ status = dmjson_get_value(res, 1, "registry_request_sent");
+ if(strcasecmp(status, "true") == 0)
+ *value = "Registering";
+ else
+ *value = "Disabled";
+ }
+ }
+ return 0;
+}
+
+int get_voice_profile_line_callstate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp, *line_name;
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ line_name = section_name(telargs->tel_section);
+ dmuci_get_varstate_string("chan_tel", line_name, "subchannel_0", &tmp);
+ if (strcmp(tmp, "ONHOOK") == 0)
+ *value = "idle";
+ else if (strcmp(tmp, "OFFHOOK") == 0)
+ *value = "Disconnecting";
+ else if (strcmp(tmp, "DIALING") == 0)
+ *value = "Calling";
+ else if (strcmp(tmp, "INCALL") == 0)
+ *value = "InCall";
+ else if (strcmp(tmp, "RINGING") == 0)
+ *value = "Ringing";
+ else
+ *value = "";
+ return 0;
+}
+
+int get_line_line_profile(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ *value = telargs->profile_num;
+ return 0;
+}
+
+int set_line_line_profile(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char call_lines[32];
+ char *str;
+ struct uci_section *sip_s;
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ uci_foreach_option_eq("voice_client", "sip_service_provider", "profileinstance", value, sip_s) {
+ break;
+ }
+ if (!sip_s || strcmp(telargs->profile_num, value) == 0)
+ return 0;
+
+ delete_line(telargs->tel_section, telargs->sip_section);
+ str = update_vp_line_instance(telargs->tel_section, section_name(sip_s));
+ add_line(telargs->tel_section, section_name(sip_s));
+
+ dmuci_get_value_by_section_string(sip_s, "call_lines", &value);
+ if (value[0] == '\0') {
+ value = section_name(telargs->tel_section) + strlen(section_name(telargs->tel_section)) - 1;
+ dmuci_set_value_by_section(sip_s, "call_lines", value);
+ }
+ else {
+ str = (section_name(telargs->tel_section) + strlen(section_name(telargs->tel_section)) - 1);
+ sprintf(call_lines, "%s %s", value, str);
+ dmuci_set_value_by_section(sip_s, "call_lines", call_lines);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_line_tel_line(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *line_name;
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ line_name = section_name(telargs->tel_section);
+ *value = dmstrdup(line_name + strlen(line_name) - 1); // MEM WILL BE FREED IN DMMEMCLEAN
+ return 0;
+}
+
+int set_line_tel_line(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ int error;
+ char line_name[8], bname[8], *stype = NULL, *sipaccount = NULL, *lineinstance = NULL, *linealias = NULL, *voice_profile_key = NULL, *v;
+ struct tel_args *telargs = (struct tel_args *)data;
+ struct uci_section *dmmap_section = NULL, *dmmap_tel_line_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ memset(line_name, '\0', sizeof(line_name));
+ strncpy(line_name, section_name(telargs->tel_section), strlen(section_name(telargs->tel_section)) - 1);
+ sprintf(bname, "%s%s", line_name, value);
+ error = dmuci_get_section_type("voice_client", bname, &stype);
+ if(error)
+ return 0;
+ dmuci_get_option_value_string("voice_client", bname, "sip_account", &sipaccount);
+ if ((sipaccount[0] != '\0' && sipaccount[0] != '-'))
+ return 0;
+ dmuci_get_value_by_section_string(telargs->tel_section, "sip_account", &sipaccount);
+ dmuci_set_value_by_section(telargs->tel_section, "sip_account", "-");
+ get_dmmap_section_of_config_section("dmmap_voice_client", "tel_line", section_name(telargs->tel_section), &dmmap_section);
+ if(dmmap_section != NULL) {
+ dmuci_get_value_by_section_string(dmmap_section, "voice_profile_key", &voice_profile_key);
+ dmuci_get_value_by_section_string(dmmap_section, "lineinstance", &lineinstance);
+ dmuci_get_value_by_section_string(dmmap_section, "linealias", &linealias);
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ }
+ dmuci_set_value("voice_client", bname, "sip_account", sipaccount);
+ dmuci_add_section_icwmpd("dmmap_voice_client", "tel_line", &dmmap_tel_line_section, &v);
+ if(dmmap_section != NULL) {
+ dmuci_set_value_by_section(dmmap_tel_line_section, "section_name", bname);
+ dmuci_set_value_by_section(dmmap_tel_line_section, "voice_profile_key", voice_profile_key);
+ dmuci_set_value_by_section(dmmap_tel_line_section, "lineinstance", lineinstance);
+ dmuci_set_value_by_section(dmmap_tel_line_section, "linealias", linealias);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_line_confort_noise_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ dmuci_get_value_by_section_string(telargs->tel_section, "noise", value);
+ return 0;
+}
+
+int set_line_confort_noise_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ if(string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b)
+ dmuci_set_value_by_section(telargs->tel_section, "noise", "1");
+ else
+ dmuci_set_value_by_section(telargs->tel_section, "noise", "0");
+ return 0;
+ }
+ return 0;
+}
+
+int get_line_voice_processing_cancellation_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ dmuci_get_value_by_section_string(telargs->tel_section, "echo_cancel", value);
+ return 0;
+}
+
+
+int set_line_voice_processing_cancellation_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ if(string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b)
+ dmuci_set_value_by_section(telargs->tel_section, "echo_cancel", "1");
+ else
+ dmuci_set_value_by_section(telargs->tel_section, "echo_cancel", "0");
+ return 0;
+ }
+ return 0;
+}
+
+
+int get_line_calling_features_caller_id_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ dmuci_get_value_by_section_string(telargs->sip_section, "displayname", value);
+ return 0;
+}
+
+int set_line_calling_features_caller_id_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(telargs->sip_section, "displayname", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_line_calling_features_callwaiting(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ dmuci_get_value_by_section_string(telargs->tel_section, "callwaiting", value);
+ if((*value)[0] == '\0')
+ *value = "0";
+ return 0;
+}
+
+int set_line_calling_features_callwaiting(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ if(string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b)
+ dmuci_set_value_by_section(telargs->tel_section, "callwaiting", "1");
+ else
+ dmuci_set_value_by_section(telargs->tel_section, "callwaiting", "");
+ return 0;
+ }
+ return 0;
+}
+
+int get_line_sip_auth_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ dmuci_get_value_by_section_string(telargs->sip_section, "authuser", value);
+ return 0;
+}
+
+int set_line_sip_auth_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(telargs->sip_section, "authuser", value);
+ return 0;
+ }
+ return 0;
+}
+
+int set_line_sip_auth_password(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(telargs->sip_section, "secret", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_line_sip_uri(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *domain = NULL, *user = NULL;
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ dmuci_get_value_by_section_string(telargs->sip_section, "domain", &domain);
+ dmuci_get_value_by_section_string(telargs->sip_section, "user", &user);
+ if (user && domain)
+ dmasprintf(value, "%s@%s", user, domain); // MEM WILL BE FREED IN DMMEMCLEAN
+ else
+ *value = "";
+ return 0;
+}
+
+int set_line_sip_uri(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *pch, *spch, *str1;
+ struct tel_args *telargs = (struct tel_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ str1 = dmstrdup(value);
+ pch = strtok_r(str1, "@", &spch);
+ dmuci_set_value_by_section(telargs->sip_section, "user", pch);
+ pch = strtok_r(NULL, "@", &spch);
+ dmuci_set_value_by_section(telargs->sip_section, "domain", pch);
+ dmfree(str1);
+ return 0;
+ }
+ return 0;
+}
+
+/******************Line codec ***************************************/
+
+int codec_compare(const void *s1, const void *s2)
+{
+ struct codec *sc1 = (struct codec *)s1;
+ struct codec *sc2 = (struct codec *)s2;
+ if (!sc1->priority) return 1;
+ if (!sc2->priority) return -1;
+ return (atoi(sc1->priority) - atoi(sc2->priority));
+}
+
+void codec_priority_sort(struct uci_section *sip_section, char *new_codec)
+{
+ int j, k = 0, h = 0, size = ARRAY_SIZE(codec_option_array);
+ char *ucodec, *coption, *poption;
+ bool found;
+ struct codec sipcodec[ARRAY_SIZE(codec_option_array)+1] = {0};
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_voice_client", "sip_service_provider", section_name(sip_section), &dmmap_section);
+ for (j = 0; j < ARRAY_SIZE(codec_option_array); j++) {
+ dmuci_get_value_by_section_string(sip_section, codec_option_array[j], &ucodec);
+ if(ucodec[0] != '\0') {
+ found = false;
+ for (k = 0; k < available_sip_codecs; k++) {
+ if(strcmp(ucodec, allowed_sip_codecs[k].allowed_cdc) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ sipcodec[j].cdc = allowed_sip_codecs[k].allowed_cdc;
+ dmuci_get_value_by_section_string(dmmap_section, allowed_sip_codecs[k].priority_cdc, &(sipcodec[j].priority));
+ }
+ sipcodec[j].id = codec_option_array[j];
+ }
+ else {
+ sipcodec[j].id = codec_option_array[j];
+ }
+ }
+ if (new_codec) {
+ sipcodec[size].id = "codec5";
+ found = false;
+ for (k = 0; k < available_sip_codecs; k++) {
+ if(strcmp(new_codec, allowed_sip_codecs[k].allowed_cdc) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ sipcodec[size].cdc = allowed_sip_codecs[k].allowed_cdc;
+ dmuci_get_value_by_section_string(dmmap_section, allowed_sip_codecs[k].priority_cdc, &(sipcodec[size].priority));
+ }
+ }
+ qsort(sipcodec, ARRAY_SIZE(sipcodec), sizeof(struct codec), codec_compare);
+
+ for (j = 0; j < ARRAY_SIZE(codec_option_array); j++) {
+ dmuci_set_value_by_section(sip_section, codec_option_array[j], sipcodec[j].cdc ? sipcodec[j].cdc : "");
+ }
+}
+
+void codec_priority_update(struct uci_section *sip_section)
+{
+ bool found;
+ int i, j;
+ char *priority = NULL;
+ char *codec;
+ char pid[4] = "1";
+ struct uci_section *dmmap_section = NULL;
+
+ get_dmmap_section_of_config_section("dmmap_voice_client", "sip_service_provider", section_name(sip_section), &dmmap_section);
+
+ for (i = 0; i < available_sip_codecs; i++) {
+ dmuci_get_value_by_section_string(dmmap_section, allowed_sip_codecs[i].priority_cdc, &priority);
+ if( priority[0] != '\0')
+ continue;
+ found = false;
+ for (j = 0; j < ARRAY_SIZE(codec_option_array); j++) {
+ dmuci_get_value_by_section_string(sip_section, codec_option_array[j], &codec);
+ if(strcmp(codec, allowed_sip_codecs[i].allowed_cdc) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ sprintf(pid, "%d", j+1);
+ dmuci_set_value_by_section(dmmap_section, allowed_sip_codecs[i].priority_cdc, pid);
+ }
+ codec_priority_sort(sip_section, NULL);
+}
+
+int get_codec_entry_id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct line_codec_args *line_codecargs = (struct line_codec_args *)data;
+
+ *value = line_codecargs->id;
+ return 0;
+}
+
+int capabilities_sip_codecs_get_codec(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int i;
+ struct line_codec_args *line_codecargs = (struct line_codec_args *)data;
+
+ for (i = 0; i < ARRAY_SIZE(capabilities_sip_codecs); i++) {
+ if(capabilities_sip_codecs[i].enumid == line_codecargs->enumid) {
+ *value = capabilities_sip_codecs[i].c2;
+ break;
+ }
+ }
+ return 0;
+}
+
+int capabilities_sip_codecs_get_bitrate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int i;
+ struct line_codec_args *line_codecargs = (struct line_codec_args *)data;
+
+ for (i = 0; i < ARRAY_SIZE(capabilities_sip_codecs); i++) {
+ if(capabilities_sip_codecs[i].enumid == line_codecargs->enumid) {
+ *value = capabilities_sip_codecs[i].c3;
+ break;
+ }
+ }
+ return 0;
+}
+
+int get_capabilities_sip_codecs_pperiod(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int i;
+ struct line_codec_args *line_codecargs = (struct line_codec_args *)data;
+ dmuci_get_value_by_section_string(line_codecargs->sip_section, line_codecargs->ptime_cdc, value);
+ if ((*value)[0] != '\0')
+ return 0;
+ for (i = 0; i < ARRAY_SIZE(capabilities_sip_codecs); i++) {
+ if(capabilities_sip_codecs[i].enumid == line_codecargs->enumid) {
+ *value = capabilities_sip_codecs[i].c5;
+ break;
+ }
+ }
+ return 0;
+}
+
+int get_line_codec_list_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int i;
+ char *val;
+ struct line_codec_args *line_codecargs = (struct line_codec_args *)data;
+
+ for (i =0; i < ARRAY_SIZE(codec_option_array); i++) {
+ dmuci_get_value_by_section_string(line_codecargs->sip_section, codec_option_array[i], &val);
+ if (strcmp(val, line_codecargs->cdc) == 0) {
+ *value = "1";
+ return 0;
+ }
+ }
+ *value = "0";
+ return 0;
+}
+
+int get_line_codec_list_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct line_codec_args *line_codecargs = (struct line_codec_args *)data;
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_voice_client", "sip_service_provider", section_name(line_codecargs->sip_section), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, line_codecargs->priority_cdc, value);
+ return 0;
+}
+
+int set_line_codec_list_packetization(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct line_codec_args *line_codecargs = (struct line_codec_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(line_codecargs->sip_section, line_codecargs->ptime_cdc, value);
+ return 0;
+ }
+ return 0;
+}
+
+int set_line_codec_list_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ int j;
+ char *codec;
+ struct line_codec_args *line_codecargs = (struct line_codec_args *)data;
+ int error = string_to_bool(value, &b);
+
+ switch (action) {
+ case VALUECHECK:
+ if (error)
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ if (b) {
+ for (j = 0; j < ARRAY_SIZE(codec_option_array); j++) {
+ dmuci_get_value_by_section_string(line_codecargs->sip_section, codec_option_array[j], &codec);
+ if(strcmp(codec, line_codecargs->cdc) == 0) {
+ return 0;
+ }
+ }
+ codec_priority_sort(line_codecargs->sip_section, line_codecargs->cdc);
+ }
+ else {
+ for (j = 0; j < ARRAY_SIZE(codec_option_array); j++) {
+ dmuci_get_value_by_section_string(line_codecargs->sip_section, codec_option_array[j], &codec);
+ if(strcmp(codec, line_codecargs->cdc) == 0) {
+ dmuci_set_value_by_section(line_codecargs->sip_section, codec_option_array[j], "");
+ }
+ }
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int set_line_codec_list_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ int i;
+ char *val;
+ struct line_codec_args *line_codecargs = (struct line_codec_args *)data;
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_voice_client", "sip_service_provider", section_name(line_codecargs->sip_section), &dmmap_section);
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(dmmap_section, line_codecargs->priority_cdc, value);
+ for (i =0; i < ARRAY_SIZE(codec_option_array); i++) {
+ dmuci_get_value_by_section_string(line_codecargs->sip_section, codec_option_array[i], &val);
+ if (strcmp(val, line_codecargs->cdc) == 0) {
+ codec_priority_sort(line_codecargs->sip_section, NULL);
+ return 0;
+ }
+ }
+ return 0;
+ }
+ return 0;
+}
+
+//////////////ENABLE SET////////////////
+bool dm_service_enable_set(void)
+{
+ if( access("/etc/init.d/asterisk", F_OK ) != -1 ) {
+ return true;
+ } else {
+ return false;
+ }
+}
+void codec_update_id()
+{
+ int i = 0;
+ int found = 0;
+ struct uci_section *s = NULL;
+ struct uci_section *ss = NULL;
+
+ for (i = 0; i < available_sip_codecs; i++) {
+ update_section_list(DMMAP,"codec_id", "id", 1, allowed_sip_codecs[i].id, NULL, NULL, NULL, NULL);
+ }
+ if(i == 0)
+ {
+ uci_path_foreach_sections(icwmpd, "dmmap", "codec_id", s) {
+ if (found != 0) {
+ DMUCI_DELETE_BY_SECTION(icwmpd, ss, NULL, NULL);
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL) {
+ DMUCI_DELETE_BY_SECTION(icwmpd, ss, NULL, NULL);
+ }
+ }
+}
+////////////////////////SET AND GET ALIAS/////////////////////////////////
+int get_service_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *service_section = (struct uci_section *)data;
+ dmuci_get_value_by_section_string(service_section, "vsalias", value);
+ return 0;
+}
+
+int set_service_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *service_section = (struct uci_section *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(service_section, "vsalias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_cap_codec_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct codec_args *cur_codec_args = (struct codec_args *)data;
+ dmuci_get_value_by_section_string(cur_codec_args->codec_section, "codecalias", value);
+ return 0;
+}
+
+int set_cap_codec_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct codec_args *cur_codec_args = (struct codec_args *)data;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(cur_codec_args->codec_section, "codecalias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_voice_profile_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_voice_client", "sip_service_provider", section_name(sipargs->sip_section), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "profilealias", value);
+ return 0;
+}
+
+int set_voice_profile_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct sip_args *sipargs = (struct sip_args *)data;
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_voice_client", "sip_service_provider", section_name(sipargs->sip_section), &dmmap_section);
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(dmmap_section, "profilealias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_line_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct tel_args *telarg = (struct tel_args *)data;
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_voice_client", "tel_line", section_name(telarg->tel_section), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "linealias", value);
+ return 0;
+}
+
+int set_line_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct tel_args *telarg = (struct tel_args *)data;
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_voice_client", "tel_line", section_name(telarg->tel_section), &dmmap_section);
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(dmmap_section, "linealias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_line_codec_list_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct line_codec_args *)data)->codec_sec, "codecalias", value);
+ return 0;
+}
+
+int set_line_codec_list_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(((struct line_codec_args *)data)->codec_sec, "codecalias", value);
+ return 0;
+ }
+ return 0;
+}
+///////////////////////////////////////
+void set_voice_profile_key_of_line(struct uci_section *dmmap_line_section, char* prev_instance){
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_line_section, "voice_profile_key", prev_instance);
+}
+
+int browseVoiceServiceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ char *vs = NULL, *vs_last = NULL;
+
+ update_section_list(DMMAP,"voice_service", NULL, 1, NULL, NULL, NULL, NULL, NULL);
+ uci_path_foreach_sections(icwmpd, "dmmap", "voice_service", s) {
+ vs = handle_update_instance(1, dmctx, &vs_last, update_instance_alias_icwmpd, 3, s, "vsinstance", "vsalias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, vs) == DM_STOP)
+ break;
+ }
+ return 0;
+}
+
+int browseCodecsInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ int i = 0;
+ char *id, *id_last = NULL;
+ struct uci_section *code_sec;
+ struct codec_args curr_codec_args = {0};
+
+ init_allowed_sip_codecs();
+ codec_update_id();
+ uci_path_foreach_sections(icwmpd, "dmmap", "codec_id", code_sec) {
+ init_codec_args(&curr_codec_args, allowed_sip_codecs[i].allowed_cdc, allowed_sip_codecs[i].id, allowed_sip_codecs[i].enumid, code_sec);
+ id = handle_update_instance(2, dmctx, &id_last, update_instance_alias_icwmpd, 3, code_sec, "codecinstance", "codecalias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_codec_args, id) == DM_STOP) {
+ fini_codec_args(&curr_codec_args);
+ break;
+ }
+ fini_codec_args(&curr_codec_args);
+ i++;
+ }
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.!UCI:voice_client/sip_service_provider/dmmap_voice_client*/
+int browseProfileInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *sip_section;
+ char *profile_num = NULL, *profile_num_last = NULL;
+ struct sip_args curr_sip_args = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+ wait_voice_service_up();
+ synchronize_specific_config_sections_with_dmmap("voice_client", "sip_service_provider", "dmmap_voice_client", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ profile_num = handle_update_instance(2, dmctx, &profile_num_last, update_instance_alias_icwmpd, 3, p->dmmap_section, "profileinstance", "profilealias");
+ init_sip_args(&curr_sip_args, p->config_section, profile_num_last);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_sip_args, profile_num) == DM_STOP)
+ break;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
+
+/*#Device.Services.VoiceService.{i}.VoiceProfile.{i}.Line.{i}.!UCI:voice_client/tel_line/dmmap_voice_client*/
+int browseLineInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ int maxLine, line_id = 0;
+ char *line_num = NULL, *last_inst = NULL;
+ struct uci_section *b_section = NULL;
+ json_object *res, *jobj;
+ struct sip_args *sipargs = (struct sip_args *)prev_data;
+ struct tel_args curr_tel_args = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ maxLine = get_voice_service_max_line();
+
+ synchronize_specific_config_sections_with_dmmap_eq("voice_client", "tel_line", "dmmap_voice_client", "sip_account", section_name(sipargs->sip_section), &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ line_id = atoi(section_name(p->config_section) + strlen(section_name(p->config_section)) - 1);
+ if ( line_id >= maxLine )
+ continue;
+ set_voice_profile_key_of_line(p->dmmap_section, prev_instance);
+ line_num = handle_update_instance(3, dmctx, &last_inst, update_instance_alias_icwmpd, 3, p->dmmap_section, "lineinstance", "linealias");
+ init_tel_args(&curr_tel_args, p->config_section, sipargs->sip_section, sipargs->profile_num); //check difference between sipargs->profile_num and profile_num
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_tel_args, line_num) == DM_STOP)
+ break;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
+
+int browseLineCodecListInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ int i = 0;
+ char *id = NULL , *id_last = NULL;
+ struct tel_args *telargs = (struct tel_args *)prev_data;
+ struct uci_section *code_sec = NULL;
+ struct line_codec_args curr_line_codec_args = {0};
+
+ init_allowed_sip_codecs();
+ codec_update_id();
+ codec_priority_update(telargs->sip_section);
+ uci_path_foreach_sections(icwmpd, "dmmap", "codec_id", code_sec) {
+ init_line_code_args(&curr_line_codec_args, i, telargs->sip_section, code_sec);
+ id = handle_update_instance(4, dmctx, &id_last, update_instance_alias_icwmpd, 3, code_sec, "codecinstance", "codecalias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_line_codec_args, id) == DM_STOP)
+ break;
+ i++;
+ }
+ return 0;
+}
diff --git a/dmtree/tr104/voice_services.h b/dmtree/tr104/voice_services.h
new file mode 100644
index 00000000..8949f521
--- /dev/null
+++ b/dmtree/tr104/voice_services.h
@@ -0,0 +1,262 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2012-2014 PIVA SOFTWARE (www.pivasoftware.com)
+* Author: Imen Bhiri
+ * Author: Feten Besbes
+ * Author: Mohamed Kallel
+ * Author: Anis Ellouze
+ */
+
+#ifndef __VOICE_H
+#define __VOICE_H
+
+extern DMOBJ tServiceObj[];
+extern DMOBJ tVoiceServiceObj[];
+extern DMLEAF tVoiceServiceParam[];
+extern DMLEAF tCapabilitiesParams[];
+extern DMOBJ tCapabilitiesObj[];
+extern DMLEAF tSIPParams[];
+extern DMLEAF tCodecsParams[] ;
+extern DMOBJ tProfileObj[] ;
+extern DMLEAF tProfileSIPParams[];
+extern DMLEAF tServiceProviderInfoParams[];
+extern DMLEAF tProfileParam[];
+extern DMOBJ tLineObj[];
+extern DMOBJ tLineCodecObj[];
+extern DMLEAF tLineCodecListParams[];
+extern DMLEAF tLineSIPParams[];
+extern DMLEAF tVoiceProcessingParams[];
+extern DMLEAF tCallingFeaturesParams[];
+extern DMLEAF tLineParams[];
+extern DMLEAF tRTPParams[];
+extern DMOBJ tRTPObj[];
+extern DMLEAF tSRTPParam[];
+extern DMLEAF tRTCPParams[];
+extern DMLEAF tFaxT38Params[];
+
+struct codec_args
+{
+ char *cdc;
+ char *id;
+ int enumid;
+ struct uci_section *codec_section;
+};
+
+struct rtp_tos
+{
+ char *key;
+ char *val;
+};
+
+struct cap_sip_codec
+{
+ int enumid;
+ char *c1;
+ char *c2;
+ char *c3;
+ char *c4;
+ char *c5;
+};
+
+struct sip_args
+{
+ struct uci_section *sip_section;
+ char *profile_num;
+};
+
+struct tel_args
+{
+ struct uci_section *tel_section;
+ struct uci_section *sip_section;
+ char *profile_num;
+};
+
+struct allow_sip_codec
+{
+ int enumid;
+ char *id;
+ char *allowed_cdc;
+ char *priority_cdc;
+ char *ptime_cdc;
+};
+
+struct line_codec_args
+{
+ int enumid;
+ char *sip_id;
+ char *cdc;
+ char *id;
+ char *priority_cdc;
+ char *ptime_cdc;
+ struct uci_section *sip_section;
+ struct uci_section *codec_sec;
+};
+
+struct region
+{
+ char *country;
+ char *id;
+};
+
+struct codec
+{
+ char *cdc;
+ char *id;
+ char *priority;
+};
+
+enum enum_cap_sip_codecs {
+ SIP_CODEC_G723,
+ SIP_CODEC_GSM,
+ SIP_CODEC_ULAW,
+ SIP_CODEC_ALAW,
+ SIP_CODEC_G726AAL2,
+ SIP_CODEC_ADPCM,
+ SIP_CODEC_SLIN,
+ SIP_CODEC_LPC10,
+ SIP_CODEC_G729,
+ SIP_CODEC_SPEEX,
+ SIP_CODEC_ILBC,
+ SIP_CODEC_G726,
+ SIP_CODEC_G722,
+ SIP_CODEC_SIREN7,
+ SIP_CODEC_SIREN14,
+ SIP_CODEC_SLIN16,
+ SIP_CODEC_G719,
+ SIP_CODEC_SPEEX16,
+ SIP_CODEC_TESTLAW
+};
+
+bool dm_service_enable_set(void);
+int browseVoiceServiceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseCodecsInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseProfileInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseLineInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseLineCodecListInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int add_profile_object(char *refparam, struct dmctx *ctx, void *data, char **instancepara);
+int delete_profile_object(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int add_line_object(char *refparam, struct dmctx *ctx, void *data, char **instancepara);
+int delete_line_object(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+
+int get_service_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_max_profile_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_max_line_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_true_value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_max_session_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_signal_protocols(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_regions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_false_value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_role(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_extension(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_tls_auth_protocols(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_tls_enc_protocols(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_tls_key_protocols(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_cap_codec_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_entry_id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_capabilities_sip_codec(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_capabilities_sip_bitrate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_capabilities_sip_pperiod(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_signalprotocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_max_sessions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_number_of_lines(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_sip_dtmfmethod(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_profile_region(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_sip_proxyserver(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_proxy_server_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_sip_registerserver(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_sip_registerserverport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_registrar_server_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_user_agent_domain(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_user_agent_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_user_agent_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_outbound_proxy(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_outbound_proxy_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_registration_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_re_invite_expires(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_call_lines(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_service_serviceproviderinfo_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_sip_fax_t38_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_service_vp_rtp_portmin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_service_vp_rtp_portmax(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_service_vp_rtp_dscp(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_service_vp_rtp_rtcp_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_service_vp_rtp_rtcp_txrepeatinterval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_service_vp_rtp_srtp_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_line_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_line_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_voice_profile_line_callstate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_line_profile(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_tel_line(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_confort_noise_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_voice_processing_cancellation_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_calling_features_caller_id_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_calling_features_callwaiting(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_sip_auth_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_sip_uri(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_codec_list_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_codec_entry_id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int capabilities_sip_codecs_get_codec(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int capabilities_sip_codecs_get_bitrate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_capabilities_sip_codecs_pperiod(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_codec_list_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_codec_list_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_line_directory_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int set_service_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_cap_codec_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_profile_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_profile_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_profile_reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_profile_signaling_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_profile_sip_dtmfmethod(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_profile_sip_proxyserver(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_proxy_server_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_proxy_server_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_profile_sip_registerserver(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_profile_sip_registerserverport(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_registrar_server_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_user_agent_domain(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_user_agent_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_user_agent_transport(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_outbound_proxy(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_outbound_proxy_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_registration_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_re_invite_expires(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_call_lines(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_service_serviceproviderinfo_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_fax_t38_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_service_vp_rtp_portmin(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_profile_rtp_localportmax(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_service_vp_rtp_dscp(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_service_vp_rtp_rtcp_txrepeatinterval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_service_vp_rtp_srtp_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_voice_profile_line_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_directory_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_line_profile(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_tel_line(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_confort_noise_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_calling_features_caller_id_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_voice_processing_cancellation_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_calling_features_callwaiting(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_sip_auth_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_sip_auth_password(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_sip_uri(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_codec_list_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_codec_list_packetization(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_codec_list_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_line_codec_list_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_sip_profile_region(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_voice_service_max_line();
+
+#endif
diff --git a/dmtree/tr143/diagnostics.c b/dmtree/tr143/diagnostics.c
new file mode 100644
index 00000000..5e524809
--- /dev/null
+++ b/dmtree/tr143/diagnostics.c
@@ -0,0 +1,2469 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Amin Ben Ramdhane
+*
+*/
+
+#include
+#include
+#include
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcwmp.h"
+#include "dmcommon.h"
+#include "dmjson.h"
+#include "dmentry.h"
+#include "diagnostics.h"
+
+/* *** Device.IP.Diagnostics. *** */
+DMOBJ tIPDiagnosticsObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"IPPing", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsIPPingParams, NULL, BBFDM_CWMP},
+{"TraceRoute", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsTraceRouteObj, tIPDiagnosticsTraceRouteParams, NULL, BBFDM_CWMP},
+{"DownloadDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsDownloadDiagnosticsObj, tIPDiagnosticsDownloadDiagnosticsParams, NULL, BBFDM_CWMP},
+{"UploadDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsUploadDiagnosticsObj, tIPDiagnosticsUploadDiagnosticsParams, NULL, BBFDM_CWMP},
+{"UDPEchoConfig", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsUDPEchoConfigParams, NULL, BBFDM_CWMP},
+{"UDPEchoDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsUDPEchoDiagnosticsParams, NULL, BBFDM_CWMP},
+{"ServerSelectionDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsServerSelectionDiagnosticsParams, NULL, BBFDM_CWMP},
+{0}
+};
+
+DMLEAF tIPDiagnosticsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"IPv4PingSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv6PingSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv4TraceRouteSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv6TraceRouteSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv4DownloadDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv6DownloadDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv4UploadDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv6UploadDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv4UDPEchoDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv6UDPEchoDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv4ServerSelectionDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{"IPv6ServerSelectionDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/* *** Device.IP.Diagnostics.IPPing. *** */
+DMLEAF tIPDiagnosticsIPPingParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"DiagnosticsState", &DMWRITE, DMT_STRING, get_ip_ping_diagnostics_state, set_ip_ping_diagnostics_state, NULL, NULL, BBFDM_CWMP},
+{"Interface", &DMWRITE, DMT_STRING, get_ip_ping_interface, set_ip_ping_interface, NULL, NULL, BBFDM_CWMP},
+{"ProtocolVersion", &DMWRITE, DMT_STRING, get_ip_ping_protocolversion, set_ip_ping_protocolversion, NULL, NULL, BBFDM_CWMP},
+{"Host", &DMWRITE, DMT_STRING, get_ip_ping_host, set_ip_ping_host, NULL, NULL, BBFDM_CWMP},
+{"NumberOfRepetitions", &DMWRITE, DMT_UNINT, get_ip_ping_repetition_number, set_ip_ping_repetition_number, NULL, NULL, BBFDM_CWMP},
+{"Timeout", &DMWRITE, DMT_UNINT, get_ip_ping_timeout, set_ip_ping_timeout, NULL, NULL, BBFDM_CWMP},
+{"DataBlockSize", &DMWRITE, DMT_UNINT, get_ip_ping_block_size, set_ip_ping_block_size, NULL, NULL, BBFDM_CWMP},
+{"DSCP", &DMWRITE, DMT_UNINT, get_ip_ping_DSCP, set_ip_ping_DSCP, NULL, NULL, BBFDM_CWMP},
+{"SuccessCount", &DMREAD, DMT_UNINT, get_ip_ping_success_count, NULL, NULL, NULL, BBFDM_CWMP},
+{"FailureCount", &DMREAD, DMT_UNINT, get_ip_ping_failure_count, NULL, NULL, NULL, BBFDM_CWMP},
+{"AverageResponseTime", &DMREAD, DMT_UNINT, get_ip_ping_average_response_time, NULL, NULL, NULL, BBFDM_CWMP},
+{"MinimumResponseTime", &DMREAD, DMT_UNINT, get_ip_ping_min_response_time, NULL, NULL, NULL, BBFDM_CWMP},
+{"MaximumResponseTime", &DMREAD, DMT_UNINT, get_ip_ping_max_response_time, NULL, NULL, NULL, BBFDM_CWMP},
+{"AverageResponseTimeDetailed", &DMREAD, DMT_UNINT, get_ip_ping_AverageResponseTimeDetailed, NULL, NULL, NULL, BBFDM_CWMP},
+{"MinimumResponseTimeDetailed", &DMREAD, DMT_UNINT, get_ip_ping_MinimumResponseTimeDetailed, NULL, NULL, NULL, BBFDM_CWMP},
+{"MaximumResponseTimeDetailed", &DMREAD, DMT_UNINT, get_ip_ping_MaximumResponseTimeDetailed, NULL, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/* *** Device.IP.Diagnostics.TraceRoute. *** */
+DMOBJ tIPDiagnosticsTraceRouteObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"RouteHops", &DMREAD, NULL, NULL, NULL, browseIPDiagnosticsTraceRouteRouteHopsInst, NULL, NULL, NULL, tIPDiagnosticsTraceRouteRouteHopsParams, NULL, BBFDM_CWMP},
+{0}
+};
+
+DMLEAF tIPDiagnosticsTraceRouteParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"DiagnosticsState", &DMWRITE, DMT_STRING, get_IPDiagnosticsTraceRoute_DiagnosticsState, set_IPDiagnosticsTraceRoute_DiagnosticsState, NULL, NULL, BBFDM_CWMP},
+{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsTraceRoute_Interface, set_IPDiagnosticsTraceRoute_Interface, NULL, NULL, BBFDM_CWMP},
+{"ProtocolVersion", &DMWRITE, DMT_STRING, get_IPDiagnosticsTraceRoute_ProtocolVersion, set_IPDiagnosticsTraceRoute_ProtocolVersion, NULL, NULL, BBFDM_CWMP},
+{"Host", &DMWRITE, DMT_STRING, get_IPDiagnosticsTraceRoute_Host, set_IPDiagnosticsTraceRoute_Host, NULL, NULL, BBFDM_CWMP},
+{"NumberOfTries", &DMWRITE, DMT_UNINT, get_IPDiagnosticsTraceRoute_NumberOfTries, set_IPDiagnosticsTraceRoute_NumberOfTries, NULL, NULL, BBFDM_CWMP},
+{"Timeout", &DMWRITE, DMT_UNINT, get_IPDiagnosticsTraceRoute_Timeout, set_IPDiagnosticsTraceRoute_Timeout, NULL, NULL, BBFDM_CWMP},
+{"DataBlockSize", &DMWRITE, DMT_UNINT, get_IPDiagnosticsTraceRoute_DataBlockSize, set_IPDiagnosticsTraceRoute_DataBlockSize, NULL, NULL, BBFDM_CWMP},
+{"DSCP", &DMWRITE, DMT_UNINT, get_IPDiagnosticsTraceRoute_DSCP, set_IPDiagnosticsTraceRoute_DSCP, NULL, NULL, BBFDM_CWMP},
+{"MaxHopCount", &DMWRITE, DMT_UNINT, get_IPDiagnosticsTraceRoute_MaxHopCount, set_IPDiagnosticsTraceRoute_MaxHopCount, NULL, NULL, BBFDM_CWMP},
+{"ResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsTraceRoute_ResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"RouteHopsNumberOfEntries", &DMREAD, DMT_UNINT, get_IPDiagnosticsTraceRoute_RouteHopsNumberOfEntries, NULL, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/* *** Device.IP.Diagnostics.TraceRoute.RouteHops.{i}. *** */
+DMLEAF tIPDiagnosticsTraceRouteRouteHopsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Host", &DMREAD, DMT_STRING, get_IPDiagnosticsTraceRouteRouteHops_Host, NULL, NULL, NULL, BBFDM_CWMP},
+{"HostAddress", &DMREAD, DMT_STRING, get_IPDiagnosticsTraceRouteRouteHops_HostAddress, NULL, NULL, NULL, BBFDM_CWMP},
+{"ErrorCode", &DMREAD, DMT_UNINT, get_IPDiagnosticsTraceRouteRouteHops_ErrorCode, NULL, NULL, NULL, BBFDM_CWMP},
+{"RTTimes", &DMREAD, DMT_STRING, get_IPDiagnosticsTraceRouteRouteHops_RTTimes, NULL, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/* *** Device.IP.Diagnostics.DownloadDiagnostics. *** */
+DMOBJ tIPDiagnosticsDownloadDiagnosticsObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"PerConnectionResult", &DMREAD, NULL, NULL, NULL, browseIPDiagnosticsDownloadDiagnosticsPerConnectionResultInst, NULL, NULL, NULL, tIPDiagnosticsDownloadDiagnosticsPerConnectionResultParams, NULL, BBFDM_CWMP},
+{0}
+};
+
+DMLEAF tIPDiagnosticsDownloadDiagnosticsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"DiagnosticsState", &DMWRITE, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_DiagnosticsState, set_IPDiagnosticsDownloadDiagnostics_DiagnosticsState, NULL, NULL, BBFDM_CWMP},
+{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_Interface, set_IPDiagnosticsDownloadDiagnostics_Interface, NULL, NULL, BBFDM_CWMP},
+{"DownloadURL", &DMWRITE, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_DownloadURL, set_IPDiagnosticsDownloadDiagnostics_DownloadURL, NULL, NULL, BBFDM_CWMP},
+{"DownloadTransports", &DMREAD, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_DownloadTransports, NULL, NULL, NULL, BBFDM_CWMP},
+{"DownloadDiagnosticMaxConnections", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_DownloadDiagnosticMaxConnections, NULL, NULL, NULL, BBFDM_CWMP},
+{"DSCP", &DMWRITE, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_DSCP, set_IPDiagnosticsDownloadDiagnostics_DSCP, NULL, NULL, BBFDM_CWMP},
+{"EthernetPriority", &DMWRITE, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_EthernetPriority, set_IPDiagnosticsDownloadDiagnostics_EthernetPriority, NULL, NULL, BBFDM_CWMP},
+{"ProtocolVersion", &DMWRITE, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_ProtocolVersion, set_IPDiagnosticsDownloadDiagnostics_ProtocolVersion, NULL, NULL, BBFDM_CWMP},
+{"NumberOfConnections", &DMWRITE, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_NumberOfConnections, set_IPDiagnosticsDownloadDiagnostics_NumberOfConnections, NULL, NULL, BBFDM_CWMP},
+{"ROMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnostics_ROMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"BOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnostics_BOMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"EOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnostics_EOMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"TestBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TestBytesReceived, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TotalBytesReceived, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesSent", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TotalBytesSent, NULL, NULL, NULL, BBFDM_CWMP},
+{"TestBytesReceivedUnderFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TestBytesReceivedUnderFullLoading, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesReceivedUnderFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TotalBytesReceivedUnderFullLoading, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesSentUnderFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TotalBytesSentUnderFullLoading, NULL, NULL, NULL, BBFDM_CWMP},
+{"PeriodOfFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_PeriodOfFullLoading, NULL, NULL, NULL, BBFDM_CWMP},
+{"TCPOpenRequestTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnostics_TCPOpenRequestTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"TCPOpenResponseTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnostics_TCPOpenResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"PerConnectionResultNumberOfEntries", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_PerConnectionResultNumberOfEntries, NULL, NULL, NULL, BBFDM_CWMP},
+{"EnablePerConnectionResults", &DMWRITE, DMT_BOOL, get_IPDiagnosticsDownloadDiagnostics_EnablePerConnectionResults, set_IPDiagnosticsDownloadDiagnostics_EnablePerConnectionResults, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/* *** Device.IP.Diagnostics.DownloadDiagnostics.PerConnectionResult.{i}. *** */
+DMLEAF tIPDiagnosticsDownloadDiagnosticsPerConnectionResultParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"ROMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_ROMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"BOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_BOMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"EOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_EOMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"TestBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TestBytesReceived, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TotalBytesReceived, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesSent", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TotalBytesSent, NULL, NULL, NULL, BBFDM_CWMP},
+{"TCPOpenRequestTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TCPOpenRequestTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"TCPOpenResponseTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TCPOpenResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/* *** Device.IP.Diagnostics.UploadDiagnostics. *** */
+DMOBJ tIPDiagnosticsUploadDiagnosticsObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"PerConnectionResult", &DMREAD, NULL, NULL, NULL, browseIPDiagnosticsUploadDiagnosticsPerConnectionResultInst, NULL, NULL, NULL, tIPDiagnosticsUploadDiagnosticsPerConnectionResultParams, NULL, BBFDM_CWMP},
+{0}
+};
+
+DMLEAF tIPDiagnosticsUploadDiagnosticsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"DiagnosticsState", &DMWRITE, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_DiagnosticsState, set_IPDiagnosticsUploadDiagnostics_DiagnosticsState, NULL, NULL, BBFDM_CWMP},
+{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_Interface, set_IPDiagnosticsUploadDiagnostics_Interface, NULL, NULL, BBFDM_CWMP},
+{"UploadURL", &DMWRITE, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_UploadURL, set_IPDiagnosticsUploadDiagnostics_UploadURL, NULL, NULL, BBFDM_CWMP},
+{"UploadTransports", &DMREAD, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_UploadTransports, NULL, NULL, NULL, BBFDM_CWMP},
+{"DSCP", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_DSCP, set_IPDiagnosticsUploadDiagnostics_DSCP, NULL, NULL, BBFDM_CWMP},
+{"EthernetPriority", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_EthernetPriority, set_IPDiagnosticsUploadDiagnostics_EthernetPriority, NULL, NULL, BBFDM_CWMP},
+{"TestFileLength", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_TestFileLength, set_IPDiagnosticsUploadDiagnostics_TestFileLength, NULL, NULL, BBFDM_CWMP},
+{"ProtocolVersion", &DMWRITE, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_ProtocolVersion, set_IPDiagnosticsUploadDiagnostics_ProtocolVersion, NULL, NULL, BBFDM_CWMP},
+{"NumberOfConnections", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_NumberOfConnections, set_IPDiagnosticsUploadDiagnostics_NumberOfConnections, NULL, NULL, BBFDM_CWMP},
+{"ROMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnostics_ROMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"BOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnostics_BOMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"EOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnostics_EOMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"TestBytesSent", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_TestBytesSent, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_TotalBytesReceived, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesSent", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_TotalBytesSent, NULL, NULL, NULL, BBFDM_CWMP},
+{"TestBytesSentUnderFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_TestBytesSentUnderFullLoading, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesReceivedUnderFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_TotalBytesReceivedUnderFullLoading, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesSentUnderFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_TotalBytesSentUnderFullLoading, NULL, NULL, NULL, BBFDM_CWMP},
+{"PeriodOfFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_PeriodOfFullLoading, NULL, NULL, NULL, BBFDM_CWMP},
+{"TCPOpenRequestTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnostics_TCPOpenRequestTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"TCPOpenResponseTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnostics_TCPOpenResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"PerConnectionResultNumberOfEntries", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_PerConnectionResultNumberOfEntries, NULL, NULL, NULL, BBFDM_CWMP},
+{"EnablePerConnectionResults", &DMWRITE, DMT_BOOL, get_IPDiagnosticsUploadDiagnostics_EnablePerConnectionResults, set_IPDiagnosticsUploadDiagnostics_EnablePerConnectionResults, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/* *** Device.IP.Diagnostics.UploadDiagnostics.PerConnectionResult.{i}. *** */
+DMLEAF tIPDiagnosticsUploadDiagnosticsPerConnectionResultParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"ROMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_ROMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"BOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_BOMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"EOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_EOMTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"TestBytesSent", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TestBytesSent, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TotalBytesReceived, NULL, NULL, NULL, BBFDM_CWMP},
+{"TotalBytesSent", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TotalBytesSent, NULL, NULL, NULL, BBFDM_CWMP},
+{"TCPOpenRequestTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TCPOpenRequestTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"TCPOpenResponseTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TCPOpenResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/* *** Device.IP.Diagnostics.UDPEchoConfig. *** */
+DMLEAF tIPDiagnosticsUDPEchoConfigParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_IPDiagnosticsUDPEchoConfig_Enable, set_IPDiagnosticsUDPEchoConfig_Enable, NULL, NULL, BBFDM_CWMP},
+{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoConfig_Interface, set_IPDiagnosticsUDPEchoConfig_Interface, NULL, NULL, BBFDM_CWMP},
+{"SourceIPAddress", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoConfig_SourceIPAddress, set_IPDiagnosticsUDPEchoConfig_SourceIPAddress, NULL, NULL, BBFDM_CWMP},
+{"UDPPort", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoConfig_UDPPort, set_IPDiagnosticsUDPEchoConfig_UDPPort, NULL, NULL, BBFDM_CWMP},
+{"EchoPlusEnabled", &DMWRITE, DMT_BOOL, get_IPDiagnosticsUDPEchoConfig_EchoPlusEnabled, set_IPDiagnosticsUDPEchoConfig_EchoPlusEnabled, NULL, NULL, BBFDM_CWMP},
+{"EchoPlusSupported", &DMREAD, DMT_BOOL, get_IPDiagnosticsUDPEchoConfig_EchoPlusSupported, NULL, NULL, NULL, BBFDM_CWMP},
+{"PacketsReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoConfig_PacketsReceived, NULL, NULL, NULL, BBFDM_CWMP},
+{"PacketsResponded", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoConfig_PacketsResponded, NULL, NULL, NULL, BBFDM_CWMP},
+{"BytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoConfig_BytesReceived, NULL, NULL, NULL, BBFDM_CWMP},
+{"BytesResponded", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoConfig_BytesResponded, NULL, NULL, NULL, BBFDM_CWMP},
+{"TimeFirstPacketReceived", &DMREAD, DMT_TIME, get_IPDiagnosticsUDPEchoConfig_TimeFirstPacketReceived, NULL, NULL, NULL, BBFDM_CWMP},
+{"TimeLastPacketReceived", &DMREAD, DMT_TIME, get_IPDiagnosticsUDPEchoConfig_TimeLastPacketReceived, NULL, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/* *** Device.IP.Diagnostics.UDPEchoDiagnostics. *** */
+DMLEAF tIPDiagnosticsUDPEchoDiagnosticsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"DiagnosticsState", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoDiagnostics_DiagnosticsState, set_IPDiagnosticsUDPEchoDiagnostics_DiagnosticsState, NULL, NULL, BBFDM_CWMP},
+{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoDiagnostics_Interface, set_IPDiagnosticsUDPEchoDiagnostics_Interface, NULL, NULL, BBFDM_CWMP},
+{"Host", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoDiagnostics_Host, set_IPDiagnosticsUDPEchoDiagnostics_Host, NULL, NULL, BBFDM_CWMP},
+{"Port", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_Port, set_IPDiagnosticsUDPEchoDiagnostics_Port, NULL, NULL, BBFDM_CWMP},
+{"NumberOfRepetitions", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_NumberOfRepetitions, set_IPDiagnosticsUDPEchoDiagnostics_NumberOfRepetitions, NULL, NULL, BBFDM_CWMP},
+{"Timeout", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_Timeout, set_IPDiagnosticsUDPEchoDiagnostics_Timeout, NULL, NULL, BBFDM_CWMP},
+{"DataBlockSize", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_DataBlockSize, set_IPDiagnosticsUDPEchoDiagnostics_DataBlockSize, NULL, NULL, BBFDM_CWMP},
+{"DSCP", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_DSCP, set_IPDiagnosticsUDPEchoDiagnostics_DSCP, NULL, NULL, BBFDM_CWMP},
+{"InterTransmissionTime", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_InterTransmissionTime, set_IPDiagnosticsUDPEchoDiagnostics_InterTransmissionTime, NULL, NULL, BBFDM_CWMP},
+{"ProtocolVersion", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoDiagnostics_ProtocolVersion, set_IPDiagnosticsUDPEchoDiagnostics_ProtocolVersion, NULL, NULL, BBFDM_CWMP},
+{"SuccessCount", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_SuccessCount, NULL, NULL, NULL, BBFDM_CWMP},
+{"FailureCount", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_FailureCount, NULL, NULL, NULL, BBFDM_CWMP},
+{"AverageResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_AverageResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"MinimumResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_MinimumResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"MaximumResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_MaximumResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/* *** Device.IP.Diagnostics.ServerSelectionDiagnostics. *** */
+DMLEAF tIPDiagnosticsServerSelectionDiagnosticsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"DiagnosticsState", &DMWRITE, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_DiagnosticsState, set_IPDiagnosticsServerSelectionDiagnostics_DiagnosticsState, NULL, NULL, BBFDM_CWMP},
+{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_Interface, set_IPDiagnosticsServerSelectionDiagnostics_Interface, NULL, NULL, BBFDM_CWMP},
+{"ProtocolVersion", &DMWRITE, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_ProtocolVersion, set_IPDiagnosticsServerSelectionDiagnostics_ProtocolVersion, NULL, NULL, BBFDM_CWMP},
+{"Protocol", &DMWRITE, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_Protocol, set_IPDiagnosticsServerSelectionDiagnostics_Protocol, NULL, NULL, BBFDM_CWMP},
+{"Port", &DMWRITE, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_Port, set_IPDiagnosticsServerSelectionDiagnostics_Port, NULL, NULL, BBFDM_CWMP},
+{"HostList", &DMWRITE, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_HostList, set_IPDiagnosticsServerSelectionDiagnostics_HostList, NULL, NULL, BBFDM_CWMP},
+{"NumberOfRepetitions", &DMWRITE, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_NumberOfRepetitions, set_IPDiagnosticsServerSelectionDiagnostics_NumberOfRepetitions, NULL, NULL, BBFDM_CWMP},
+{"Timeout", &DMWRITE, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_Timeout, set_IPDiagnosticsServerSelectionDiagnostics_Timeout, NULL, NULL, BBFDM_CWMP},
+{"FastestHost", &DMREAD, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_FastestHost, NULL, NULL, NULL, BBFDM_CWMP},
+{"MinimumResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_MinimumResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"AverageResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_AverageResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{"MaximumResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_MaximumResponseTime, NULL, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+int get_diag_enable_true(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+/*
+ * *** Device.IP.Diagnostics.IPPing. ***
+ */
+
+static inline char *ipping_get(char *option, char *def)
+{
+ char *tmp;
+ dmuci_get_varstate_string("cwmp", "@ippingdiagnostic[0]", option, &tmp);
+ if(tmp && tmp[0] == '\0')
+ return dmstrdup(def);
+ else
+ return tmp;
+}
+
+int get_ip_ping_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("DiagnosticState", "None");
+ return 0;
+}
+
+int set_ip_ping_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "Requested") == 0) {
+ IPPING_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "ippingdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "ippingdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@ippingdiagnostic[0]", "DiagnosticState", value);
+ cwmp_set_end_session(END_SESSION_IPPING_DIAGNOSTIC);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_ip_ping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@ippingdiagnostic[0]", "interface", value);
+ return 0;
+}
+
+int set_ip_ping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ IPPING_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "ippingdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "ippingdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@ippingdiagnostic[0]", "interface", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_ip_ping_protocolversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("ProtocolVersion", "Any");
+ return 0;
+}
+
+int set_ip_ping_protocolversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "IPv4") == 0 || strcmp(value, "IPv6") == 0) {
+ IPPING_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "ippingdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "ippingdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@ippingdiagnostic[0]", "ProtocolVersion", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_ip_ping_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@ippingdiagnostic[0]", "Host", value);
+ return 0;
+}
+
+int set_ip_ping_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ IPPING_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "ippingdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "ippingdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@ippingdiagnostic[0]", "Host", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_ip_ping_repetition_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("NumberOfRepetitions", "3");
+ return 0;
+}
+
+int set_ip_ping_repetition_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (atoi(value) >= 1) {
+ IPPING_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "ippingdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "ippingdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@ippingdiagnostic[0]", "NumberOfRepetitions", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_ip_ping_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("Timeout", "1000");
+ return 0;
+}
+
+int set_ip_ping_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (atoi(value) >= 1) {
+ IPPING_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "ippingdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "ippingdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@ippingdiagnostic[0]", "Timeout", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_ip_ping_block_size(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("DataBlockSize", "64");
+
+ return 0;
+}
+
+int set_ip_ping_block_size(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if ((atoi(value) >= 1) && (atoi(value) <= 65535)) {
+ IPPING_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "ippingdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "ippingdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@ippingdiagnostic[0]", "DataBlockSize", value);
+ }
+ }
+ return 0;
+}
+
+int get_ip_ping_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("DSCP", "0");
+ return 0;
+}
+
+int set_ip_ping_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if ((atoi(value) >= 0) && (atoi(value) <= 63)) {
+ TRACEROUTE_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "ippingdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "ippingdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@ippingdiagnostic[0]", "DSCP", value);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int get_ip_ping_success_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("SuccessCount", "0");
+ return 0;
+}
+
+int get_ip_ping_failure_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("FailureCount", "0");
+ return 0;
+}
+
+int get_ip_ping_average_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("AverageResponseTime", "0");
+ return 0;
+}
+
+int get_ip_ping_min_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("MinimumResponseTime", "0");
+ return 0;
+}
+
+int get_ip_ping_max_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("MaximumResponseTime", "0");
+ return 0;
+}
+
+int get_ip_ping_AverageResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("AverageResponseTimeDetailed", "0");
+ return 0;
+}
+
+int get_ip_ping_MinimumResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("MinimumResponseTimeDetailed", "0");
+ return 0;
+}
+
+int get_ip_ping_MaximumResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ipping_get("MaximumResponseTimeDetailed", "0");
+ return 0;
+}
+
+/*
+ * *** Device.IP.Diagnostics.TraceRoute. ***
+ */
+
+static inline char *traceroute_get(char *option, char *def)
+{
+ char *tmp;
+ dmuci_get_varstate_string("cwmp", "@traceroutediagnostic[0]", option, &tmp);
+ if(tmp && tmp[0] == '\0')
+ return dmstrdup(def);
+ else
+ return tmp;
+}
+
+int get_IPDiagnosticsTraceRoute_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = traceroute_get("DiagnosticState", "None");
+ return 0;
+}
+
+int set_IPDiagnosticsTraceRoute_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "Requested") == 0) {
+ TRACEROUTE_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "traceroutediagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "traceroutediagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@traceroutediagnostic[0]", "DiagnosticState", value);
+ cwmp_set_end_session(END_SESSION_TRACEROUTE_DIAGNOSTIC);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRoute_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@traceroutediagnostic[0]", "interface", value);
+ return 0;
+}
+
+int set_IPDiagnosticsTraceRoute_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ TRACEROUTE_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "traceroutediagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "traceroutediagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@traceroutediagnostic[0]", "interface", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRoute_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = traceroute_get("ProtocolVersion", "Any");
+ return 0;
+}
+
+int set_IPDiagnosticsTraceRoute_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "IPv4") == 0 || strcmp(value, "IPv6") == 0) {
+ TRACEROUTE_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "traceroutediagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "traceroutediagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@traceroutediagnostic[0]", "ProtocolVersion", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRoute_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@traceroutediagnostic[0]", "Host", value);
+ return 0;
+}
+
+int set_IPDiagnosticsTraceRoute_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ TRACEROUTE_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "traceroutediagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "traceroutediagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@traceroutediagnostic[0]", "Host", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRoute_NumberOfTries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = traceroute_get("NumberOfTries", "3");
+ return 0;
+}
+
+int set_IPDiagnosticsTraceRoute_NumberOfTries(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if ((atoi(value) >= 1) && (atoi(value) <= 3)) {
+ TRACEROUTE_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "traceroutediagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "traceroutediagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@traceroutediagnostic[0]", "NumberOfTries", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRoute_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = traceroute_get("Timeout", "5000");
+ return 0;
+}
+
+int set_IPDiagnosticsTraceRoute_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (atoi(value) >= 1) {
+ TRACEROUTE_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "traceroutediagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "traceroutediagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@traceroutediagnostic[0]", "Timeout", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRoute_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = traceroute_get("DataBlockSize", "38");
+ return 0;
+}
+
+int set_IPDiagnosticsTraceRoute_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if ((atoi(value) >= 1) && (atoi(value) <= 65535)) {
+ TRACEROUTE_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "traceroutediagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "traceroutediagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@traceroutediagnostic[0]", "DataBlockSize", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRoute_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = traceroute_get("DSCP", "0");
+ return 0;
+}
+
+int set_IPDiagnosticsTraceRoute_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if ((atoi(value) >= 0) && (atoi(value) <= 63)) {
+ TRACEROUTE_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "traceroutediagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "traceroutediagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@traceroutediagnostic[0]", "DSCP", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRoute_MaxHopCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = traceroute_get("MaxHops", "30");
+ return 0;
+}
+
+int set_IPDiagnosticsTraceRoute_MaxHopCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if ((atoi(value) >= 1) && (atoi(value) <= 64)) {
+ TRACEROUTE_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "traceroutediagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "traceroutediagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@traceroutediagnostic[0]", "MaxHops", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRoute_ResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = traceroute_get("ResponseTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRoute_RouteHopsNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = traceroute_get("NumberOfHops", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRouteRouteHops_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "host", value);
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRouteRouteHops_HostAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", value);
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRouteRouteHops_ErrorCode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ return 0;
+}
+
+int get_IPDiagnosticsTraceRouteRouteHops_RTTimes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "time", value);
+ return 0;
+}
+
+/*
+ * *** Device.IP.Diagnostics.DownloadDiagnostics. ***
+ */
+
+static inline char *download_get(char *option, char *def)
+{
+ char *tmp;
+ dmuci_get_varstate_string("cwmp", "@downloaddiagnostic[0]", option, &tmp);
+ if(tmp && tmp[0] == '\0')
+ return dmstrdup(def);
+ else
+ return tmp;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("DiagnosticState", "None");
+ return 0;
+}
+
+int set_IPDiagnosticsDownloadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "Requested") == 0) {
+ DOWNLOAD_DIAGNOSTIC_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "downloaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "downloaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@downloaddiagnostic[0]", "DiagnosticState", value);
+ cwmp_set_end_session(END_SESSION_DOWNLOAD_DIAGNOSTIC);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *linker;
+ dmuci_get_varstate_string("cwmp", "@downloaddiagnostic[0]", "interface", &linker);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value); // MEM WILL BE FREED IN DMMEMCLEAN
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+int set_IPDiagnosticsDownloadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *linker = NULL, *tmp, *device = NULL;
+ struct uci_section *curr_section = NULL;
+ json_object *res;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ adm_entry_get_linker_value(ctx, value, &linker);
+ if (linker) {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", linker, String}}, 1, &res);
+ device = dmjson_get_value(res, 1, "device");
+ if (device) {
+ DOWNLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "downloaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "downloaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@downloaddiagnostic[0]", "interface", linker);
+ dmuci_set_varstate_value("cwmp", "@downloaddiagnostic[0]", "device", device);
+ }
+ dmfree(linker);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_DownloadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@downloaddiagnostic[0]", "url", value);
+ return 0;
+}
+
+int set_IPDiagnosticsDownloadDiagnostics_DownloadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ DOWNLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "downloaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "downloaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@downloaddiagnostic[0]", "url", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_DownloadTransports(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "HTTP,FTP";
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_DownloadDiagnosticMaxConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("DSCP", "0");
+ return 0;
+}
+
+int set_IPDiagnosticsDownloadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ DOWNLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "downloaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "downloaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@downloaddiagnostic[0]", "DSCP", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("ethernetpriority", "");
+ return 0;
+}
+
+int set_IPDiagnosticsDownloadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ DOWNLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "downloaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "downloaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@downloaddiagnostic[0]", "ethernetpriority", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("ProtocolVersion", "Any");
+ return 0;
+}
+
+int set_IPDiagnosticsDownloadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "IPv4") == 0 || strcmp(value, "IPv6") == 0) {
+ DOWNLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "downloaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "downloaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@downloaddiagnostic[0]", "ProtocolVersion", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("NumberOfConnections", "1");
+ return 0;
+}
+
+int set_IPDiagnosticsDownloadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "1") == 0) {
+ DOWNLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "downloaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "downloaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@downloaddiagnostic[0]", "NumberOfConnections", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("ROMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("BOMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("EOMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_TestBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TestBytesReceived", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TotalBytesReceived", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TotalBytesSent", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_TestBytesReceivedUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TestBytesReceived", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_TotalBytesReceivedUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TotalBytesReceived", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_TotalBytesSentUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TotalBytesSent", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_PeriodOfFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("PeriodOfFullLoading", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TCPOpenRequestTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TCPOpenResponseTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_PerConnectionResultNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+ bool b;
+ dmuci_get_varstate_string("cwmp", "@downloaddiagnostic[0]", "EnablePerConnection", &tmp);
+ string_to_bool(tmp, &b);
+ *value = (b) ? "1" : "0";
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("EnablePerConnection", "0");
+ return 0;
+}
+
+int set_IPDiagnosticsDownloadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ DOWNLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "downloaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "downloaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@downloaddiagnostic[0]", "EnablePerConnection", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("ROMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("BOMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("EOMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TestBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TestBytesReceived", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "TotalBytesReceived", value);
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "TotalBytesSent", value);
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TCPOpenRequestTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = download_get("TCPOpenResponseTime", "0");
+ return 0;
+}
+
+/*
+ * *** Device.IP.Diagnostics.UploadDiagnostics. ***
+ */
+
+static inline char *upload_get(char *option, char *def)
+{
+ char *tmp;
+ dmuci_get_varstate_string("cwmp", "@uploaddiagnostic[0]", option, &tmp);
+ if(tmp && tmp[0] == '\0')
+ return dmstrdup(def);
+ else
+ return tmp;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("DiagnosticState", "None");
+ return 0;
+}
+
+int set_IPDiagnosticsUploadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "Requested") == 0) {
+ UPLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "uploaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "uploaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@uploaddiagnostic[0]", "DiagnosticState", value);
+ cwmp_set_end_session(END_SESSION_UPLOAD_DIAGNOSTIC);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *linker;
+ dmuci_get_varstate_string("cwmp", "@uploaddiagnostic[0]", "interface", &linker);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value); // MEM WILL BE FREED IN DMMEMCLEAN
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+int set_IPDiagnosticsUploadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *linker = NULL, *tmp, *device= NULL;
+ struct uci_section *curr_section = NULL;
+ json_object *res;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ adm_entry_get_linker_value(ctx, value, &linker);
+ if (linker) {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", linker, String}}, 1, &res);
+ device = dmjson_get_value(res, 1, "device");
+ if (device) {
+ UPLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "uploaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "uploaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@uploaddiagnostic[0]", "interface", linker);
+ dmuci_set_varstate_value("cwmp", "@uploaddiagnostic[0]", "device", device);
+ }
+ dmfree(linker);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_UploadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@uploaddiagnostic[0]", "url", value);
+ return 0;
+}
+
+int set_IPDiagnosticsUploadDiagnostics_UploadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ UPLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "uploaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "uploaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@uploaddiagnostic[0]", "url", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_UploadTransports(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "HTTP,FTP";
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("DSCP", "0");
+ return 0;
+}
+
+int set_IPDiagnosticsUploadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ UPLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "uploaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "uploaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@uploaddiagnostic[0]", "DSCP", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("ethernetpriority", "0");
+ return 0;
+}
+
+int set_IPDiagnosticsUploadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ UPLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "uploaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "uploaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@uploaddiagnostic[0]", "ethernetpriority", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_TestFileLength(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TestFileLength", "0");
+ return 0;
+}
+
+int set_IPDiagnosticsUploadDiagnostics_TestFileLength(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ UPLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "uploaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "uploaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@uploaddiagnostic[0]", "TestFileLength", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("ProtocolVersion", "Any");
+ return 0;
+}
+
+int set_IPDiagnosticsUploadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "IPv4") == 0 || strcmp(value, "IPv6") == 0) {
+ UPLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "uploaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "uploaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@uploaddiagnostic[0]", "ProtocolVersion", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("NumberOfConnections", "1");
+ return 0;
+}
+
+int set_IPDiagnosticsUploadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "1") == 0) {
+ UPLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "uploaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "uploaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@uploaddiagnostic[0]", "NumberOfConnections", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("ROMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("BOMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("EOMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_TestBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TestBytesSent", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TotalBytesReceived", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TotalBytesSent", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_TestBytesSentUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TestBytesSent", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_TotalBytesReceivedUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TotalBytesReceived", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_TotalBytesSentUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TotalBytesSent", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_PeriodOfFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("PeriodOfFullLoading", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TCPOpenRequestTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TCPOpenResponseTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_PerConnectionResultNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+ bool b;
+ dmuci_get_varstate_string("cwmp", "@uploaddiagnostic[0]", "EnablePerConnection", &tmp);
+ string_to_bool(tmp, &b);
+ *value = (b) ? "1" : "0";
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("EnablePerConnection", "0");
+ return 0;
+}
+
+int set_IPDiagnosticsUploadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ UPLOAD_DIAGNOSTIC_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "uploaddiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "uploaddiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@uploaddiagnostic[0]", "EnablePerConnection", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("ROMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("BOMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("EOMtime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TestBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "TestBytesSent", value);
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "TotalBytesReceived", value);
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "TotalBytesSent", value);
+ return 0;
+
+}
+
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TCPOpenRequestTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = upload_get("TCPOpenResponseTime", "0");
+ return 0;
+}
+
+/*
+ * *** Device.IP.Diagnostics.UDPEchoConfig. ***
+ */
+
+int get_IPDiagnosticsUDPEchoConfig_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp_udpechoserver", "udpechoserver", "enable", value);
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoConfig_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ char file[32] = "/var/state/cwmp_udpechoserver";
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b) {
+ if( access( file, F_OK ) != -1 )
+ dmcmd("/bin/rm", 1, file);
+ dmuci_set_value("cwmp_udpechoserver", "udpechoserver", "enable", "1");
+ }
+ else
+ dmuci_set_value("cwmp_udpechoserver", "udpechoserver", "enable", "0");
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp_udpechoserver", "udpechoserver", "interface", value);
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoConfig_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp_udpechoserver", "udpechoserver", "interface", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_SourceIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp_udpechoserver", "udpechoserver", "address", value);
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoConfig_SourceIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp_udpechoserver", "udpechoserver", "address", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_UDPPort(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp_udpechoserver", "udpechoserver", "server_port", value);
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoConfig_UDPPort(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp_udpechoserver", "udpechoserver", "server_port", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_EchoPlusEnabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp_udpechoserver", "udpechoserver", "plus", value);
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoConfig_EchoPlusEnabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b)
+ dmuci_set_value("cwmp_udpechoserver", "udpechoserver", "plus", "1");
+ else
+ dmuci_set_value("cwmp_udpechoserver", "udpechoserver", "plus", "0");
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_EchoPlusSupported(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "true";
+ return 0;
+}
+
+static inline char *udpechoconfig_get(char *option, char *def)
+{
+ char *tmp;
+ dmuci_get_varstate_string("cwmp_udpechoserver", "udpechoserver", option, &tmp);
+ if(tmp && tmp[0] == '\0')
+ return dmstrdup(def);
+ else
+ return tmp;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechoconfig_get("PacketsReceived", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_PacketsResponded(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechoconfig_get("PacketsResponded", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_BytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechoconfig_get("BytesReceived", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_BytesResponded(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechoconfig_get("BytesResponded", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_TimeFirstPacketReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechoconfig_get("TimeFirstPacketReceived", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoConfig_TimeLastPacketReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechoconfig_get("TimeLastPacketReceived", "0");
+ return 0;
+}
+
+/*
+ * *** Device.IP.Diagnostics.UDPEchoDiagnostics. ***
+ */
+
+static inline char *udpechodiagnostics_get(char *option, char *def)
+{
+ char *tmp;
+ dmuci_get_varstate_string("cwmp", "@udpechodiagnostic[0]", option, &tmp);
+ if(tmp && tmp[0] == '\0')
+ return dmstrdup(def);
+ else
+ return tmp;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("DiagnosticState", "None");
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "Requested") == 0) {
+ UDPECHO_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "udpechodiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "udpechodiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@udpechodiagnostic[0]", "DiagnosticState", value);
+ cwmp_set_end_session(END_SESSION_UDPECHO_DIAGNOSTIC);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@udpechodiagnostic[0]", "Interface", value);
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ UDPECHO_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "udpechodiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "udpechodiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@udpechodiagnostic[0]", "Interface", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@udpechodiagnostic[0]", "Host", value);
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoDiagnostics_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ UDPECHO_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "udpechodiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "udpechodiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@udpechodiagnostic[0]", "Host", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@udpechodiagnostic[0]", "port", value);
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoDiagnostics_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (atoi(value) >= 1 && atoi(value) <= 65535) {
+ UDPECHO_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "udpechodiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "udpechodiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@udpechodiagnostic[0]", "port", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("NumberOfRepetitions", "1");
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ UDPECHO_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "udpechodiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "udpechodiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@udpechodiagnostic[0]", "NumberOfRepetitions", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("Timeout", "5000");
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ UDPECHO_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "udpechodiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "udpechodiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@udpechodiagnostic[0]", "Timeout", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("DataBlockSize", "24");
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoDiagnostics_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (atoi(value) >= 1 && atoi(value) <= 65535) {
+ UDPECHO_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "udpechodiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "udpechodiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@udpechodiagnostic[0]", "DataBlockSize", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("DSCP", "0");
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (atoi(value) >= 0 && atoi(value) <= 63) {
+ UDPECHO_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "udpechodiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "udpechodiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@udpechodiagnostic[0]", "DSCP", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_InterTransmissionTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("InterTransmissionTime", "1000");
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoDiagnostics_InterTransmissionTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (atoi(value) >= 1 && atoi(value) <= 65535) {
+ UDPECHO_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "udpechodiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "udpechodiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@udpechodiagnostic[0]", "InterTransmissionTime", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("ProtocolVersion", "Any");
+ return 0;
+}
+
+int set_IPDiagnosticsUDPEchoDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "IPv4") == 0 || strcmp(value, "IPv6") == 0) {
+ UDPECHO_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "udpechodiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "udpechodiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@udpechodiagnostic[0]", "ProtocolVersion", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_SuccessCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("SuccessCount", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_FailureCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("FailureCount", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_AverageResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("AverageResponseTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_MinimumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("MinimumResponseTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsUDPEchoDiagnostics_MaximumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = udpechodiagnostics_get("MaximumResponseTime", "0");
+ return 0;
+}
+
+/*
+ * *** Device.IP.Diagnostics.ServerSelectionDiagnostics. ***
+ */
+
+static inline char *serverselection_get(char *option, char *def)
+{
+ char *tmp;
+ dmuci_get_varstate_string("cwmp", "@serverselectiondiagnostic[0]", option, &tmp);
+ if(tmp && tmp[0] == '\0')
+ return dmstrdup(def);
+ else
+ return tmp;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = serverselection_get("DiagnosticState", "None");
+ return 0;
+}
+
+int set_IPDiagnosticsServerSelectionDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "Requested") == 0) {
+ SERVERSELECTION_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "serverselectiondiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "serverselectiondiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@serverselectiondiagnostic[0]", "DiagnosticState", value);
+ cwmp_set_end_session(END_SESSION_SERVERSELECTION_DIAGNOSTIC);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@serverselectiondiagnostic[0]", "interface", value);
+ return 0;
+}
+
+int set_IPDiagnosticsServerSelectionDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ SERVERSELECTION_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "serverselectiondiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "serverselectiondiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@serverselectiondiagnostic[0]", "interface", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = serverselection_get("ProtocolVersion", "Any");
+ return 0;
+}
+
+int set_IPDiagnosticsServerSelectionDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "IPv4") == 0 || strcmp(value, "IPv6") == 0) {
+ SERVERSELECTION_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "serverselectiondiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "serverselectiondiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@serverselectiondiagnostic[0]", "ProtocolVersion", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = serverselection_get("Protocol", "ICMP");
+ return 0;
+}
+
+int set_IPDiagnosticsServerSelectionDiagnostics_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "ICMP") == 0 || strcmp(value, "UDP Echo") == 0) {
+ SERVERSELECTION_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "serverselectiondiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "serverselectiondiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@serverselectiondiagnostic[0]", "Protocol", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@serverselectiondiagnostic[0]", "port", value);
+ return 0;
+}
+
+int set_IPDiagnosticsServerSelectionDiagnostics_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (atoi(value) >= 1 && atoi(value) <= 65535) {
+ SERVERSELECTION_STOP;
+ curr_section = dmuci_walk_state_section("cwmp", "serverselectiondiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "serverselectiondiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@serverselectiondiagnostic[0]", "port", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_HostList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@serverselectiondiagnostic[0]", "HostList", value);
+ return 0;
+}
+
+int set_IPDiagnosticsServerSelectionDiagnostics_HostList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ SERVERSELECTION_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "serverselectiondiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "serverselectiondiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@serverselectiondiagnostic[0]", "HostList", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = serverselection_get("NumberOfRepetitions", "3");
+ return 0;
+}
+
+int set_IPDiagnosticsServerSelectionDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (atoi(value) >= 1) {
+ SERVERSELECTION_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "serverselectiondiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "serverselectiondiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@serverselectiondiagnostic[0]", "NumberOfRepetitions", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = serverselection_get("Timeout", "1000");
+ return 0;
+}
+
+int set_IPDiagnosticsServerSelectionDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (atoi(value) >= 1) {
+ SERVERSELECTION_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "serverselectiondiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "serverselectiondiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@serverselectiondiagnostic[0]", "Timeout", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_FastestHost(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = serverselection_get("FastestHost", "");
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_MinimumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = serverselection_get("MinimumResponseTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_AverageResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = serverselection_get("AverageResponseTime", "0");
+ return 0;
+}
+
+int get_IPDiagnosticsServerSelectionDiagnostics_MaximumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = serverselection_get("MaximumResponseTime", "0");
+ return 0;
+}
+
+int browseIPDiagnosticsTraceRouteRouteHopsInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ char *instance, *idx_last = NULL;
+
+ uci_foreach_sections_state("cwmp", "RouteHops", s)
+ {
+ instance = handle_update_instance(2, dmctx, &idx_last, update_instance_alias, 3, (void *)s, "routehop_instance", "routehop_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, instance) == DM_STOP)
+ break;
+ }
+ return 0;
+}
+
+int browseIPDiagnosticsDownloadDiagnosticsPerConnectionResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ char *instance, *idx_last = NULL;
+
+ uci_foreach_sections_state("cwmp", "DownloadPerConnection", s)
+ {
+ instance = handle_update_instance(2, dmctx, &idx_last, update_instance_alias, 3, (void *)s, "perconnection_instance", "perconnection_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, instance) == DM_STOP)
+ break;
+ }
+ return 0;
+}
+
+int browseIPDiagnosticsUploadDiagnosticsPerConnectionResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ char *instance, *idx_last = NULL;
+
+ uci_foreach_sections_state("cwmp", "UploadPerConnection", s)
+ {
+ instance = handle_update_instance(2, dmctx, &idx_last, update_instance_alias, 3, (void *)s, "perconnection_instance", "perconnection_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, instance) == DM_STOP)
+ break;
+ }
+ return 0;
+}
diff --git a/dmtree/tr143/diagnostics.h b/dmtree/tr143/diagnostics.h
new file mode 100644
index 00000000..9d0b4f78
--- /dev/null
+++ b/dmtree/tr143/diagnostics.h
@@ -0,0 +1,232 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Amin Ben Ramdhane
+*
+*/
+
+#ifndef __DIAGNOSTICS_H
+#define __DIAGNOSTICS_H
+
+extern DMOBJ tIPDiagnosticsObj[];
+extern DMLEAF tIPDiagnosticsParams[];
+extern DMLEAF tIPDiagnosticsIPPingParams[];
+extern DMOBJ tIPDiagnosticsTraceRouteObj[];
+extern DMLEAF tIPDiagnosticsTraceRouteParams[];
+extern DMLEAF tIPDiagnosticsTraceRouteRouteHopsParams[];
+extern DMOBJ tIPDiagnosticsDownloadDiagnosticsObj[];
+extern DMLEAF tIPDiagnosticsDownloadDiagnosticsParams[];
+extern DMLEAF tIPDiagnosticsDownloadDiagnosticsPerConnectionResultParams[];
+extern DMOBJ tIPDiagnosticsUploadDiagnosticsObj[];
+extern DMLEAF tIPDiagnosticsUploadDiagnosticsParams[];
+extern DMLEAF tIPDiagnosticsUploadDiagnosticsPerConnectionResultParams[];
+extern DMLEAF tIPDiagnosticsUDPEchoConfigParams[];
+extern DMLEAF tIPDiagnosticsUDPEchoDiagnosticsParams[];
+extern DMLEAF tIPDiagnosticsServerSelectionDiagnosticsParams[];
+
+int browseIPDiagnosticsTraceRouteRouteHopsInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseIPDiagnosticsDownloadDiagnosticsPerConnectionResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseIPDiagnosticsUploadDiagnosticsPerConnectionResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int get_diag_enable_true(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_ping_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ip_ping_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ip_ping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ip_ping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ip_ping_protocolversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ip_ping_protocolversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ip_ping_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ip_ping_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ip_ping_repetition_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ip_ping_repetition_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ip_ping_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ip_ping_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ip_ping_block_size(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ip_ping_block_size(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ip_ping_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ip_ping_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ip_ping_success_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_ping_failure_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_ping_average_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_ping_min_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_ping_max_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_ping_AverageResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_ping_MinimumResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_ping_MaximumResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_IPDiagnosticsTraceRoute_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsTraceRoute_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsTraceRoute_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsTraceRoute_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsTraceRoute_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsTraceRoute_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsTraceRoute_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsTraceRoute_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsTraceRoute_NumberOfTries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsTraceRoute_NumberOfTries(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsTraceRoute_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsTraceRoute_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsTraceRoute_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsTraceRoute_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsTraceRoute_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsTraceRoute_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsTraceRoute_MaxHopCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsTraceRoute_MaxHopCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsTraceRoute_ResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsTraceRoute_RouteHopsNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsTraceRouteRouteHops_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsTraceRouteRouteHops_HostAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsTraceRouteRouteHops_ErrorCode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsTraceRouteRouteHops_RTTimes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_IPDiagnosticsDownloadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsDownloadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsDownloadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsDownloadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsDownloadDiagnostics_DownloadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsDownloadDiagnostics_DownloadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsDownloadDiagnostics_DownloadTransports(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_DownloadDiagnosticMaxConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsDownloadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsDownloadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsDownloadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsDownloadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsDownloadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsDownloadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsDownloadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsDownloadDiagnostics_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_TestBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_TestBytesReceivedUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_TotalBytesReceivedUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_TotalBytesSentUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_PeriodOfFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_PerConnectionResultNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsDownloadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TestBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_IPDiagnosticsUploadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUploadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUploadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUploadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUploadDiagnostics_UploadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUploadDiagnostics_UploadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUploadDiagnostics_UploadTransports(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUploadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUploadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUploadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUploadDiagnostics_TestFileLength(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUploadDiagnostics_TestFileLength(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUploadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUploadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUploadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUploadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUploadDiagnostics_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_TestBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_TestBytesSentUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_TotalBytesReceivedUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_TotalBytesSentUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_PeriodOfFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_PerConnectionResultNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUploadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TestBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_IPDiagnosticsUDPEchoConfig_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoConfig_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoConfig_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoConfig_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoConfig_SourceIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoConfig_SourceIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoConfig_UDPPort(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoConfig_UDPPort(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoConfig_EchoPlusEnabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoConfig_EchoPlusEnabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoConfig_EchoPlusSupported(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUDPEchoConfig_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUDPEchoConfig_PacketsResponded(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUDPEchoConfig_BytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUDPEchoConfig_BytesResponded(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUDPEchoConfig_TimeFirstPacketReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUDPEchoConfig_TimeLastPacketReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_IPDiagnosticsUDPEchoDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoDiagnostics_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoDiagnostics_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoDiagnostics_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoDiagnostics_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoDiagnostics_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoDiagnostics_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoDiagnostics_InterTransmissionTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoDiagnostics_InterTransmissionTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsUDPEchoDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsUDPEchoDiagnostics_SuccessCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUDPEchoDiagnostics_FailureCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUDPEchoDiagnostics_AverageResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUDPEchoDiagnostics_MinimumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsUDPEchoDiagnostics_MaximumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_IPDiagnosticsServerSelectionDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsServerSelectionDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsServerSelectionDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsServerSelectionDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsServerSelectionDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsServerSelectionDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsServerSelectionDiagnostics_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsServerSelectionDiagnostics_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsServerSelectionDiagnostics_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsServerSelectionDiagnostics_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsServerSelectionDiagnostics_HostList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsServerSelectionDiagnostics_HostList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsServerSelectionDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsServerSelectionDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsServerSelectionDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPDiagnosticsServerSelectionDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPDiagnosticsServerSelectionDiagnostics_FastestHost(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsServerSelectionDiagnostics_MinimumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsServerSelectionDiagnostics_AverageResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPDiagnosticsServerSelectionDiagnostics_MaximumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+#endif
\ No newline at end of file
diff --git a/dmtree/tr181/atm.c b/dmtree/tr181/atm.c
new file mode 100644
index 00000000..f4124041
--- /dev/null
+++ b/dmtree/tr181/atm.c
@@ -0,0 +1,375 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2016 PIVA SOFTWARE (www.pivasoftware.com)
+ * Author: Anis Ellouze
+ *
+ */
+
+#include
+#include
+#include "dmcwmp.h"
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcommon.h"
+#include "atm.h"
+#include "dmjson.h"
+#include "dmentry.h"
+
+/*** ATM. ***/
+DMOBJ tATMObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Link", &DMWRITE, add_atm_link, delete_atm_link, NULL, browseAtmLinkInst, NULL, NULL, tATMLinkObj, tATMLinkParams, get_atm_linker, BBFDM_BOTH},
+{0}
+};
+
+/*** ATM.Link. ***/
+DMOBJ tATMLinkObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Stats", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tATMLinkStatsParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tATMLinkParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_atm_alias, set_atm_alias, NULL, NULL, BBFDM_BOTH},
+{"Enable", &DMREAD, DMT_BOOL, get_atm_enable, NULL, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_atm_link_name, NULL, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_atm_enable, NULL, NULL, NULL, BBFDM_BOTH},
+{"LowerLayers", &DMREAD, DMT_STRING, get_atm_lower_layer, NULL, NULL, NULL, BBFDM_BOTH},
+{"LinkType", &DMWRITE, DMT_STRING, get_atm_link_type, set_atm_link_type, NULL, NULL, BBFDM_BOTH},
+{"DestinationAddress", &DMWRITE, DMT_STRING, get_atm_destination_address, set_atm_destination_address, NULL, NULL, BBFDM_BOTH},
+{"Encapsulation", &DMWRITE, DMT_STRING, get_atm_encapsulation, set_atm_encapsulation, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** ATM.Link.Stats. ***/
+DMLEAF tATMLinkStatsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"BytesSent", &DMREAD, DMT_UNINT, get_atm_stats_bytes_sent, NULL, NULL, NULL, BBFDM_BOTH},
+{"BytesReceived", &DMREAD, DMT_UNINT, get_atm_stats_bytes_received, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsSent", &DMREAD, DMT_UNINT, get_atm_stats_pack_sent, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsReceived", &DMREAD, DMT_UNINT, get_atm_stats_pack_received, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/**************************************************************************
+* LINKER
+***************************************************************************/
+int get_atm_linker(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker) {
+ if (data && ((struct atm_args *)data)->ifname) {
+ *linker = ((struct atm_args *)data)->ifname;
+ return 0;
+ }
+ *linker = "" ;
+ return 0;
+}
+
+/**************************************************************************
+* INIT
+***************************************************************************/
+inline int init_atm_link(struct atm_args *args, struct uci_section *s, char *ifname)
+{
+ args->atm_sec = s;
+ args->ifname = ifname;
+ return 0;
+}
+
+/**************************************************************************
+* SET & GET DSL LINK PARAMETERS
+***************************************************************************/
+/*#Device.ATM.Link.{i}.DestinationAddress!UCI:dsl/atm-device,@i-1/vpi*/
+int get_atm_destination_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *vpi, *vci;
+
+ dmuci_get_value_by_section_string(((struct atm_args *)data)->atm_sec, "vpi", &vpi);
+ dmuci_get_value_by_section_string(((struct atm_args *)data)->atm_sec, "vci", &vci);
+ dmasprintf(value, "PVC: %s/%s", vpi, vci); // MEM WILL BE FREED IN DMMEMCLEAN
+ return 0;
+}
+
+int set_atm_destination_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *vpi = NULL, *vci = NULL, *spch, *val;
+ struct uci_section *s;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strstr(value, "PVC: "))
+ value += 5;
+ else
+ return 0;
+ val = dmstrdup(value);
+ vpi = strtok_r(val, "/", &spch);
+ if (vpi) {
+ vci = strtok_r(NULL, "/", &spch);
+ }
+ if (vpi && vci) {
+ dmuci_set_value_by_section(((struct atm_args *)data)->atm_sec, "vpi", vpi);
+ dmuci_set_value_by_section(((struct atm_args *)data)->atm_sec, "vci", vci);
+ }
+ dmfree(val);
+ break;
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ATM.Link.{i}.Name!UCI:dsl/atm-device,@i-1/name*/
+int get_atm_link_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct atm_args *)data)->atm_sec, "name", value);
+ return 0;
+}
+
+/*#Device.ATM.Link.{i}.Encapsulation!UCI:dsl/atm-device,@i-1/encapsulation*/
+int get_atm_encapsulation(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *encapsulation;
+
+ dmuci_get_value_by_section_string(((struct atm_args *)data)->atm_sec, "encapsulation", &encapsulation);
+ if (strcasecmp(encapsulation, "vcmux") == 0) {
+ *value = "VCMUX";
+ }
+ else if (strcasecmp(encapsulation, "llc") == 0) {
+ *value = "LLC";
+ } else {
+ *value = "";
+ }
+ return 0;
+}
+
+int set_atm_encapsulation(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *encapsulation;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "VCMUX") == 0)
+ encapsulation = "vcmux";
+ else if (strcmp(value, "LLC") == 0)
+ encapsulation = "llc";
+ else
+ return 0;
+
+ dmuci_set_value_by_section(((struct atm_args *)data)->atm_sec, "encapsulation", encapsulation);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ATM.Link.{i}.LinkType!UCI:dsl/atm-device,@i-1/link_type*/
+int get_atm_link_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "";
+ dmuci_get_value_by_section_string(((struct atm_args *)data)->atm_sec, "link_type", value);
+ return 0;
+}
+
+int set_atm_link_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(((struct atm_args *)data)->atm_sec, "link_type", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_atm_lower_layer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char linker[16];
+ sprintf(linker, "channel_%d", atoi(instance)-1);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cDSL%cChannel%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value); // MEM WILL BE FREED IN DMMEMCLEAN
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+inline int ubus_atm_stats(json_object *res, char **value, char *stat_mod, void *data)
+{
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct atm_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 2, "statistics", stat_mod);
+ return 0;
+}
+
+/*#Device.ATM.Link.{i}.Stats.BytesReceived!UBUS:network.device/status/name,@Name/statistics.rx_bytes*/
+int get_atm_stats_bytes_received(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ ubus_atm_stats(res, value, "rx_bytes", data);
+ return 0;
+}
+
+/*#Device.ATM.Link.{i}.Stats.BytesSent!UBUS:network.device/status/name,@Name/statistics.tx_bytes*/
+int get_atm_stats_bytes_sent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ ubus_atm_stats(res, value, "tx_bytes", data);
+ return 0;
+}
+
+/*#Device.ATM.Link.{i}.Stats.PacketsReceived!UBUS:network.device/status/name,@Name/statistics.rx_packets*/
+int get_atm_stats_pack_received(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ ubus_atm_stats(res, value, "rx_packets", data);
+ return 0;
+}
+
+/*#Device.ATM.Link.{i}.Stats.PacketsSent!UBUS:network.device/status/name,@Name/statistics.tx_packets*/
+int get_atm_stats_pack_sent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ ubus_atm_stats(res, value, "tx_packets", data);
+ return 0;
+}
+
+int get_atm_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "true";
+ return 0;
+}
+
+/*************************************************************
+ * ADD OBJ
+/*************************************************************/
+int add_atm_link(char *refparam, struct dmctx *ctx, void *data, char **instancepara)
+{
+ char *instance = NULL, *atm_device = NULL, *v = NULL, *instance_update = NULL;
+ struct uci_section *dmmap_atm = NULL;
+
+ check_create_dmmap_package("dmmap_dsl");
+ instance = get_last_instance_icwmpd("dmmap_dsl", "atm-device", "atmlinkinstance");
+ dmasprintf(&atm_device, "atm%d", instance ? atoi(instance) : 0);
+ dmasprintf(&instance_update, "%d", instance ? atoi(instance)+ 1 : 1);
+ dmuci_set_value("dsl", atm_device, "", "atm-device");
+ dmuci_set_value("dsl", atm_device, "name", "ATM");
+ dmuci_set_value("dsl", atm_device, "vpi", "8");
+ dmuci_set_value("dsl", atm_device, "vci", "35");
+ dmuci_set_value("dsl", atm_device, "device", atm_device);
+ dmuci_set_value("dsl", atm_device, "link_type", "eoa");
+ dmuci_set_value("dsl", atm_device, "encapsulation", "llc");
+ dmuci_set_value("dsl", atm_device, "qos_class", "ubr");
+ dmuci_add_section_icwmpd("dmmap_dsl", "atm-device", &dmmap_atm, &v);
+ dmuci_set_value_by_section(dmmap_atm, "section_name", atm_device);
+ *instancepara = update_instance_icwmpd(dmmap_atm, instance, "atmlinkinstance");
+ return 0;
+}
+
+int delete_atm_link(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *s = NULL, *ss = NULL, *ns = NULL, *nss = NULL, *dmmap_section= NULL;
+ char *ifname;
+
+ switch (del_action) {
+ case DEL_INST:
+ get_dmmap_section_of_config_section("dmmap_dsl", "atm-device", section_name(((struct atm_args *)data)->atm_sec), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(((struct atm_args *)data)->atm_sec, NULL, NULL);
+ uci_foreach_option_cont("network", "interface", "ifname", ((struct atm_args *)data)->ifname, s) {
+ if (ss && ifname!=NULL)
+ wan_remove_dev_interface(ss, ((struct atm_args *)data)->ifname);
+ ss = s;
+ }
+ if (ss != NULL && ifname!=NULL)
+ wan_remove_dev_interface(ss, ((struct atm_args *)data)->ifname);
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("dsl", "atm-device", s) {
+ if (ss){
+ get_dmmap_section_of_config_section("dmmap_dsl", "atm-device", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_get_value_by_section_string(ss, "device", &ifname);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ uci_foreach_option_cont("network", "interface", "ifname", ifname, ns) {
+ if (nss && ifname!=NULL)
+ wan_remove_dev_interface(nss, ifname);
+ nss = ns;
+ }
+ if (nss != NULL && ifname!=NULL)
+ wan_remove_dev_interface(nss, ifname);
+ }
+ ss = s;
+ }
+ if (ss != NULL) {
+ get_dmmap_section_of_config_section("dmmap_dsl", "atm-device", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_get_value_by_section_string(ss, "device", &ifname);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ uci_foreach_option_cont("network", "interface", "ifname", ifname, ns) {
+ if (nss && ifname!=NULL)
+ wan_remove_dev_interface(nss, ifname);
+ nss = ns;
+ }
+ if (nss != NULL && ifname!=NULL)
+ wan_remove_dev_interface(nss, ifname);
+ }
+ break;
+ }
+ return 0;
+}
+
+/*************************************************************
+ * SET AND GET ALIAS
+/*************************************************************/
+int get_atm_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_dsl", "atm-device", section_name(((struct atm_args *)data)->atm_sec), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "atmlinkalias", value);
+ return 0;
+}
+
+int set_atm_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ get_dmmap_section_of_config_section("dmmap_dsl", "atm-device", section_name(((struct atm_args *)data)->atm_sec), &dmmap_section);
+ dmuci_set_value_by_section(dmmap_section, "atmlinkalias", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*************************************************************
+ * ENTRY METHOD
+/*************************************************************/
+/*#Device.ATM.Link.{i}.!UCI:dsl/atm-device/dmmap_dsl*/
+int browseAtmLinkInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *wnum = NULL, *channel_last = NULL, *ifname;
+ struct atm_args curr_atm_args = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap("dsl", "atm-device", "dmmap_dsl", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ dmuci_get_value_by_section_string(p->config_section, "device", &ifname);
+ init_atm_link(&curr_atm_args, p->config_section, ifname);
+ wnum = handle_update_instance(1, dmctx, &channel_last, update_instance_alias, 3, p->dmmap_section, "atmlinkinstance", "atmlinkalias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_atm_args, wnum) == DM_STOP)
+ break;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
diff --git a/dmtree/tr181/atm.h b/dmtree/tr181/atm.h
new file mode 100644
index 00000000..0f5cee2e
--- /dev/null
+++ b/dmtree/tr181/atm.h
@@ -0,0 +1,50 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2016 Inteno Broadband Technology AB
+ * Author: Anis Ellouze
+ *
+ */
+
+#ifndef __ATM_H
+#define __ATM_H
+
+struct atm_args
+{
+ struct uci_section *atm_sec;
+ char *ifname;
+};
+
+extern DMOBJ tATMObj[];
+extern DMOBJ tATMLinkObj[];
+extern DMLEAF tATMLinkParams[];
+extern DMLEAF tATMLinkStatsParams[] ;
+
+int browseAtmLinkInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int add_atm_link(char *refparam, struct dmctx *ctx, void *data, char **instancepara);
+int delete_atm_link(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+
+int get_atm_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_atm_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_atm_link_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_atm_lower_layer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_atm_link_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_atm_destination_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_atm_encapsulation(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_atm_stats_bytes_sent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_atm_stats_bytes_received(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_atm_stats_pack_sent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_atm_stats_pack_received(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int set_atm_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_atm_link_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_atm_destination_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_atm_encapsulation(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int get_atm_linker(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+
+#endif
diff --git a/dmtree/tr181/bridging.c b/dmtree/tr181/bridging.c
new file mode 100644
index 00000000..842416ce
--- /dev/null
+++ b/dmtree/tr181/bridging.c
@@ -0,0 +1,1848 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB
+ * Author: Anis Ellouze
+ * Author: Amin Ben Ramdhane
+ *
+ */
+
+#include
+#include
+#include "dmcwmp.h"
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcommon.h"
+#include "bridging.h"
+#include "dmjson.h"
+#include "dmentry.h"
+
+static char *wan_baseifname = NULL;
+
+/*** Bridging. ***/
+DMOBJ tBridgingObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Bridge", &DMWRITE, add_bridge, delete_bridge, NULL, browseBridgeInst, NULL, NULL, tBridgingBridgeObj, tBridgingBridgeParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tBridgingParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"MaxBridgeEntries", &DMREAD, DMT_UNINT, get_Max_Bridge_Entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"MaxDBridgeEntries", &DMREAD, DMT_UNINT, get_Max_DBridge_Entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"MaxQBridgeEntries", &DMREAD, DMT_UNINT, get_Max_QBridge_Entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"MaxVLANEntries", &DMREAD, DMT_UNINT, get_Max_VLAN_Entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"MaxProviderBridgeEntries", &DMREAD, DMT_UNINT, get_Max_Provider_Bridge_Entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"MaxFilterEntries", &DMREAD, DMT_UNINT, get_Max_Filter_Entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"BridgeNumberOfEntries", &DMREAD, DMT_UNINT, get_Bridge_Number_Of_Entries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** Bridging.Bridge.{i}. ***/
+DMOBJ tBridgingBridgeObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Port", &DMWRITE, add_br_port, delete_br_port, NULL, browseBridgePortInst, NULL, NULL, tBridgingBridgePortObj, tBridgingBridgePortParams, get_linker_br_port, BBFDM_BOTH},
+{"VLAN", &DMWRITE, add_br_vlan, delete_br_vlan, NULL, browseBridgeVlanInst, NULL, NULL, NULL, tBridgingBridgeVLANParams, get_linker_br_vlan, BBFDM_BOTH},
+{"VLANPort", &DMREAD, NULL, NULL, NULL, browseBridgeVlanPortInst, NULL, NULL, NULL, tBridgingBridgeVLANPortParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tBridgingBridgeParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_br_enable, set_br_enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_br_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_br_alias, set_br_alias, NULL, NULL, BBFDM_BOTH},
+{"Standard", &DMWRITE, DMT_STRING, get_br_standard, set_br_standard, NULL, NULL, BBFDM_BOTH},
+{"PortNumberOfEntries", &DMREAD, DMT_UNINT, get_br_port_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"VLANNumberOfEntries", &DMREAD, DMT_UNINT, get_br_vlan_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"VLANPortNumberOfEntries", &DMREAD, DMT_UNINT, get_br_vlan_port_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"AssociatedInterfaces", &DMWRITE, DMT_STRING, get_br_associated_interfaces, set_br_associated_interfaces, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** Bridging.Bridge.{i}.Port.{i}. ***/
+DMOBJ tBridgingBridgePortObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Stats", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tBridgingBridgePortStatsParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tBridgingBridgePortParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_br_port_enable, set_br_port_enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_br_port_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_br_port_alias, set_br_port_alias, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_br_port_name, NULL, NULL, NULL, BBFDM_BOTH},
+{"LastChange", &DMREAD, DMT_UNINT, get_br_port_last_change, NULL, NULL, NULL, BBFDM_BOTH},
+{"LowerLayers", &DMWRITE, DMT_STRING, get_port_lower_layer, set_port_lower_layer, NULL, NULL, BBFDM_BOTH},
+{"ManagementPort", &DMWRITE, DMT_STRING, get_br_port_management, set_br_port_management, NULL, NULL, BBFDM_BOTH},
+{"Type", &DMWRITE, DMT_STRING, get_br_port_type, set_br_port_type, NULL, NULL, BBFDM_BOTH},
+{"DefaultUserPriority", &DMWRITE, DMT_UNINT, get_br_port_default_user_priority, set_br_port_default_user_priority, NULL, NULL, BBFDM_BOTH},
+{"PriorityRegeneration", &DMWRITE, DMT_STRING, get_br_port_priority_regeneration, set_br_port_priority_regeneration, NULL, NULL, BBFDM_BOTH},
+{"PortState", &DMREAD, DMT_STRING, get_br_port_port_state, NULL, NULL, NULL, BBFDM_BOTH},
+{"PVID", &DMWRITE, DMT_INT, get_br_port_pvid, set_br_port_pvid, NULL, NULL, BBFDM_BOTH},
+{"TPID", &DMWRITE, DMT_UNINT, get_br_port_tpid, set_br_port_tpid, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** Bridging.Bridge.{i}.Port.{i}.Stats. ***/
+DMLEAF tBridgingBridgePortStatsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"BytesSent", &DMREAD, DMT_UNINT, get_br_port_stats_tx_bytes, NULL, NULL, NULL, BBFDM_BOTH},
+{"BytesReceived", &DMREAD, DMT_UNINT, get_br_port_stats_rx_bytes, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsSent", &DMREAD, DMT_UNINT, get_br_port_stats_tx_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsReceived", &DMREAD, DMT_UNINT, get_br_port_stats_rx_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"ErrorsSent", &DMREAD, DMT_UNINT, get_br_port_stats_tx_errors, NULL, NULL, NULL, BBFDM_BOTH},
+{"ErrorsReceived", &DMREAD, DMT_UNINT, get_br_port_stats_rx_errors, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnicastPacketsSent", &DMREAD, DMT_UNINT, get_br_port_stats_tx_unicast_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnicastPacketsReceived", &DMREAD, DMT_UNINT, get_br_port_stats_rx_unicast_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"DiscardPacketsSent", &DMREAD, DMT_UNINT, get_br_port_stats_tx_discard_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"DiscardPacketsReceived", &DMREAD, DMT_UNINT, get_br_port_stats_rx_discard_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"MulticastPacketsSent", &DMREAD, DMT_UNINT, get_br_port_stats_tx_multicast_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"MulticastPacketsReceived", &DMREAD, DMT_UNINT, get_br_port_stats_rx_multicast_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"BroadcastPacketsSent", &DMREAD, DMT_UNINT, get_br_port_stats_tx_broadcast_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"BroadcastPacketsReceived", &DMREAD, DMT_UNINT, get_br_port_stats_rx_broadcast_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnknownProtoPacketsReceived", &DMREAD, DMT_UNINT, get_br_port_stats_rx_unknown_proto_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** Bridging.Bridge.{i}.VLAN.{i}. ***/
+DMLEAF tBridgingBridgeVLANParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_br_vlan_enable, set_br_vlan_enable, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING,get_br_vlan_alias, set_br_vlan_alias, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMWRITE, DMT_STRING, get_br_vlan_name, set_br_vlan_name, NULL, NULL, BBFDM_BOTH},
+{"VLANID", &DMWRITE, DMT_STRING, get_br_vlan_vid, set_br_vlan_vid, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"VLANPriority", &DMWRITE, DMT_STRING, get_br_vlan_priority, set_br_vlan_priority, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** Bridging.Bridge.{i}.VLANPort.{i}. ***/
+DMLEAF tBridgingBridgeVLANPortParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_br_vlan_enable, set_br_vlan_enable, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_br_vlan_alias, set_br_vlan_alias, NULL, NULL, BBFDM_BOTH},
+{"VLAN", &DMWRITE, DMT_STRING, get_vlan_port_vlan_ref, set_vlan_port_vlan_ref, NULL, NULL, BBFDM_BOTH},
+{"Port", &DMWRITE, DMT_STRING, get_vlan_port_port_ref, set_vlan_port_port_ref, NULL, NULL, BBFDM_BOTH},
+{"Untagged", &DMWRITE, DMT_BOOL, get_br_vlan_untagged, set_br_vlan_untagged, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/**************************************************************************
+* LINKER
+***************************************************************************/
+int get_linker_br_port(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker) {
+ if(data && ((struct bridging_port_args *)data)->bridge_port_sec) {
+ dmasprintf(linker,"%s+%s", section_name(((struct bridging_port_args *)data)->bridge_port_sec), ((struct bridging_port_args *)data)->ifname);
+ return 0;
+ }
+ *linker = "";
+ return 0;
+}
+
+int get_linker_br_vlan(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker) {
+ if(data && ((struct bridging_vlan_args *)data)->vlan_port) {
+ dmasprintf(linker,"vlan%s_%s", ((struct bridging_vlan_args *)data)->vlan_port, ((struct bridging_vlan_args *)data)->br_inst);
+ return 0;
+ }
+ *linker = "";
+ return 0;
+}
+/**************************************************************************
+* INIT
+***************************************************************************/
+inline int init_bridging_args(struct bridging_args *args, struct uci_section *s, char *last_instance, char *ifname, char *br_instance)
+{
+ args->bridge_sec = s;
+ args->br_key = last_instance;
+ args->ifname = ifname;
+ args->br_inst = br_instance;
+ return 0;
+}
+
+inline int init_bridging_port_args(struct bridging_port_args *args, struct uci_section *s, struct uci_section *bs, bool vlan, char *ifname)
+{
+ args->bridge_port_sec = s;
+ args->bridge_sec = bs;
+ args->vlan = vlan;
+ args->ifname = ifname;
+ return 0;
+}
+
+inline int init_bridging_vlan_args(struct bridging_vlan_args *args, struct uci_section *s, struct uci_section *bs, char *vlan_port, char *br_inst)
+{
+ args->bridge_vlan_sec = s;
+ args->bridge_sec = bs;
+ args->vlan_port = vlan_port;
+ args->br_inst = br_inst;
+ return 0;
+}
+
+/**************************************************************************
+* INSTANCE MG
+***************************************************************************/
+char *get_last_vid(void)
+{
+ struct uci_section *vlan_s;
+ char *vid = NULL, *type;
+ int num_vid = 0;
+
+ uci_foreach_sections("network", "device", vlan_s) {
+ if(!vlan_s)
+ break;
+ dmuci_get_value_by_section_string(vlan_s, "type", &type);
+ if (strcmp(type, "untagged")==0)
+ continue;
+ dmuci_get_value_by_section_string(vlan_s, "vid", &vid);
+ if( atoi(vid)> num_vid )
+ num_vid = atoi(vid);
+ dmasprintf(&vid, "%d", num_vid);
+ }
+ return vid;
+}
+
+int check_ifname_exist_in_br_ifname_list(char *ifname)
+{
+ char *br_ifname_list, *br_ifname_dup, *pch, *spch;
+ struct uci_section *s;
+ uci_foreach_option_eq("network", "interface", "type", "bridge", s) {
+ dmuci_get_value_by_section_string(s, "ifname", &br_ifname_list);
+ if(br_ifname_list[0] == '\0')
+ return 0;
+ br_ifname_dup = dmstrdup(br_ifname_list);
+ for (pch = strtok_r(br_ifname_dup, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) {
+ if (strcmp(pch, ifname) == 0)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int get_br_port_last_inst(char *br_key)
+{
+ char *tmp;
+ int max=1;
+ struct uci_section *s;
+ int instance;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_bridge_port", "bridge_port", "bridge_key", br_key, s) {
+ dmuci_get_value_by_section_string(s, "bridge_port_instance", &tmp);
+ if (tmp[0] == '\0')
+ continue;
+ instance = atoi(tmp);
+ if(instance>max) max=instance;
+ }
+ return max;
+}
+
+int reset_br_port(char *br_key)
+{
+ struct uci_section *s, *prev_s = NULL;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_bridge_port", "bridge_port", "bridge_key", br_key, s){
+ if (prev_s)
+ dmuci_delete_by_section(prev_s, NULL, NULL);
+ prev_s = s;
+ }
+
+ if (prev_s)
+ dmuci_delete_by_section(prev_s, NULL, NULL);
+ return 0;
+}
+
+int check_ifname_is_not_lan_port(char *ifname)
+{
+ struct uci_section *s;
+ if (!strstr(ifname, wan_baseifname)) {
+ uci_foreach_option_eq("ports", "ethport", "ifname", ifname, s) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int update_port_parameters(char *linker, char *br_key, char *br_pt_inst, char *mg_port)
+{
+ struct uci_section *s, *dmmap_section;
+ if (check_ifname_is_vlan(linker)) {
+ uci_foreach_option_eq("network", "device", "ifname", linker, s) {
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(s), &dmmap_section);
+ dmuci_set_value_by_section(dmmap_section, "bridge_key", br_key);
+ dmuci_set_value_by_section(dmmap_section, "bridge_port_instance", br_pt_inst);
+ dmuci_set_value_by_section(dmmap_section, "mg_port", mg_port);
+ break;
+ }
+ } else if (strncmp(linker, "ptm", 3) == 0) {
+ uci_foreach_option_eq("dsl", "ptm-device", "device", linker, s) {
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(s), &dmmap_section);
+ dmuci_set_value_by_section(dmmap_section, "bridge_key", br_key);
+ dmuci_set_value_by_section(dmmap_section, "bridge_port_instance", br_pt_inst);
+ dmuci_set_value_by_section(dmmap_section, "mg_port", mg_port);
+ break;
+ }
+ } else if (strncmp(linker, "atm", 3) == 0) {
+ uci_foreach_option_eq("dsl", "atm-device", "device", linker, s) {
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(s), &dmmap_section);
+ dmuci_set_value_by_section(dmmap_section, "bridge_key", br_key);
+ dmuci_set_value_by_section(dmmap_section, "bridge_port_instance", br_pt_inst);
+ dmuci_set_value_by_section(dmmap_section, "mg_port", mg_port);
+ break;
+ }
+ } else if (strncmp(linker, "wl", 2) == 0) {
+ uci_foreach_option_eq("wireless", "wifi-iface", "ifname", linker, s) {
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(s), &dmmap_section);
+ dmuci_set_value_by_section(dmmap_section, "bridge_key", br_key);
+ dmuci_set_value_by_section(dmmap_section, "bridge_port_instance", br_pt_inst);
+ dmuci_set_value_by_section(dmmap_section, "mg_port", mg_port);
+ break;
+ }
+ } else if (strncmp(linker, "eth0", 4) == 0) {
+ uci_foreach_option_eq("network", "device", "name", linker, s) {
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(s), &dmmap_section);
+ dmuci_set_value_by_section(dmmap_section, "bridge_key", br_key);
+ dmuci_set_value_by_section(dmmap_section, "bridge_port_instance", br_pt_inst);
+ dmuci_set_value_by_section(dmmap_section, "mg_port", mg_port);
+ break;
+ }
+ } else {
+ uci_foreach_option_eq("ports", "ethport", "ifname", linker, s) {
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(s), &dmmap_section);
+ dmuci_set_value_by_section(dmmap_section, "bridge_key", br_key);
+ dmuci_set_value_by_section(dmmap_section, "bridge_port_instance", br_pt_inst);
+ dmuci_set_value_by_section(dmmap_section, "mg_port", mg_port);
+ break;
+ }
+ }
+ return 0;
+}
+
+static int is_br_port_enabled(struct bridging_port_args *curr_arg)
+{
+ struct uci_section *vlan_sec = curr_arg->bridge_port_sec, *br_sec = curr_arg->bridge_sec;
+ char *ifname, *br_ifname, *ifname_dup;
+
+ dmuci_get_value_by_section_string(br_sec, "ifname", &br_ifname);
+ dmuci_get_value_by_section_string(vlan_sec, "name", &ifname);
+ ifname_dup = dmstrdup(br_ifname);
+ if(ifname != NULL && ifname[0] != '\0') {
+ if (is_strword_in_optionvalue(ifname_dup, ifname))
+ return 1;
+ }
+ return 0;
+}
+
+static int update_br_port_ifname(struct bridging_port_args *curr_arg, int status)
+{
+ char ifname_dup[128], *ptr, *baseifname, *ifname, *start, *end;
+ struct uci_section *vlan_sec = curr_arg->bridge_port_sec, *br_sec = curr_arg->bridge_sec;
+ int pos=0;
+ dmuci_get_value_by_section_string(br_sec, "ifname", &ifname);
+ dmuci_get_value_by_section_string(vlan_sec, "name", &baseifname);
+ ptr = ifname_dup;
+ dmstrappendstr(ptr, ifname);
+ dmstrappendend(ptr);
+ if(status){
+ if (is_strword_in_optionvalue(ifname_dup, baseifname)) return 0;
+ if (ifname_dup[0] != '\0') dmstrappendchr(ptr, ' ');
+ dmstrappendstr(ptr, baseifname);
+ dmstrappendend(ptr);
+ }else{
+ if (is_strword_in_optionvalue(ifname_dup, baseifname)){
+ start = strstr(ifname_dup, baseifname);
+ end = start + strlen(baseifname);
+ if(start != ifname_dup){
+ start--;
+ pos=1;
+ }
+ memmove(start, start + strlen(baseifname)+pos, strlen(end) + 1);
+ }
+ }
+ dmuci_set_value_by_section(br_sec, "ifname", ifname_dup);
+ return 0;
+}
+
+/**************************************************************************
+*SET & GET BRIDGING PARAMETERS
+***************************************************************************/
+int get_Max_Bridge_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "20";
+ return 0;
+}
+
+int get_Max_DBridge_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "20";
+ return 0;
+}
+
+int get_Max_QBridge_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "20";
+ return 0;
+}
+
+int get_Max_VLAN_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "20";
+ return 0;
+}
+
+int get_Max_Provider_Bridge_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ return 0;
+}
+
+int get_Max_Filter_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ return 0;
+}
+
+/*#Device.Bridging.BridgeNumberOfEntries!UCI:network/interface/*/
+int get_Bridge_Number_Of_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_foreach_option_eq("network", "interface", "type", "bridge", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Enable!UBUS:network.interface/status/interface,@Name/up*/
+int get_br_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(((struct bridging_args *)data)->bridge_sec), String}}, 1, &res);
+ DM_ASSERT(res, *value = "false");
+ *value = dmjson_get_value(res, 1, "up");
+ return 0;
+}
+
+int set_br_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ dmubus_call_set("network.interface", b ? "up" : "down", UBUS_ARGS{{"interface", section_name(((struct bridging_args *)data)->bridge_sec), String}}, 1);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Status!UBUS:network.interface/status/interface,@Name/up*/
+int get_br_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(((struct bridging_args *)data)->bridge_sec), String}}, 1, &res);
+ DM_ASSERT(res, *value = "Disabled");
+ *value = dmjson_get_value(res, 1, "up");
+ if(strcmp(*value, "true") == 0)
+ *value = "Enabled";
+ else
+ *value = "Disabled";
+ return 0;
+}
+
+int get_br_standard(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "802.1Q-2011";
+ return 0;
+}
+
+int set_br_standard(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_port_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_bridge_port", "bridge_port", "bridge_key", instance, s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+int get_br_vlan_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "device", "bridge_key", instance, s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+int get_br_vlan_port_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "device", "bridge_key", instance, s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+int get_br_associated_interfaces(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct bridging_args *)data)->bridge_sec, "ifname", value);
+ return 0;
+}
+
+int set_br_associated_interfaces(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(((struct bridging_args *)data)->bridge_sec, "ifname", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Enable!UBUS:network.device/status/name,@Name/speed*/
+int get_br_port_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ char *speed, *val;
+ struct uci_section *wifi_device_s;
+
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "ifname", value);
+ if(strncmp(*value, "wl", 2) == 0 || strncmp(*value, "ra", 2) == 0 || strncmp(*value, "apclii", 6) == 0) {
+ uci_foreach_option_eq("wireless", "wifi-iface", "ifname", *value, wifi_device_s) {
+ dmuci_get_value_by_section_string(wifi_device_s, "disabled", &val);
+ if ((val[0] == '\0') || (val[0] == '0'))
+ *value = "true";
+ else
+ *value = "false";
+ return 0;
+ }
+ }
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", *value, String}}, 1, &res);
+ DM_ASSERT(res, *value = "false");
+ speed = dmjson_get_value(res, 1, "speed");
+ if(*speed != '\0')
+ *value = "true";
+ else
+ *value = "false";
+ return 0;
+}
+
+int set_br_port_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Status!UBUS:network.device/status/name,@Name/speed*/
+int get_br_port_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ bool b;
+ get_br_port_enable(refparam, ctx, data, instance, value);
+ string_to_bool(*value, &b);
+ if (b)
+ *value = "Up";
+ else
+ *value = "Down";
+ return 0;
+}
+
+int get_br_port_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "name", value);
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.LastChange!UBUS:network.interface/status/interface,@Name/uptime*/
+int get_br_port_last_change(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(((struct bridging_port_args *)data)->bridge_sec), String}}, 1, &res);
+ DM_ASSERT(res, *value = "0");
+ *value = dmjson_get_value(res, 1, "uptime");
+ if((*value)[0] == '\0')
+ *value = "0";
+ return 0;
+}
+
+int get_br_port_management(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section= NULL;
+
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(((struct bridging_port_args *)data)->bridge_port_sec), &dmmap_section);
+ if(dmmap_section==NULL || dmmap_section==0)
+ dmmap_section= ((struct bridging_port_args *)data)->bridge_port_sec;
+ dmuci_get_value_by_section_string(dmmap_section, "mg_port", value);
+ return 0;
+}
+
+int set_br_port_management(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ return 0;
+ }
+ return 0;
+}
+
+static struct uci_section *check_if_ifname_is_tagged(char *ifname)
+{
+ struct uci_section *s;
+ uci_foreach_option_eq("network", "device", "name", ifname, s) {
+ return s;
+ }
+ return NULL;
+}
+
+int get_br_port_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *name;
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "name", &name);
+ if(check_if_ifname_is_tagged(name) != NULL)
+ *value = "CustomerVLANPort";
+ else
+ *value = "";
+ return 0;
+}
+
+int set_br_port_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_port_default_user_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ char *name, *type, *priority;
+
+ *value = "";
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "name", &name);
+ s = check_if_ifname_is_tagged(name);
+ if(s != NULL) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if(strcmp(type, "untagged") != 0)
+ dmuci_get_value_by_section_string(s, "priority", value);
+ }
+ return 0;
+}
+
+int set_br_port_default_user_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *s = NULL;
+ char *name, *type, *priority;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "name", &name);
+ s = check_if_ifname_is_tagged(name);
+ if(s != NULL) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if(strcmp(type, "untagged") != 0)
+ dmuci_set_value_by_section(s, "priority", value);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_port_priority_regeneration(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0,1,2,3,4,5,6,7";
+ return 0;
+}
+
+int set_br_port_priority_regeneration(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_port_port_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *name;
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "name", &name);
+ if(check_if_ifname_is_tagged(name) != NULL)
+ *value = "Forwarding";
+ else
+ *value = "Disabled";
+ return 0;
+}
+
+int get_br_port_pvid(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ char *name, *type, *priority;
+
+ *value = "1";
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "name", &name);
+ s = check_if_ifname_is_tagged(name);
+ if(s != NULL) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if(strcmp(type, "untagged") != 0)
+ dmuci_get_value_by_section_string(s, "vid", value);
+ }
+ return 0;
+}
+
+int set_br_port_pvid(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *s = NULL;
+ char *name, *type, *priority, *ifname, *new_name;
+ int is_enabled;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "name", &name);
+ s = check_if_ifname_is_tagged(name);
+ if(s != NULL) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if(strcmp(type, "untagged") != 0) {
+ dmuci_set_value_by_section(s, "vid", value);
+ dmuci_get_value_by_section_string(s, "ifname", &ifname);
+ dmasprintf(&new_name, "%s.%s", ifname, value);
+ is_enabled = is_br_port_enabled((struct bridging_port_args *)data);
+ if(is_enabled)
+ update_br_port_ifname((struct bridging_port_args *)data, 0);
+ dmuci_set_value_by_section(s, "name", new_name);
+ if(is_enabled)
+ update_br_port_ifname((struct bridging_port_args *)data, 1);
+ dmfree(new_name);
+ }
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_port_tpid(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *type;
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "type", &type);
+ if (strcmp(type, "8021q") == 0 || strcmp(type, "untagged") == 0)
+ *value = "33024";
+ else if (strcmp(type, "8021ad") == 0)
+ *value = "34984";
+ else
+ *value = "";
+ return 0;
+}
+
+int set_br_port_tpid(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "33024") == 0)
+ dmuci_set_value_by_section(((struct bridging_port_args *)data)->bridge_port_sec, "type", "8021q");
+ else if (strcmp(value, "34984") == 0)
+ dmuci_set_value_by_section(((struct bridging_port_args *)data)->bridge_port_sec, "type", "8021ad");
+ return 0;
+ }
+ return 0;
+}
+
+/**************************************************************************
+* GET STAT
+***************************************************************************/
+inline int get_bridge_port_statistics(void *data, char *stat_mod, char **value)
+{
+ json_object *res;
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "ifname", value);
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", *value, String}}, 1, &res);
+ DM_ASSERT(res, *value = "0");
+ *value = dmjson_get_value(res, 2, "statistics", stat_mod);
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Stats.BytesSent!UBUS:network.device/status/name,@Name/statistics.tx_bytes*/
+int get_br_port_stats_tx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_bridge_port_statistics(data, "tx_bytes", value);
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Stats.BytesSent!UBUS:network.device/status/name,@Name/statistics.rx_bytes*/
+int get_br_port_stats_rx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_bridge_port_statistics(data, "rx_bytes", value);
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Stats.PacketsSent!UBUS:network.device/status/name,@Name/statistics.tx_packets*/
+int get_br_port_stats_tx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_bridge_port_statistics(data, "tx_packets", value);
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Stats.PacketsReceived!UBUS:network.device/status/name,@Name/statistics.rx_packets*/
+int get_br_port_stats_rx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_bridge_port_statistics(data, "rx_packets", value);
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Stats.ErrorsSent!UBUS:network.device/status/name,@Name/statistics.tx_errors*/
+int get_br_port_stats_tx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_bridge_port_statistics(data, "tx_errors", value);
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Stats.ErrorsReceived!UBUS:network.device/status/name,@Name/statistics.rx_errors*/
+int get_br_port_stats_rx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_bridge_port_statistics(data, "rx_errors", value);
+ return 0;
+}
+
+int get_br_port_stats_tx_unicast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "ifname", &ifname);
+ if(ifname[0] != '\0' && !strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "TX", "unicast"));
+ return 0;
+}
+
+int get_br_port_stats_rx_unicast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "ifname", &ifname);
+ if(ifname[0] != '\0' && !strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "RX", "unicast"));
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Stats.DiscardPacketsSent!UBUS:network.device/status/name,@Name/statistics.tx_dropped*/
+int get_br_port_stats_tx_discard_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_bridge_port_statistics(data, "tx_dropped", value);
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Stats.DiscardPacketsReceived!UBUS:network.device/status/name,@Name/statistics.rx_dropped*/
+int get_br_port_stats_rx_discard_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_bridge_port_statistics(data, "rx_dropped", value);
+ return 0;
+}
+
+int get_br_port_stats_tx_multicast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "ifname", &ifname);
+ if(ifname[0] != '\0' && !strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "TX", "multicast"));
+ return 0;
+}
+
+int get_br_port_stats_rx_multicast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "ifname", &ifname);
+ if(ifname[0] != '\0' && !strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "RX", "multicast"));
+ return 0;
+}
+
+int get_br_port_stats_tx_broadcast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "ifname", &ifname);
+ if(ifname[0] != '\0' && !strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "TX", "broadcast"));
+ return 0;
+}
+
+int get_br_port_stats_rx_broadcast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "ifname", &ifname);
+ if(ifname[0] != '\0' && !strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "RX", "broadcast"));
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.Port.{i}.Stats.UnknownProtoPacketsReceived!UBUS:network.device/status/name,@Name/statistics.rx_over_errors*/
+int get_br_port_stats_rx_unknown_proto_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_bridge_port_statistics(data, "rx_over_errors", value);
+ return 0;
+}
+
+static int is_bridge_vlan_enabled(struct bridging_vlan_args *curr_arg)
+{
+ struct uci_section *vlan_sec = curr_arg->bridge_vlan_sec, *br_sec = curr_arg->bridge_sec;
+ char *ifname, *br_ifname, *ifname_dup, *pch, *spch;
+
+ dmuci_get_value_by_section_string(br_sec, "ifname", &br_ifname);
+ dmuci_get_value_by_section_string(vlan_sec, "name", &ifname);
+ ifname_dup = dmstrdup(br_ifname);
+ if(ifname!=NULL && ifname[0]!='\0'){
+ if (is_strword_in_optionvalue(ifname_dup, ifname))
+ return 1;
+ }
+ return 0;
+}
+
+static int update_br_vlan_ifname(struct bridging_vlan_args *curr_arg, int status)
+{
+ char ifname_dup[128], *ptr, *baseifname, *ifname, *start, *end;
+ struct uci_section *vlan_sec = curr_arg->bridge_vlan_sec, *br_sec = curr_arg->bridge_sec;
+ int pos=0;
+ dmuci_get_value_by_section_string(br_sec, "ifname", &ifname);
+ dmuci_get_value_by_section_string(vlan_sec, "name", &baseifname);
+ ptr = ifname_dup;
+ dmstrappendstr(ptr, ifname);
+ dmstrappendend(ptr);
+ if(status){
+ if (is_strword_in_optionvalue(ifname_dup, baseifname)) return 0;
+ if (ifname_dup[0] != '\0') dmstrappendchr(ptr, ' ');
+ dmstrappendstr(ptr, baseifname);
+ dmstrappendend(ptr);
+ }else{
+ if (is_strword_in_optionvalue(ifname_dup, baseifname)){
+ start = strstr(ifname_dup, baseifname);
+ end = start + strlen(baseifname);
+ if(start != ifname_dup){
+ start--;
+ pos=1;
+ }
+ memmove(start, start + strlen(baseifname)+pos, strlen(end) + 1);
+ }
+ }
+ dmuci_set_value_by_section(br_sec, "ifname", ifname_dup);
+ return 0;
+}
+
+int get_br_vlan_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "false";
+ int status;
+ status = is_bridge_vlan_enabled((struct bridging_vlan_args *)data);
+ if (status)
+ *value = "true";
+ return 0;
+}
+
+int set_br_vlan_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ char *vlan_ifname, *br_ifname, *vid, *p;
+ char new_ifname[256];
+ char pr_linker[32];
+ int is_enabled;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ is_enabled = is_bridge_vlan_enabled((struct bridging_vlan_args *)data);
+ if (b && !is_enabled) {
+ update_br_vlan_ifname((struct bridging_vlan_args *)data, 1);
+ }
+ if (!b && is_enabled){
+ update_br_vlan_ifname((struct bridging_vlan_args *)data, 0);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_vlan_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "";
+ *value = dmstrdup(section_name(((struct bridging_vlan_args *)data)->bridge_vlan_sec));
+ return 0;
+}
+
+int set_br_vlan_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_rename_section_by_section(((struct bridging_vlan_args *)data)->bridge_vlan_sec,value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_vlan_vid(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "vid", value);
+ return 0;
+}
+
+int set_br_vlan_vid(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *name, *br_ifname, *ifname;
+ int is_enabled;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "vid", value);
+ dmuci_get_value_by_section_string(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "ifname", &ifname);
+ dmasprintf(&name, "%s.%s", ifname, value);
+ is_enabled = is_bridge_vlan_enabled((struct bridging_vlan_args *)data);
+ if(is_enabled)
+ update_br_vlan_ifname((struct bridging_vlan_args *)data, 0);
+ dmuci_set_value_by_section(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "name", name);
+ if(is_enabled)
+ update_br_vlan_ifname((struct bridging_vlan_args *)data, 1);
+ dmfree(name);
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_vlan_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "priority", value);
+ return 0;
+}
+
+int set_br_vlan_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "priority", value);
+ return 0;
+ }
+ return 0;
+}
+/*************************************************************
+ * GET SET ALIAS
+/*************************************************************/
+int get_br_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct bridging_args *)data)->bridge_sec), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "bridge_alias", value);
+ return 0;
+}
+
+int set_br_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct bridging_args *)data)->bridge_sec), &dmmap_section);
+ dmuci_set_value_by_section(dmmap_section, "bridge_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_port_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section= NULL;
+
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(((struct bridging_port_args *)data)->bridge_port_sec), &dmmap_section);
+ if(dmmap_section==NULL || dmmap_section==0)
+ dmmap_section= ((struct bridging_port_args *)data)->bridge_port_sec;
+
+ dmuci_get_value_by_section_string(dmmap_section, "bridge_port_alias", value);
+ return 0;
+}
+
+int set_br_port_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section= NULL;
+
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(((struct bridging_port_args *)data)->bridge_port_sec), &dmmap_section);
+ if(dmmap_section==NULL || dmmap_section==0)
+ dmmap_section= ((struct bridging_port_args *)data)->bridge_port_sec;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(dmmap_section, "bridge_port_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_vlan_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_network", "device", section_name(((struct bridging_vlan_args *)data)->bridge_vlan_sec), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "bridge_vlan_alias", value);
+ return 0;
+}
+
+int set_br_vlan_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ get_dmmap_section_of_config_section("dmmap_network", "device", section_name(((struct bridging_vlan_args *)data)->bridge_vlan_sec), &dmmap_section);
+ dmuci_set_value_by_section(dmmap_section, "bridge_vlan_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*************************************************************
+ * ADD DELETE OBJECT
+/*************************************************************/
+int add_bridge(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ char *last_inst, *v;
+ char bridge_name[16], ib[8];
+ char *p = bridge_name;
+ struct uci_section* dmmap_bridge= NULL;
+
+ last_inst = get_last_instance_lev2_icwmpd("network", "interface", "dmmap_network", "bridge_instance", "type", "bridge");
+ sprintf(ib, "%d", last_inst ? atoi(last_inst)+1 : 1);
+ dmstrappendstr(p, "bridge_0_");
+ dmstrappendstr(p, ib);
+ dmstrappendend(p);
+ dmuci_set_value("network", bridge_name, "", "interface");
+ dmuci_set_value("network", bridge_name, "type", "bridge");
+ dmuci_set_value("network", bridge_name, "proto", "dhcp");
+
+ dmuci_add_section_icwmpd("dmmap_network", "interface", &dmmap_bridge, &v);
+ dmuci_set_value_by_section(dmmap_bridge, "section_name", bridge_name);
+ *instance = update_instance_icwmpd(dmmap_bridge, last_inst, "bridge_instance");
+
+ update_section_list(DMMAP,"bridge_port", "bridge_key", 1, ib, "mg_port", "true", "bridge_port_instance", "1");
+ return 0;
+}
+
+int delete_bridge(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *s = NULL, *prev_s = NULL;
+ struct uci_section *bridge_s, *vlan_s, *dmmap_section= NULL;
+ char *bridgekey = NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct bridging_args *)data)->bridge_sec), &dmmap_section);
+ dmuci_set_value_by_section(((struct bridging_args *)data)->bridge_sec, "type", "");
+ dmuci_set_value_by_section(dmmap_section, "bridge_instance", "");
+ dmuci_set_value_by_section(dmmap_section, "ip_int_instance", "");
+ dmuci_set_value_by_section(dmmap_section, "ipv4_instance", "");
+ uci_path_foreach_option_eq(icwmpd, "dmmap", "bridge_port", "bridge_key", ((struct bridging_args *)data)->br_key, s) {
+ if (prev_s)
+ DMUCI_DELETE_BY_SECTION(icwmpd, prev_s, NULL, NULL);
+ prev_s = s;
+ }
+ if (prev_s)
+ DMUCI_DELETE_BY_SECTION(icwmpd, prev_s, NULL, NULL);
+ reset_br_port( ((struct bridging_args *)data)->br_key);
+ dmuci_set_value_by_section(((struct bridging_args *)data)->bridge_sec, "ifname", "");
+ break;
+ case DEL_ALL:
+ uci_foreach_option_eq("network", "interface", "type", "bridge", bridge_s) {
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(bridge_s), &dmmap_section);
+ dmuci_set_value_by_section(bridge_s, "type", "");
+ dmuci_get_value_by_section_string(dmmap_section, "bridge_instance", &bridgekey);
+ dmuci_set_value_by_section(dmmap_section, "bridge_instance", "");
+ dmuci_set_value_by_section(dmmap_section, "ip_int_instance", "");
+ dmuci_set_value_by_section(dmmap_section, "ipv4_instance", "");
+ uci_path_foreach_option_eq(icwmpd, "dmmap", "bridge_port", "bridge_key", bridgekey, s) {
+ prev_s = s;
+ }
+ if (prev_s)
+ DMUCI_DELETE_BY_SECTION(icwmpd, prev_s, NULL, NULL);
+ reset_br_port(bridgekey);
+ dmuci_set_value_by_section(bridge_s, "ifname", "");
+ }
+ break;
+ }
+ return 0;
+}
+
+int add_br_vlan(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ char *value, *last_instance, *v, *vlan_name, *name, *last_vid, *vid;
+ struct uci_section *vlan_s, *dmmap_bridge_vlan;
+
+ check_create_dmmap_package("dmmap_network");
+ last_instance = get_last_instance_lev2_icwmpd_dmmap_opt("dmmap_network", "device", "bridge_vlan_instance", "bridge_key", ((struct bridging_args *)data)->br_key);
+ dmasprintf(&vlan_name, "vlan%d", last_instance ? atoi(last_instance)+ 1 : 1);
+ last_vid = get_last_vid();
+ dmasprintf(&name, "%s.%d", wan_baseifname, last_vid ? atoi(last_vid)+ 1 : 1001);
+ dmasprintf(&vid, "%d", last_vid ? atoi(last_vid)+ 1 : 1001);
+ dmuci_add_section_and_rename("network", "device", &vlan_s, &value);
+ dmuci_rename_section_by_section(vlan_s, vlan_name);
+ dmuci_set_value_by_section(vlan_s, "priority", "0");
+ dmuci_set_value_by_section(vlan_s, "type", "8021q");
+ dmuci_set_value_by_section(vlan_s, "vid", vid);
+ dmuci_set_value_by_section(vlan_s, "name", name);
+ dmuci_set_value_by_section(vlan_s, "ifname", wan_baseifname);
+ dmfree(name);
+ dmfree(vid);
+
+ dmuci_add_section_icwmpd("dmmap_network", "device", &dmmap_bridge_vlan, &v);
+ dmuci_set_value_by_section(dmmap_bridge_vlan, "section_name", vlan_name);
+ dmuci_set_value_by_section(dmmap_bridge_vlan, "bridge_key", ((struct bridging_args *)data)->br_key);
+ *instance = update_instance_icwmpd(dmmap_bridge_vlan, last_instance, "bridge_vlan_instance");
+ return 0;
+}
+
+int delete_br_vlan(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ char *vid, *ifname, *type;
+ struct uci_section *prev_s = NULL, *vlan_s=NULL, *dmmap_section;
+ char new_ifname[128];
+ int is_enabled;
+
+ switch (del_action) {
+ case DEL_INST:
+ is_enabled = is_bridge_vlan_enabled((struct bridging_vlan_args *)data);
+ if(is_enabled)
+ update_br_vlan_ifname((struct bridging_vlan_args *)data, 0);
+ get_dmmap_section_of_config_section("dmmap_network", "device", section_name(((struct bridging_vlan_args *)data)->bridge_vlan_sec), &dmmap_section);
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(((struct bridging_vlan_args *)data)->bridge_vlan_sec, NULL, NULL);
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("network", "device", vlan_s) {
+ dmuci_get_value_by_section_string(vlan_s, "type", &type);
+ if (strcmp(type, "untagged")==0)
+ continue;
+ dmuci_get_value_by_section_string(vlan_s, "vid", &vid);
+ dmuci_get_value_by_section_string(((struct bridging_args *)data)->bridge_sec, "ifname", &ifname);
+ if(ifname[0] != '\0' && vid[0] != '\0'){
+ remove_vid_interfaces_from_ifname(vid, ifname, new_ifname);
+ dmuci_set_value_by_section(((struct bridging_args *)data)->bridge_sec, "ifname", new_ifname);
+ }
+ if (prev_s != NULL){
+ get_dmmap_section_of_config_section("dmmap_network", "device", section_name(prev_s), &dmmap_section);
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(prev_s, NULL, NULL);
+ }
+ prev_s = vlan_s;
+ }
+ if (prev_s != NULL){
+ get_dmmap_section_of_config_section("dmmap_network", "device", section_name(prev_s), &dmmap_section);
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(prev_s, NULL, NULL);
+ }
+ break;
+ }
+ return 0;
+}
+
+int add_br_port(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ char *value;
+ struct uci_section *br_port_s;
+
+ int m = get_br_port_last_inst(((struct bridging_args *)data)->br_key);
+ dmasprintf(instance, "%d", m+1);
+ DMUCI_ADD_SECTION(icwmpd, "dmmap_bridge_port", "bridge_port", &br_port_s, &value);
+ dmuci_set_value_by_section(br_port_s, "bridge_key", ((struct bridging_args *)data)->br_key);
+ dmuci_set_value_by_section(br_port_s, "bridge_port_instance", *instance);
+ dmuci_set_value_by_section(br_port_s, "mg_port", "false");
+ return 0;
+}
+
+int delete_br_port(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ char *ifname;
+ char new_ifname[128];
+ struct uci_section *s = NULL, *prev_s = NULL, *dmmap_section= NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(((struct bridging_port_args *)data)->bridge_port_sec), &dmmap_section);
+ if(dmmap_section==NULL || dmmap_section==0){
+ dmmap_section= ((struct bridging_port_args *)data)->bridge_port_sec;
+ dmuci_delete_by_section_unnamed_icwmpd(dmmap_section, NULL, NULL);
+ }
+ else{
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_sec, "ifname", &ifname);
+ if(ifname[0] != '\0'){
+ remove_interface_from_ifname(((struct bridging_port_args *)data)->ifname, ifname, new_ifname);
+ dmuci_set_value_by_section(((struct bridging_port_args *)data)->bridge_sec, "ifname", new_ifname);
+ }
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(((struct bridging_port_args *)data)->bridge_port_sec), &dmmap_section);
+ dmuci_delete_by_section_unnamed_icwmpd(dmmap_section, NULL, NULL);
+ }
+ break;
+ case DEL_ALL:
+ uci_path_foreach_option_eq(icwmpd, "dmmap_bridge_port", "bridge_port", "bridge_key", ((struct bridging_args *)data)->br_key, s) {
+ if (prev_s)
+ DMUCI_DELETE_BY_SECTION(icwmpd, prev_s, NULL, NULL);
+ prev_s = s;
+ }
+ if (prev_s)
+ DMUCI_DELETE_BY_SECTION(icwmpd, prev_s, NULL, NULL);
+ dmuci_set_value_by_section(((struct bridging_args *)data)->bridge_sec, "ifname", ""); // TO CHECK
+ break;
+ }
+ return 0;
+}
+
+/*************************************************************
+ * LOWER LAYER
+/*************************************************************/
+int check_port_with_ifname (char *ifname, struct uci_section **ss)
+{
+ struct uci_section *sss, *s;
+ char *file_config_name;
+ char *atm_device, *ptm_device;
+
+ dmasprintf(&file_config_name, "%s","/etc/config/dsl");
+
+ if (check_ifname_is_vlan(ifname)) {
+ uci_foreach_option_eq("network", "device", "name", ifname, s) {
+ *ss = s;
+ break;
+ }
+ }
+ else if (strncmp(ifname, "ptm", 3) == 0) {
+ if(access( file_config_name, F_OK ) != -1){
+ uci_foreach_sections("dsl", "ptm-device", sss) {
+ dmuci_get_value_by_section_string(sss, "device", &ptm_device);
+ dmasprintf(&ptm_device, "%s.1", ptm_device);
+ if(strcmp(ifname, ptm_device)==0) {
+ uci_foreach_option_eq("network", "device", "name", ifname, s) {
+ *ss = s;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (strncmp(ifname, "atm", 3) == 0) {
+ if(access( file_config_name, F_OK ) != -1){
+ uci_foreach_sections("dsl", "atm-device", sss) {
+ dmuci_get_value_by_section_string(sss, "device", &atm_device);
+ dmasprintf(&atm_device, "%s.1", atm_device);
+ if(strcmp(ifname, atm_device)==0) {
+ uci_foreach_option_eq("network", "device", "name", ifname, s) {
+ *ss = s;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if(strncmp(ifname, wan_baseifname, strlen(wan_baseifname))==0) {
+ uci_foreach_option_eq("network", "device", "name", ifname, s) {
+ *ss = s;
+ break;
+ }
+ }
+ else if(strncmp(ifname, "wl", 2) == 0 || strncmp(ifname, "ra", 2) == 0 || strncmp(ifname, "apclii", 6) == 0) {
+ uci_foreach_option_eq("wireless", "wifi-iface", "ifname", ifname, s) {
+ *ss = s;
+ break;
+ }
+ }
+ else {
+ uci_foreach_option_eq("ports", "ethport", "ifname", ifname, s) {
+ *ss = s;
+ break;
+ }
+ }
+ return 0;
+}
+
+int get_port_lower_layer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *mg_port, *pch, *spch, *ifname, *ifname_dup, *p, *linker = "";
+ char buf[16], plinker[32], lbuf[512];
+ struct uci_section *s = NULL;
+
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "mg_port", &mg_port);
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_sec, "ifname", &ifname);
+ if (ifname[0] != '\0' && strcmp(mg_port, "true") == 0) {
+ ifname_dup = dmstrdup(ifname);
+ p = lbuf;
+ for (pch = strtok_r(ifname_dup, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) {
+ check_port_with_ifname(pch, &s);
+ if(s == NULL)
+ continue;
+ sprintf(plinker, "%s+%s", section_name(s), pch);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, dm_delim, dm_delim, dm_delim), plinker, value);
+ if (*value == NULL)
+ *value = "";
+ dmstrappendstr(p, *value);
+ dmstrappendchr(p, ',');
+ }
+ p = p -1;
+ dmstrappendend(p);
+ *value = dmstrdup(lbuf);
+ return 0;
+ } else {
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "ifname", &linker);
+ if (strcmp(linker, wan_baseifname) == 0) {
+ dmasprintf(&linker, "%s.1", linker);
+ }
+ if(((struct bridging_port_args *)data)->vlan) {
+ strncpy(buf, linker, 5);
+ buf[5] = '\0';
+ strcat(buf, "1");
+ linker = buf;
+ }
+ }
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
+ if (*value == NULL)
+ adm_entry_get_linker_param(ctx,dm_print_path("%s%cWiFi%cSSID%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
+ if (*value == NULL)
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cATM%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
+ if (*value == NULL)
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cPTM%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
+
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+int set_port_lower_layer(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *linker, *iface, *ifname, *p, *br_key, *br_pt_inst = "", *mg_port = "false", *br_port_ifname, *vid = NULL;
+ char *newvalue= NULL;
+ char new_ifname[256];
+ char tmp[16];
+ char pr_linker[32];
+ struct uci_section *s;
+ struct uci_section *dmmap_section= NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ get_dmmap_section_of_config_section("dmmap_bridge_port", "bridge_port", section_name(((struct bridging_port_args *)data)->bridge_port_sec), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "mg_port", &mg_port);
+ if (value[strlen(value)-1]!='.') {
+ dmasprintf(&newvalue, "%s.", value);
+ adm_entry_get_linker_value(ctx, newvalue, &linker);
+ } else
+ adm_entry_get_linker_value(ctx, value, &linker);
+ if (strcmp(mg_port, "false")!=0 && linker && !check_ifname_exist_in_br_ifname_list(linker))
+ return FAULT_9001;
+ return 0;
+ case VALUESET:
+ if (value[strlen(value)-1]!='.') {
+ dmasprintf(&newvalue, "%s.", value);
+ adm_entry_get_linker_value(ctx, newvalue, &linker);
+ } else
+ adm_entry_get_linker_value(ctx, value, &linker);
+ //check ifname(linker) doesn't exit in bridges
+ if (linker && check_ifname_exist_in_br_ifname_list(linker)) {
+ //save param of current port and copy it to new port
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "bridge_key", &br_key);
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "bridge_port_instance", &br_pt_inst);
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_port_sec, "mg_port", &mg_port);
+ //remove old port (ifname) from bridge
+ if (((struct bridging_port_args *)data)->ifname[0] != 0 && strcmp(((struct bridging_port_args *)data)->ifname, linker) != 0) {
+ delete_br_port(NULL, ctx, data, instance, DEL_INST);
+ }
+ // check if the current port is already linked with VLAN
+ sprintf(pr_linker,"%s+%s", section_name(((struct bridging_port_args *)data)->bridge_port_sec), ((struct bridging_port_args *)data)->ifname);
+ uci_foreach_option_eq("network", "device", "br_port_linker", pr_linker, s) {
+ dmuci_get_value_by_section_string(s, "vlan8021q", &vid);
+ break;
+ }
+ dmuci_get_value_by_section_string(((struct bridging_port_args *)data)->bridge_sec, "ifname", &ifname);
+ p = new_ifname;
+ if (ifname[0] != '\0') {
+ dmstrappendstr(p, ifname);
+ dmstrappendchr(p, ' ');
+ }
+ if(vid && check_ifname_is_not_lan_port(linker) && !strstr (linker, "wl")) {
+ strncpy(tmp, linker, 5);
+ tmp[5] = '\0';
+ strcat(tmp, vid);
+ linker = tmp;
+ dmstrappendstr(p, tmp);
+ dmstrappendend(p);
+ uci_foreach_option_eq("network", "device", "br_port_linker", pr_linker, s) {
+ sprintf(pr_linker,"%s+%s", section_name(s), linker);
+ dmuci_set_value_by_section(s, "br_port_linker", pr_linker);
+ dmuci_set_value_by_section(s, "ifname", linker);
+ dmuci_set_value_by_section(s, "penable", "1");
+ }
+ } else {
+ dmstrappendstr(p, linker);
+ dmstrappendend(p);
+ }
+ dmuci_set_value_by_section(((struct bridging_port_args *)data)->bridge_sec, "ifname", new_ifname);
+ //remove old br_port param to the new one
+ update_port_parameters(linker, br_key, br_pt_inst, mg_port);
+ if(((struct bridging_port_args *)data)->ifname[0] == '\0')
+ DMUCI_DELETE_BY_SECTION(icwmpd,((struct bridging_port_args *)data)->bridge_port_sec, NULL, NULL);// delete dmmap section after remove br_port_instance to adequate config
+ } else {
+ return FAULT_9005;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_vlan_port_vlan_ref(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char linker[8];
+ sprintf(linker,"vlan%s_%s", ((struct bridging_vlan_args *)data)->vlan_port, ((struct bridging_vlan_args *)data)->br_inst);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value); // MEM WILL BE FREED IN DMMEMCLEAN
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+int set_vlan_port_vlan_ref(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ return 0;
+ }
+ return 0;
+}
+
+int get_vlan_port_port_ref(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char linker[16], *name;
+ dmuci_get_value_by_section_string(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "name", &name);
+ sprintf(linker,"%s+%s", section_name(((struct bridging_vlan_args *)data)->bridge_vlan_sec), name);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value); // MEM WILL BE FREED IN DMMEMCLEAN
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+int set_vlan_port_port_ref(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *linker = NULL, *vid, *enable, *vifname, tmp[8], *pch, *p, *br_ifname;
+ char new_ifname[16];
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ adm_entry_get_linker_value(ctx, value, &linker);
+ if (!linker) {
+ dmuci_set_value_by_section(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "br_port_linker", "");
+ set_br_vlan_enable(refparam, ctx, data, instance, "false", action);
+ return 0;
+ }
+ dmuci_set_value_by_section(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "br_port_linker", linker);
+ dmuci_get_value_by_section_string(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "vlan8021q", &vid);
+ pch = strchr(linker, '+') + 1;
+ if (pch[0] == '\0') {
+ dmfree(linker);
+ return 0;
+ }
+ if (vid[0] == '\0') {
+ if (strstr(pch, "atm") || strstr(pch, "ptm") || strstr(pch, wan_baseifname)) {
+ strncpy(tmp, pch, 4);
+ tmp[4] ='\0';
+ dmuci_set_value_by_section(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "ifname", tmp);
+ }
+ } else {
+ if (strstr(pch, "atm") || strstr(pch, "ptm") || strstr(pch, wan_baseifname)) {
+ p = new_ifname;
+ strncpy(tmp, pch, 4);
+ tmp[4] ='\0';
+ dmuci_set_value_by_section(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "ifname", tmp);
+ dmstrappendstr(p, tmp);
+ dmstrappendchr(p, '.');
+ dmstrappendstr(p, vid);
+ dmstrappendend(p);
+ dmuci_set_value_by_section(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "ifname", new_ifname);
+ dmuci_get_value_by_section_string(((struct bridging_vlan_args *)data)->bridge_vlan_sec, "penable", &enable);///TO CHECK
+ // add to bridge ifname if enable = 1
+ if (enable[0] == '1') {
+ vifname = dmstrdup(new_ifname);
+ dmuci_get_value_by_section_string(((struct bridging_vlan_args *)data)->bridge_sec, "ifname", &br_ifname);
+ p = new_ifname;
+ if (br_ifname[0] != '\0') {
+ dmstrappendstr(p, br_ifname);
+ dmstrappendchr(p, ' ');
+ }
+ dmstrappendstr(p, vifname);
+ dmstrappendend(p);
+ dmuci_set_value_by_section(((struct bridging_vlan_args *)data)->bridge_sec, "ifname", new_ifname);
+ dmfree(vifname);
+ }
+ }
+ }
+ dmfree(linker);
+ return 0;
+ }
+ return 0;
+}
+
+int get_br_vlan_untagged(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int set_br_vlan_untagged(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ return 0;
+ }
+ return 0;
+}
+
+/*************************************************************
+ * ENTRY METHOD
+/*************************************************************/
+/*#Device.Bridging.Bridge.{i}.!UCI:network/interface/dmmap_network*/
+int browseBridgeInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *br_inst = NULL, *br_inst_last = NULL, *ifname;
+ struct bridging_args curr_bridging_args = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ dmuci_get_option_value_string("ports", "WAN", "ifname", &wan_baseifname);
+
+ synchronize_specific_config_sections_with_dmmap_eq("network", "interface", "dmmap_network", "type", "bridge", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ br_inst = handle_update_instance(1, dmctx, &br_inst_last, update_instance_alias, 3, p->dmmap_section, "bridge_instance", "bridge_alias");
+ dmuci_get_value_by_section_string(p->config_section, "ifname", &ifname);
+ init_bridging_args(&curr_bridging_args, p->config_section, br_inst_last, ifname, br_inst);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_bridging_args, br_inst) == DM_STOP)
+ break;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
+
+static void set_bridge_port_parameters(struct uci_section *dmmap_section, char* bridge_key)
+{
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_section, "bridge_key", bridge_key);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_section, "mg_port", "false");
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_section, "penable", "1");
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_section, "is_dmmap", "false");
+}
+
+int browseBridgePortInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance){
+ struct uci_section *new_port = NULL, *ss_atm = NULL, *ss_ptm = NULL;
+ char *port = NULL, *port_last = NULL, *ifname_dup = NULL, *pch, *spch, *is_dmmap, *file_config_name, *deviceatm, *deviceptm, *atm_device, *ptm_device;
+ bool find_max = true, found = false;
+ struct bridging_port_args curr_bridging_port_args = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ dmasprintf(&file_config_name, "%s","/etc/config/dsl");
+ check_create_dmmap_package("dmmap_bridge_port");
+ update_section_list_icwmpd("dmmap_bridge_port","bridge_port", "bridge_key", 1, ((struct bridging_args *)prev_data)->br_key, "mg_port", "true", "bridge_port_instance", "1");
+ uci_path_foreach_option_eq(icwmpd, "dmmap_bridge_port", "bridge_port", "bridge_key", ((struct bridging_args *)prev_data)->br_key, new_port) {
+ dmuci_get_value_by_section_string(new_port, "is_dmmap", &is_dmmap);
+ if(strcmp(is_dmmap, "false") !=0 ) {
+ init_bridging_port_args(&curr_bridging_port_args, new_port, ((struct bridging_args *)prev_data)->bridge_sec, false, "");
+ port = handle_update_instance(2, dmctx, &port_last, update_instance_alias_icwmpd, 5, new_port, "bridge_port_instance", "bridge_port_alias", &find_max, ((struct bridging_args *)prev_data)->br_key);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_bridging_port_args, port) == DM_STOP)
+ goto end;
+ }
+ }
+
+ if (((struct bridging_args *)prev_data)->ifname[0] == '\0')
+ return 0;
+ ifname_dup = dmstrdup(((struct bridging_args *)prev_data)->ifname);
+ for (pch = strtok_r(ifname_dup, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) {
+ found = false;
+
+ if(!found)
+ found= synchronize_multi_config_sections_with_dmmap_eq("ports", "ethport", "dmmap_bridge_port", "bridge_port", "ifname", pch, pch, &dup_list);
+
+ if(!found)
+ found= synchronize_multi_config_sections_with_dmmap_eq("wireless", "wifi-iface", "dmmap_bridge_port", "bridge_port", "ifname", pch, pch, &dup_list);
+
+ if(access( file_config_name, F_OK ) != -1) {
+ uci_foreach_sections("dsl", "atm-device", ss_atm) {
+ dmuci_get_value_by_section_string(ss_atm, "device", &deviceatm);
+ dmasprintf(&atm_device, "%s.1", deviceatm);
+ if(!found) {
+ if(strncmp(pch, atm_device, strlen(atm_device))==0) {
+ found= synchronize_multi_config_sections_with_dmmap_eq("network", "device", "dmmap_bridge_port", "bridge_port", "name", pch, pch, &dup_list);
+ }
+ }
+ }
+
+ uci_foreach_sections("dsl", "ptm-device", ss_ptm) {
+ dmuci_get_value_by_section_string(ss_ptm, "device", &deviceptm);
+ dmasprintf(&ptm_device, "%s.1", deviceptm);
+ if(!found) {
+ if(strncmp(pch, ptm_device, strlen(ptm_device))==0) {
+ found= synchronize_multi_config_sections_with_dmmap_eq("network", "device", "dmmap_bridge_port", "bridge_port", "name", pch, pch, &dup_list);
+ }
+ }
+ }
+ }
+
+ if(!found){
+ if(strncmp(pch, wan_baseifname, strlen(wan_baseifname))==0) {
+ found= synchronize_multi_config_sections_with_dmmap_eq("network", "device", "dmmap_bridge_port", "bridge_port", "name", pch, pch, &dup_list);
+ }
+ }
+
+ if(!found){
+ if(strncmp(pch, wan_baseifname, 4) == 0 || strncmp(pch, "ptm", 3) == 0 || strncmp(pch, "atm", 3) == 0){
+ found= synchronize_multi_config_sections_with_dmmap_eq_diff("network", "device", "dmmap_bridge_port", "bridge_port", "name", pch, "type", "untagged", pch, &dup_list);
+ }
+ }
+ }
+
+ list_for_each_entry(p, &dup_list, list) {
+ set_bridge_port_parameters(p->dmmap_section, ((struct bridging_args *)prev_data)->br_key);
+ init_bridging_port_args(&curr_bridging_port_args, p->config_section, ((struct bridging_args *)prev_data)->bridge_sec, false, (char*)p->additional_attribute);
+ port = handle_update_instance(2, dmctx, &port_last, update_instance_alias_icwmpd, 5, p->dmmap_section, "bridge_port_instance", "bridge_port_alias", &find_max, ((struct bridging_args *)prev_data)->br_key);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_bridging_port_args, port) == DM_STOP)
+ goto end;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+end:
+ dmfree(ifname_dup);
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.VLAN.!UCI:network/device/dmmap_network*/
+int browseBridgeVlanInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *vlan = NULL, *vlan_last = NULL, *type, *is_lan = NULL;
+ struct bridging_vlan_args curr_bridging_vlan_args = {0};
+ struct bridging_args *br_args = (struct bridging_args *)prev_data;
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ dmuci_get_value_by_section_string(br_args->bridge_sec, "is_lan", &is_lan);
+ if(is_lan == NULL || strcmp(is_lan, "1") != 0) {
+ synchronize_specific_config_sections_with_dmmap("network", "device", "dmmap_network", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ if(!p->config_section)
+ goto end;
+ //Check if VLAN or NOT
+ dmuci_get_value_by_section_string(p->config_section, "type", &type);
+ if (strcmp(type, "untagged") != 0) {
+ dmuci_set_value_by_section(p->dmmap_section, "bridge_key", br_args->br_key);
+ vlan = handle_update_instance(2, dmctx, &vlan_last, update_instance_alias, 3, p->dmmap_section, "bridge_vlan_instance", "bridge_vlan_alias");
+ init_bridging_vlan_args(&curr_bridging_vlan_args, p->config_section, br_args->bridge_sec, vlan_last, br_args->br_key);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_bridging_vlan_args, vlan) == DM_STOP)
+ goto end;
+ }
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ }
+end:
+ return 0;
+}
+
+/*#Device.Bridging.Bridge.{i}.VLANPort.!UCI:network/device/dmmap_network*/
+int browseBridgeVlanPortInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *vlan = NULL, *vlan_last = NULL, *type, *is_lan = NULL;
+ struct bridging_vlan_args curr_bridging_vlan_args = {0};
+ struct bridging_args *br_args = (struct bridging_args *)prev_data;
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ dmuci_get_value_by_section_string(br_args->bridge_sec, "is_lan", &is_lan);
+ if(is_lan==NULL || strcmp(is_lan, "1") != 0){
+ synchronize_specific_config_sections_with_dmmap("network", "device", "dmmap_network", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ if(!p->config_section)
+ goto end;
+ //Check if VLAN or NOT
+ dmuci_get_value_by_section_string(p->config_section, "type", &type);
+ if (strcmp(type, "untagged") != 0) {
+ dmuci_set_value_by_section(p->dmmap_section, "bridge_key", br_args->br_key);
+ vlan = handle_update_instance(2, dmctx, &vlan_last, update_instance_alias, 3, p->dmmap_section, "bridge_vlan_instance", "bridge_vlan_alias");
+ init_bridging_vlan_args(&curr_bridging_vlan_args, p->config_section, br_args->bridge_sec, vlan_last, br_args->br_key);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_bridging_vlan_args, vlan) == DM_STOP)
+ goto end;
+ }
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ }
+end:
+ return 0;
+}
diff --git a/dmtree/tr181/bridging.h b/dmtree/tr181/bridging.h
new file mode 100644
index 00000000..edc79651
--- /dev/null
+++ b/dmtree/tr181/bridging.h
@@ -0,0 +1,144 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB
+ * Author: Anis Ellouze
+ * Author: Amin Ben Ramdhane
+ *
+ */
+
+#ifndef __BRIDGING_H
+#define __BRIDGING_H
+
+struct bridging_args
+{
+ struct uci_section *bridge_sec;
+ char *br_key;
+ char *ifname;
+ char *br_inst;
+};
+
+struct bridging_port_args
+{
+ struct uci_section *bridge_port_sec;
+ struct uci_section *bridge_sec;
+ bool vlan;
+ char *ifname;
+};
+
+struct bridging_vlan_args
+{
+ struct uci_section *bridge_vlan_sec;
+ struct uci_section *bridge_sec;
+ char *vlan_port;
+ char *br_inst;
+ char *ifname;
+};
+
+extern DMOBJ tBridgingObj[];
+extern DMLEAF tBridgingParams[];
+extern DMOBJ tBridgingBridgeObj[];
+extern DMLEAF tBridgingBridgeParams[];
+extern DMLEAF tBridgingBridgeVLANParams[];
+extern DMLEAF tBridgingBridgePortParams[];
+extern DMLEAF tBridgingBridgeVLANPortParams[];
+extern DMOBJ tBridgingBridgePortObj[];
+extern DMLEAF tBridgingBridgePortStatsParams[];
+
+int browseBridgeVlanPortInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseBridgeVlanInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseBridgePortInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseBridgeInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int get_linker_br_port(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+int get_linker_br_vlan(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+
+int add_bridge(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delete_bridge(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int add_br_vlan(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delete_br_vlan(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int add_br_port(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delete_br_port(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+
+int get_Max_Bridge_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_Max_DBridge_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_Max_QBridge_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_Max_VLAN_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_Max_Provider_Bridge_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_Max_Filter_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_Bridge_Number_Of_Entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_br_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_standard(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_standard(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_port_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_vlan_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_vlan_port_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_associated_interfaces(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_associated_interfaces(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int get_br_port_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_port_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_port_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_port_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_port_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_last_change(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_management(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_port_management(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_port_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_port_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_port_default_user_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_port_default_user_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_port_priority_regeneration(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_port_priority_regeneration(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_port_port_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_pvid(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_port_pvid(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_port_tpid(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_port_tpid(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_port_lower_layer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_port_lower_layer(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int get_br_port_stats_tx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_rx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_tx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_rx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_tx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_rx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_tx_unicast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_rx_unicast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_tx_discard_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_rx_discard_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_tx_multicast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_rx_multicast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_tx_broadcast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_rx_broadcast_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_br_port_stats_rx_unknown_proto_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_br_vlan_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_vlan_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_vlan_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_vlan_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_vlan_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_vlan_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_vlan_vid(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_vlan_vid(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_vlan_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_vlan_priority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int get_vlan_port_vlan_ref(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_vlan_port_vlan_ref(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_vlan_port_port_ref(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_vlan_port_port_ref(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_br_vlan_untagged(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_br_vlan_untagged(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+#endif
diff --git a/dmtree/tr181/device.c b/dmtree/tr181/device.c
new file mode 100644
index 00000000..84adc0d9
--- /dev/null
+++ b/dmtree/tr181/device.c
@@ -0,0 +1,109 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Imen Bhiri
+* Author: Anis Ellouze
+* Author: Amin Ben Ramdhane
+*/
+
+#include "dmuci.h"
+#include "dmcwmp.h"
+#include "device.h"
+#include "deviceinfo.h"
+#include "managementserver.h"
+#include "times.h"
+#include "upnp.h"
+#include "x_iopsys_eu_ice.h"
+#include "x_iopsys_eu_igmp.h"
+#include "x_iopsys_eu_ipacccfg.h"
+#include "x_iopsys_eu_logincfg.h"
+#include "x_iopsys_eu_power_mgmt.h"
+#include "x_iopsys_eu_syslog.h"
+#include "softwaremodules.h"
+#include "xmpp.h"
+#include "x_iopsys_eu_owsd.h"
+#include "x_iopsys_eu_dropbear.h"
+#include "x_iopsys_eu_buttons.h"
+#include "x_iopsys_eu_wifilife.h"
+#include "ip.h"
+#include "ethernet.h"
+#include "bridging.h"
+#include "wifi.h"
+#include "atm.h"
+#include "ptm.h"
+#include "dhcpv4.h"
+#include "hosts.h"
+#include "nat.h"
+#include "ppp.h"
+#include "routing.h"
+#include "userinterface.h"
+#include "firewall.h"
+#include "dns.h"
+#include "users.h"
+#include "dsl.h"
+#include "dhcpv6.h"
+#include "interfacestack.h"
+#include "qos.h"
+#ifdef BBF_TR104
+#include "voice_services.h"
+#endif
+
+/* *** CWMP *** */
+DMOBJ tEntry181Obj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{(char *)&dmroot, &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE, tRoot_181_Obj, tRoot_181_Params, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tRoot_181_Params[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"InterfaceStackNumberOfEntries", &DMREAD, DMT_UNINT, get_Device_InterfaceStackNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMOBJ tRoot_181_Obj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"DeviceInfo", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,tDeviceInfoObj, tDeviceInfoParams, NULL, BBFDM_BOTH},
+{"ManagementServer", &DMREAD, NULL, NULL, NULL, NULL, &DMFINFRM, &DMNONE,NULL, tManagementServerParams, NULL, BBFDM_BOTH},
+{"Time", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tTimeParams, NULL, BBFDM_BOTH},
+{"UPnP", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,tUPnPObj, NULL, NULL, BBFDM_BOTH},
+#ifdef BBF_TR104
+{"Services", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,tServiceObj, NULL, NULL, BBFDM_BOTH},
+#endif
+{CUSTOM_PREFIX"ICE", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_IceParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"IGMP", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_IgmpParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"IpAccCfg", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,tSe_IpAccObj, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"LoginCfg", &DMREAD, NULL, NULL, NULL, NULL,NULL, &DMNONE,NULL, tSe_LoginCfgParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"PowerManagement", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_PowerManagementParam, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"SyslogCfg", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,NULL, tSe_SyslogCfgParam, NULL, BBFDM_BOTH},
+{"SoftwareModules", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,tSoftwareModulesObj, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"Owsd", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE,XIopsysEuOwsdObj, XIopsysEuOwsdParams, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"Dropbear", &DMWRITE, add_dropbear_instance, delete_dropbear_instance, NULL, browseXIopsysEuDropbear, NULL, &DMNONE, NULL, X_IOPSYS_EU_DropbearParams, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"Buttons", &DMREAD, NULL, NULL, NULL, browseXIopsysEuButton, NULL, &DMNONE, NULL, X_IOPSYS_EU_ButtonParams, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"WiFiLife", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE, X_IOPSYS_EU_WiFiLifeObj, X_IOPSYS_EU_WiFiLifeParams, NULL, BBFDM_BOTH},
+{"Bridging",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tBridgingObj, tBridgingParams, NULL, BBFDM_BOTH},
+{"WiFi",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tWiFiObj, tWiFiParams, NULL, BBFDM_BOTH},
+{"IP",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPObj, tIPParams, NULL, BBFDM_BOTH},
+{"Ethernet", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tEthernetObj, tEthernetParams, NULL, BBFDM_BOTH},
+{"DSL",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDSLObj, tDSLParams, NULL, BBFDM_BOTH},
+{"ATM",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tATMObj, NULL, NULL, BBFDM_BOTH},
+{"PTM", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tPTMObj, NULL, NULL, BBFDM_BOTH},
+{"DHCPv4", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDhcpv4Obj, tDHCPv4Params, NULL, BBFDM_BOTH},
+{"DHCPv6", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDHCPv6Obj, tDHCPv6Params, NULL, BBFDM_BOTH},
+{"Hosts", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tHostsObj, tHostsParams, NULL, BBFDM_BOTH},
+{"NAT", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tNATObj, tNATParams, NULL, BBFDM_BOTH},
+{"PPP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tPPPObj, tPPPParams, NULL, BBFDM_BOTH},
+{"Routing", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tRoutingObj, tRoutingParams, NULL, BBFDM_BOTH},
+{"UserInterface", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tUserInterfaceObj, NULL, NULL, BBFDM_BOTH},
+{"Firewall", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tFirewallObj, tFirewallParams, NULL, BBFDM_BOTH},
+{"DNS", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDNSObj, tDNSParams, NULL, BBFDM_BOTH},
+{"Users", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tUsersObj, tUsersParams, NULL, BBFDM_BOTH},
+{"InterfaceStack", &DMREAD, NULL, NULL, NULL, browseInterfaceStackInst, NULL, NULL, NULL, tInterfaceStackParams, NULL, BBFDM_BOTH},
+//{"QoS", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tQoSObj, tQoSParams, NULL, BBFDM_BOTH},
+{"XMPP", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL,tXMPPObj, tXMPPParams, NULL, BBFDM_BOTH},
+{0}
+};
diff --git a/dmtree/tr181/device.h b/dmtree/tr181/device.h
new file mode 100644
index 00000000..e418783e
--- /dev/null
+++ b/dmtree/tr181/device.h
@@ -0,0 +1,20 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Imen Bhiri
+* Author: Anis Ellouze
+* Author: Amin Ben Ramdhane
+*/
+
+#ifndef __DEVICE_H
+#define __DEVICE_H
+
+extern DMOBJ tEntry181Obj[];
+extern DMOBJ tRoot_181_Obj[];
+extern DMLEAF tRoot_181_Params[];
+
+#endif
diff --git a/dmtree/tr181/deviceinfo.c b/dmtree/tr181/deviceinfo.c
new file mode 100644
index 00000000..62ed3113
--- /dev/null
+++ b/dmtree/tr181/deviceinfo.c
@@ -0,0 +1,797 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2012-2014 PIVA SOFTWARE (www.pivasoftware.com)
+ * Author: Imen Bhiri
+ * Author: Feten Besbes
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "dmcwmp.h"
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcommon.h"
+#include "deviceinfo.h"
+#include "dmjson.h"
+
+/* *** Device.DeviceInfo. *** */
+DMOBJ tDeviceInfoObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{CUSTOM_PREFIX"CATV", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tCatTvParams, NULL, BBFDM_BOTH},
+{"VendorConfigFile", &DMREAD, NULL, NULL, NULL, browseVcfInst, NULL, NULL, NULL, tDeviceInfoVendorConfigFileParams, NULL, BBFDM_BOTH},
+{"VendorLogFile", &DMREAD, NULL, NULL, NULL, browseVlfInst, NULL, NULL, NULL, tDeviceInfoVendorLogFileParams, NULL, BBFDM_BOTH},
+{"MemoryStatus", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoMemoryStatusParams, NULL, BBFDM_BOTH},
+{"ProcessStatus", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoProcessStatusObj, tDeviceInfoProcessStatusParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDeviceInfoParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Manufacturer", &DMREAD, DMT_STRING, get_device_manufacturer, NULL, &DMFINFRM, NULL, BBFDM_BOTH},
+{"ManufacturerOUI", &DMREAD, DMT_STRING, get_device_manufactureroui, NULL, &DMFINFRM, NULL, BBFDM_BOTH},
+{"ModelName", &DMREAD, DMT_STRING, get_device_routermodel, NULL, &DMFINFRM, NULL, BBFDM_BOTH},
+{"ProductClass", &DMREAD, DMT_STRING, get_device_productclass, NULL, &DMFINFRM, NULL, BBFDM_BOTH},
+{"SerialNumber", &DMREAD, DMT_STRING, get_device_serialnumber, NULL, &DMFINFRM, NULL, BBFDM_BOTH},
+{"HardwareVersion", &DMREAD, DMT_STRING, get_device_hardwareversion, NULL, &DMFINFRM, NULL, BBFDM_BOTH},
+{"SoftwareVersion", &DMREAD, DMT_STRING, get_device_softwareversion, NULL, &DMFINFRM, &DMACTIVE, BBFDM_BOTH},
+{"UpTime", &DMREAD, DMT_UNINT, get_device_info_uptime, NULL, NULL, NULL, BBFDM_BOTH},
+{"DeviceLog", &DMREAD, DMT_STRING, get_device_devicelog, NULL, NULL, NULL, BBFDM_BOTH},
+{"SpecVersion", &DMREAD, DMT_STRING, get_device_specversion, NULL, &DMFINFRM, NULL, BBFDM_BOTH},
+{"ProvisioningCode", &DMWRITE, DMT_STRING, get_device_provisioningcode, set_device_provisioningcode, &DMFINFRM, &DMACTIVE, BBFDM_BOTH},
+{CUSTOM_PREFIX"BaseMacAddr", &DMREAD, DMT_STRING, get_base_mac_addr, NULL, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"CATVEnabled", &DMWRITE, DMT_STRING, get_catv_enabled, set_device_catvenabled, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"MemoryBank", &DMWRITE, DMT_STRING, get_device_memory_bank, set_device_memory_bank, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DeviceInfo.VendorConfigFile.{i}. *** */
+DMLEAF tDeviceInfoVendorConfigFileParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_vcf_alias, set_vcf_alias, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_vcf_name, NULL, NULL, NULL, BBFDM_BOTH},
+{"Version", &DMREAD, DMT_STRING, get_vcf_version, NULL, NULL, NULL, BBFDM_BOTH},
+{"Date", &DMREAD, DMT_TIME, get_vcf_date, NULL, NULL, NULL, BBFDM_BOTH},
+{"Description", &DMREAD, DMT_STRING, get_vcf_desc, NULL, NULL, NULL, BBFDM_BOTH},
+{"UseForBackupRestore", &DMREAD, DMT_BOOL, get_vcf_backup_restore, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DeviceInfo.MemoryStatus. *** */
+DMLEAF tDeviceInfoMemoryStatusParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Total", &DMREAD, DMT_UNINT, get_memory_status_total, NULL, NULL, NULL, BBFDM_BOTH},
+{"Free", &DMREAD, DMT_UNINT, get_memory_status_free, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DeviceInfo.ProcessStatus. *** */
+DMOBJ tDeviceInfoProcessStatusObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Process", &DMREAD, NULL, NULL, NULL, browsePocessEntriesInst, NULL, NULL, NULL, tDeviceInfoProcessStatusProcessParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDeviceInfoProcessStatusParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"CPUUsage", &DMREAD, DMT_UNINT, get_process_cpu_usage, NULL, NULL, NULL, BBFDM_BOTH},
+{"ProcessNumberOfEntries", &DMREAD, DMT_UNINT, get_process_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DeviceInfo.ProcessStatus.Process.{i}. *** */
+DMLEAF tDeviceInfoProcessStatusProcessParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"PID", &DMREAD, DMT_UNINT, get_process_pid, NULL, NULL, NULL, BBFDM_BOTH},
+{"Command", &DMREAD, DMT_STRING, get_process_command, NULL, NULL, NULL, BBFDM_BOTH},
+{"Size", &DMREAD, DMT_UNINT, get_process_size, NULL, NULL, NULL, BBFDM_BOTH},
+{"Priority", &DMREAD, DMT_UNINT, get_process_priority, NULL, NULL, NULL, BBFDM_BOTH},
+{"CPUTime", &DMREAD, DMT_UNINT, get_process_cpu_time, NULL, NULL, NULL, BBFDM_BOTH},
+{"State", &DMREAD, DMT_STRING, get_process_state, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** DeviceInfo.X_IOPSYS_EU_CATV. ***/
+DMLEAF tCatTvParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enabled", &DMWRITE, DMT_STRING, get_catv_enabled, set_device_catvenabled, NULL, NULL, BBFDM_BOTH},
+{"OpticalInputLevel", &DMREAD, DMT_STRING, get_catv_optical_input_level, NULL, NULL, NULL, BBFDM_BOTH},
+{"RFOutputLevel", &DMREAD, DMT_STRING, get_catv_rf_output_level, NULL, NULL, NULL, BBFDM_BOTH},
+{"Temperature", &DMREAD, DMT_STRING, get_catv_temperature, NULL, NULL, NULL, BBFDM_BOTH},
+{"Voltage", &DMREAD, DMT_STRING, get_catv_voltage, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DeviceInfo.VendorLogFile.{i}. *** */
+DMLEAF tDeviceInfoVendorLogFileParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_vlf_alias, set_vlf_alias, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_vlf_name, NULL, NULL, NULL, BBFDM_BOTH},
+{"MaximumSize", &DMREAD, DMT_UNINT, get_vlf_max_size, NULL, NULL, NULL, BBFDM_BOTH},
+{"Persistent", &DMREAD, DMT_BOOL, get_vlf_persistent, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*************************************************************
+ * INIT
+/*************************************************************/
+inline int init_process_args(struct process_args *args, char *pid, char *command, char* size, char* priority, char *cputime, char *state)
+{
+ args->pid = pid;
+ args->command= command;
+ args->size= size;
+ args->priority= priority;
+ args->state= state;
+ args->cputime= cputime;
+ return 0;
+}
+
+
+/*
+ *DeviceInfo. functions
+ */
+char *get_deviceid_manufacturer()
+{
+ char *v;
+ dmuci_get_option_value_string("cwmp","cpe","manufacturer", &v);
+ return v;
+}
+
+char *get_deviceid_manufactureroui()
+{
+ char *v;
+ char str[16];
+ char *mac = NULL;
+ json_object *res;
+ FILE *nvrammac=NULL;
+ char macreadfile[18]={0};
+
+ dmuci_get_option_value_string("cwmp", "cpe", "override_oui", &v);
+ if (v[0] == '\0')
+ {
+ dmubus_call("router.system", "info", UBUS_ARGS{{}}, 0, &res);
+ if(!(res)){
+ db_get_value_string("hw", "board", "BaseMacAddr", &mac);
+ if(!mac || strlen(mac)==0 ){
+ if ((nvrammac = fopen("/proc/nvram/BaseMacAddr", "r")) == NULL)
+ {
+ mac = NULL;
+ }
+ else{
+ fscanf(nvrammac,"%[^\n]", macreadfile);
+ macreadfile[17]='\0';
+ sscanf(macreadfile,"%2c %2c %2c", str, str+2, str+4);
+ str[6]='\0';
+ v = dmstrdup(str); // MEM WILL BE FREED IN DMMEMCLEAN
+ fclose(nvrammac);
+ return v;
+ }
+ }
+ }
+ else
+ mac = dm_ubus_get_value(res, 2, "system", "basemac");
+
+ if(mac)
+ {
+ size_t ln = strlen(mac);
+ if (ln<17) goto not_found;
+ sscanf (mac,"%2c:%2c:%2c",str,str+2,str+4);
+ str[6] = '\0';
+ v = dmstrdup(str); // MEM WILL BE FREED IN DMMEMCLEAN
+ return v;
+ }
+ else
+ goto not_found;
+ }
+ return v;
+not_found:
+ v = "";
+ return v;
+}
+
+char *get_deviceid_productclass()
+{
+ char *v, *tmp, *val;
+ dmuci_get_option_value_string("cwmp", "cpe", "override_productclass", &v);
+ if (v[0] == '\0')
+ {
+ db_get_value_string("hw", "board", "iopVerBoard", &v);
+ tmp = dmstrdup(v);// MEM WILL BE FREED IN DMMEMCLEAN
+ val = tmp;
+ return val;
+ }
+
+ tmp = dmstrdup(v);// MEM WILL BE FREED IN DMMEMCLEAN
+ val = tmp;
+ return val;
+}
+
+
+char *get_deviceid_serialnumber()
+{
+ char *v;
+ db_get_value_string("hw", "board", "serialNumber", &v);
+ return v;
+}
+
+char *get_softwareversion()
+{
+ char *v, *tmp, *val;
+
+ db_get_value_string("hw", "board", "iopVersion", &v);
+ tmp = dmstrdup(v);// MEM WILL BE FREED IN DMMEMCLEAN
+ val = tmp;
+ return val;
+}
+
+/*#Device.DeviceInfo.Manufacturer!UCI:cwmp/cwmp,cpe/manufacturer*/
+int get_device_manufacturer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_deviceid_manufacturer();
+ return 0;
+}
+
+/*#Device.DeviceInfo.ManufacturerOUI!UCI:cwmp/cwmp,cpe/override_oui*/
+int get_device_manufactureroui(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_deviceid_manufactureroui();
+ return 0;
+}
+
+/*#Device.DeviceInfo.ProductClass!UCI:cwmp/cwmp,cpe/override_productclass*/
+int get_device_productclass(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_deviceid_productclass();
+ return 0;
+}
+
+int get_device_serialnumber(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_deviceid_serialnumber();
+ return 0;
+}
+
+int get_device_softwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_softwareversion();
+ return 0;
+}
+
+int get_device_hardwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ db_get_value_string("hw", "board", "hardwareVersion", value);
+ return 0;
+}
+
+int get_device_routermodel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ db_get_value_string("hw", "board", "routerModel", value);
+ return 0;
+}
+
+int get_device_info_uptime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ FILE* fp = NULL;
+ char *pch, *spch;
+ char buf[64];
+ *value = "0";
+
+ fp = fopen(UPTIME, "r");
+ if (fp != NULL) {
+ fgets(buf, 64, fp);
+ pch = strtok_r(buf, ".", &spch);
+ if (pch)
+ *value = dmstrdup(pch); // MEM WILL BE FREED IN DMMEMCLEAN
+ fclose(fp);
+ }
+ return 0;
+}
+
+int get_device_devicelog(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "";
+ int i = 0, nbrlines = 4;
+ char buff[512], *msg = NULL;
+ int len = klogctl(3 , buff, sizeof(buff) - 1); /* read ring buffer */
+ if (len <= 0)
+ return 0;
+ buff[len] = '\0';
+ char *p = buff;
+ while (*p) { //TODO to optimize, we can avoid this if the '<' and '>' does not cause problem in the tests.
+ if (*p == '<') {
+ *p = '(';
+ if (p == buff || *(p-1) == '\n') {
+ if(msg == NULL) msg = p;
+ i++;
+ if (i == nbrlines) {
+ *(p-1) = '\0';
+ break;
+ }
+ }
+ }
+ else if (*p == '>')
+ *p = ')';
+ p++;
+ }
+ if(msg == NULL)
+ *value = "";
+ else
+ *value = dmstrdup(msg);// MEM WILL BE FREED IN DMMEMCLEAN
+ return 0;
+}
+
+int get_device_specversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1.0";
+ return 0;
+}
+
+/*#Device.DeviceInfo.ProvisioningCode!UCI:cwmp/cwmp,cpe/provisioning_code*/
+int get_device_provisioningcode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "cpe", "provisioning_code", value);
+ return 0;
+}
+
+int set_device_provisioningcode(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp", "cpe", "provisioning_code", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_base_mac_addr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("router.system", "info", UBUS_ARGS{{}}, 0, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dm_ubus_get_value(res, 2, "system", "basemac");
+ return 0;
+}
+
+int get_device_memory_bank(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("router.system", "memory_bank", UBUS_ARGS{{}}, 0, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dm_ubus_get_value(res, 1, "code");
+ return 0;
+}
+
+int set_device_memory_bank(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmubus_call_set("router.system", "memory_bank", UBUS_ARGS{{"bank", value, Integer}}, 1);
+ return 0;
+ }
+ return 0;
+}
+
+int get_catv_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *catv;
+ dmuci_get_option_value_string("catv", "catv", "enable", &catv);
+ if (strcmp(catv, "on") == 0) {
+ *value = "1";
+ }
+ else
+ *value = "0";
+ return 0;
+}
+
+int set_device_catvenabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ char *stat;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b)
+ stat = "on";
+ else
+ stat = "off";
+ dmuci_set_value("catv", "catv", "enable", stat);
+ return 0;
+ }
+ return 0;
+}
+
+int get_catv_optical_input_level(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ char *str;
+ *value = "";
+ dmubus_call("catv", "vpd", UBUS_ARGS{}, 0, &res);
+ if (!res)
+ return 0;
+ *value = dm_ubus_get_value(res, 1, "VPD");
+ return 0;
+}
+
+int get_catv_rf_output_level(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ char *str;
+ *value = "";
+ dmubus_call("catv", "rf", UBUS_ARGS{}, 0, &res);
+ if (!res)
+ return 0;
+ *value = dm_ubus_get_value(res, 1, "RF");
+ return 0;
+}
+
+int get_catv_temperature(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ char *str;
+ *value = "";
+ dmubus_call("catv", "temp", UBUS_ARGS{}, 0, &res);
+ if (!res)
+ return 0;
+ *value = dm_ubus_get_value(res, 1, "Temperature");
+ return 0;
+}
+
+int get_catv_voltage(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ char *str;
+ *value = "";
+ dmubus_call("catv", "vcc", UBUS_ARGS{}, 0, &res);
+ if (!res)
+ return 0;
+ *value = dm_ubus_get_value(res, 1, "VCC");
+ return 0;
+}
+
+int get_vcf_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *vcf_sec = (struct uci_section *)data;
+ dmuci_get_value_by_section_string(vcf_sec, "name", value);
+ return 0;
+}
+
+int get_vcf_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *vcf_sec = (struct uci_section *)data;
+ dmuci_get_value_by_section_string(vcf_sec, "version", value);
+ return 0;
+}
+
+int get_vcf_date(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ DIR *dir;
+ struct dirent *d_file;
+ struct stat attr;
+ char path[128];
+ char date[sizeof "AAAA-MM-JJTHH:MM:SS.000Z"];
+ struct uci_section *vcf_sec = (struct uci_section *)data;
+ *value = "";
+ dmuci_get_value_by_section_string(vcf_sec, "name", value);
+ if ((dir = opendir (DEFAULT_CONFIG_DIR)) != NULL) {
+ while ((d_file = readdir (dir)) != NULL) {
+ if(strcmp(*value, d_file->d_name) == 0) {
+ sprintf(path, DEFAULT_CONFIG_DIR"%s", d_file->d_name);
+ stat(path, &attr);
+ strftime(date, sizeof date, "%Y-%m-%dT%H:%M:%S.000Z", localtime(&attr.st_mtime));
+ *value = dmstrdup(date);
+ }
+ }
+ closedir (dir);
+ }
+ return 0;
+}
+
+int get_vcf_backup_restore(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *vcf_sec = (struct uci_section *)data;
+ dmuci_get_value_by_section_string(vcf_sec, "backup_restore", value);
+ return 0;
+}
+
+int get_vcf_desc(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *vcf_sec = (struct uci_section *)data;
+ dmuci_get_value_by_section_string(vcf_sec, "description", value);
+ return 0;
+}
+
+int get_vcf_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *vcf_sec = (struct uci_section *)data;
+ dmuci_get_value_by_section_string(vcf_sec, "vcf_alias", value);
+ return 0;
+}
+
+int set_vcf_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *vcf_sec = (struct uci_section *)data;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(vcf_sec, "vcf_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int lookup_vcf_name(char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ uci_path_foreach_option_eq(icwmpd, DMMAP, "vcf", "vcf_instance", instance, s) {
+ dmuci_get_value_by_section_string(s, "name", value);
+ }
+ return 0;
+}
+
+int check_file_dir(char *name)
+{
+ DIR *dir;
+ struct dirent *d_file;
+ if ((dir = opendir (DEFAULT_CONFIG_DIR)) != NULL) {
+ while ((d_file = readdir (dir)) != NULL) {
+ if(strcmp(name, d_file->d_name) == 0) {
+ closedir(dir);
+ return 1;
+ }
+ }
+ closedir(dir);
+ }
+ return 0;
+}
+
+int get_vlf_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *sys_log_sec = (struct uci_section *)data;
+ dmuci_get_value_by_section_string(sys_log_sec, "vlf_alias", value);
+ return 0;
+}
+
+int set_vlf_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *sys_log_sec = (struct uci_section *)data;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(sys_log_sec, "vlf_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_vlf_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *sys_log_sec = (struct uci_section *)data;
+ dmuci_get_value_by_section_string(sys_log_sec, "log_file", value);
+ return 0;
+}
+
+int get_vlf_max_size (char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *sys_log_sec = (struct uci_section *)data;
+ dmuci_get_value_by_section_string(sys_log_sec, "log_size", value);
+ *value = (**value) ? *value : "0";
+ return 0;
+}
+
+int get_vlf_persistent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ return 0;
+}
+
+/*#Device.DeviceInfo.MemoryStatus.Total!UBUS:router.system/info//memoryKB.total*/
+int get_memory_status_total(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ json_object *res;
+
+ dmubus_call("router.system", "info", UBUS_ARGS{{}}, 0, &res);
+ *value = dm_ubus_get_value(res, 2, "memoryKB", "total");
+ return 0;
+}
+
+/*#Device.DeviceInfo.MemoryStatus.Free!UBUS:router.system/info//memoryKB.free*/
+int get_memory_status_free(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ json_object *res;
+
+ dmubus_call("router.system", "info", UBUS_ARGS{{}}, 0, &res);
+ *value = dm_ubus_get_value(res, 2, "memoryKB", "free");
+ return 0;
+}
+
+/*#Device.DeviceInfo.ProcessStatus.CPUUsage!UBUS:router.system/info//system.cpu_per*/
+int get_process_cpu_usage(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ json_object *res;
+
+ dmubus_call("router.system", "info", UBUS_ARGS{{}}, 0, &res);
+ *value = dm_ubus_get_value(res, 2, "system", "cpu_per");
+ return 0;
+}
+
+int get_process_number_of_entries(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ json_object *res, *processes;
+ int nbre_process = 0;
+
+ dmubus_call("router.system", "processes", UBUS_ARGS{{}}, 0, &res);
+ processes = json_object_object_get(res, "processes");
+ nbre_process= json_object_array_length(processes);
+ dmasprintf(value,"%d",nbre_process);
+ return 0;
+}
+
+int get_process_pid(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct process_args *proc_args= (struct process_args*) data;
+ *value= proc_args->pid;
+ return 0;
+}
+
+int get_process_command(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct process_args *proc_args= (struct process_args*) data;
+ *value= proc_args->command;
+ return 0;
+}
+
+int get_process_size(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct process_args *proc_args= (struct process_args*) data;
+ if(proc_args->size!=NULL) *value= proc_args->size;
+ else *value= "0";
+ return 0;
+}
+
+int get_process_priority(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct process_args *proc_args= (struct process_args*) data;
+ long val;
+
+ if(proc_args->priority!=NULL) {
+ val = atol(proc_args->priority);
+ if(val<0) val=0;
+ dmasprintf(value, "%ld", val);
+ }
+ else *value= "0";
+ return 0;
+}
+
+int get_process_cpu_time(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct process_args *proc_args= (struct process_args*) data;
+ if(proc_args->cputime!=NULL) *value= proc_args->cputime;
+ return 0;
+}
+
+int get_process_state(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct process_args *proc_args= (struct process_args*) data;
+ if(strchr(proc_args->state, 'S')!=NULL) *value="Sleeping";
+ else if(strchr(proc_args->state, 'R')!=NULL) *value= "Running";
+ else if(strchr(proc_args->state, 'T')!=NULL) *value= "Stopped";
+ else if(strchr(proc_args->state, 'D')!=NULL) *value= "Uninterruptible";
+ else if(strchr(proc_args->state, 'Z')!=NULL) *value= "Zombie";
+ else *value= proc_args->state;
+
+ return 0;
+}
+
+int browsePocessEntriesInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance){
+ json_object *res, *processes, *fields, *process;
+ char *pid_field, *command_field, *state_field, *mem_size_field, *cpu_time_field, *priority_field, *pid, *command, *mem_size, *state, *cpu_time, *priority, *idx, *idx_last= NULL;
+ int i, id=0;
+ struct process_args proc_args={};
+
+ dmubus_call("router.system", "processes", UBUS_ARGS{{}}, 0, &res);
+ fields = json_object_object_get(res, "fields");
+ processes = json_object_object_get(res, "processes");
+ size_t nbre_process = json_object_array_length(processes);
+ pid_field = (char *)dmjson_get_value_in_array_idx(fields, 0, 0, NULL);
+ command_field = (char *)dmjson_get_value_in_array_idx(fields, 7, 0, NULL);
+ state_field = (char *)dmjson_get_value_in_array_idx(fields, 3, 0, NULL);
+ mem_size_field = (char *)dmjson_get_value_in_array_idx(fields, 4, 0, NULL);
+ priority_field = (char *)dmjson_get_value_in_array_idx(fields, 8, 0, NULL);
+ cpu_time_field = (char *)dmjson_get_value_in_array_idx(fields, 9, 0, NULL);
+
+ if(nbre_process>0){
+ for(i=0; id_name[0] == '.')
+ continue;
+ update_section_list(DMMAP,"vcf", "name", 1, d_file->d_name, NULL, NULL, "backup_restore", "1");
+ }
+ closedir (dir);
+ }
+ uci_path_foreach_sections(icwmpd, DMMAP, "vcf", s) {
+ dmuci_get_value_by_section_string(s, "name", &name);
+ if(del_sec) {
+ DMUCI_DELETE_BY_SECTION(icwmpd, del_sec, NULL, NULL);
+ del_sec = NULL;
+ }
+ if (check_file_dir(name) == 0) {
+ del_sec = s;
+ continue;
+ }
+ vcf = handle_update_instance(1, dmctx, &vcf_last, update_instance_alias_icwmpd, 3, s, "vcf_instance", "vcf_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, vcf) == DM_STOP)
+ break;
+ }
+ if(del_sec)
+ DMUCI_DELETE_BY_SECTION(icwmpd, del_sec, NULL, NULL);
+ return 0;
+}
+
+//Browse VendorLogFile instances
+int browseVlfInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *sys_log_sec, *s, *dm_sec, *del_sec=NULL;
+ char *instance, *last_instance, *log_file,*log_size, *add_value, *lfile;
+ int i=1, n=0;
+ uci_foreach_sections("system", "system", sys_log_sec) {
+ if(!sys_log_sec)
+ break;
+ dmuci_get_value_by_section_string(sys_log_sec, "log_file", &log_file);
+ dmuci_get_value_by_section_string(sys_log_sec, "log_size", &log_size);
+ uci_path_foreach_sections(icwmpd, "dmmap", "vlf", dm_sec) {
+ if(dm_sec)
+ break;
+ }
+ if(!dm_sec){
+ update_section_list(DMMAP,"vlf", NULL, i++, NULL, "log_file", log_file, "log_size", log_size);
+ }
+ else{
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dm_sec, "log_file", log_file);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dm_sec, "log_size", log_size);
+ }
+ }
+ uci_path_foreach_sections(icwmpd, "dmmap", "vlf", dm_sec) {
+ instance = handle_update_instance(1, dmctx, &last_instance, update_instance_alias_icwmpd, 3, dm_sec, "vlf_instance", "vlf_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)dm_sec, instance) == DM_STOP){
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/dmtree/tr181/deviceinfo.h b/dmtree/tr181/deviceinfo.h
new file mode 100644
index 00000000..41539d58
--- /dev/null
+++ b/dmtree/tr181/deviceinfo.h
@@ -0,0 +1,96 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2012-2014 PIVA SOFTWARE (www.pivasoftware.com)
+ * Author: Imen Bhiri
+ * Author: Feten Besbes
+ * Author: Anis Ellouze
+ */
+
+#ifndef __DEVICE_INFO_H
+#define __DEVICE_INFO_H
+#include "dmcwmp.h"
+
+#define UPTIME "/proc/uptime"
+#define DEFAULT_CONFIG_DIR "/etc/config/"
+extern DMLEAF tDeviceInfoParams[];
+extern DMLEAF tCatTvParams[];
+extern DMLEAF tDeviceInfoVendorConfigFileParams[];
+extern DMLEAF tDeviceInfoVendorLogFileParams[];
+extern DMLEAF tDeviceInfoMemoryStatusParams[];
+extern DMOBJ tDeviceInfoProcessStatusObj[];
+extern DMLEAF tDeviceInfoProcessStatusParams[];
+extern DMOBJ tDeviceInfoObj[];
+extern DMLEAF tDeviceInfoProcessStatusProcessParams[];
+
+struct process_args{
+ char *pid;
+ char *command;
+ char* size;
+ char* priority;
+ char *cputime;
+ char *state;
+};
+
+char *get_deviceid_manufacturer();
+char *get_deviceid_manufactureroui();
+char *get_deviceid_productclass();
+char *get_deviceid_serialnumber();
+char *get_softwareversion();
+int lookup_vcf_name(char *instance, char **value);
+
+int browseVcfInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseVlfInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browsePocessEntriesInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int get_device_manufacturer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_manufactureroui(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_routermodel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_productclass(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_serialnumber(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_hardwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_softwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_info_uptime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_devicelog(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_specversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_provisioningcode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_base_mac_addr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_catv_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_device_memory_bank(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_catv_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_catv_optical_input_level(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_catv_rf_output_level(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_catv_temperature(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_catv_voltage(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_vcf_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_vcf_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_vcf_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_vcf_date(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_vcf_desc(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_vcf_backup_restore(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_vlf_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_vlf_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_vlf_max_size(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_vlf_persistent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_memory_status_total(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_memory_status_free(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_process_cpu_usage(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_process_number_of_entries(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_process_pid(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_process_command(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_process_size(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_process_priority(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_process_cpu_time(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_process_state(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int set_device_provisioningcode(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_device_catvenabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_device_memory_bank(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_device_catvenabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_vcf_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_vlf_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+#endif
diff --git a/dmtree/tr181/dhcpv4.c b/dmtree/tr181/dhcpv4.c
new file mode 100644
index 00000000..41935a3a
--- /dev/null
+++ b/dmtree/tr181/dhcpv4.c
@@ -0,0 +1,3445 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2016 Inteno Broadband Technology AB
+ * Author: Anis Ellouze
+ * Author: Omar Kallel
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcwmp.h"
+#include "dmcommon.h"
+#include "dhcpv4.h"
+#include "dmjson.h"
+#include "dmentry.h"
+#define DELIMITOR ","
+
+/*** DHCPv4. ***/
+DMOBJ tDhcpv4Obj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Client", &DMWRITE, addObjDHCPv4Client, delObjDHCPv4Client, NULL, browseDHCPv4ClientInst, NULL, NULL, tDHCPv4ClientObj, tDHCPv4ClientParams, NULL, BBFDM_BOTH},
+{"Server", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDhcpv4ServerObj, tDHCPv4ServerParams, NULL, BBFDM_BOTH},
+{"Relay", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDHCPv4RelayObj, tDHCPv4RelayParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDHCPv4Params[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"ClientNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv4_ClientNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv4.Client.{i}. *** */
+DMOBJ tDHCPv4ClientObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"SentOption", &DMWRITE, addObjDHCPv4ClientSentOption, delObjDHCPv4ClientSentOption, NULL, browseDHCPv4ClientSentOptionInst, NULL, NULL, NULL, tDHCPv4ClientSentOptionParams, NULL, BBFDM_BOTH},
+{"ReqOption", &DMWRITE, addObjDHCPv4ClientReqOption, delObjDHCPv4ClientReqOption, NULL, browseDHCPv4ClientReqOptionInst, NULL, NULL, NULL, tDHCPv4ClientReqOptionParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDHCPv4ClientParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv4Client_Enable, set_DHCPv4Client_Enable, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DHCPv4Client_Alias, set_DHCPv4Client_Alias, NULL, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_DHCPv4Client_Interface, set_DHCPv4Client_Interface, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_DHCPv4Client_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"DHCPStatus", &DMREAD, DMT_STRING, get_DHCPv4Client_DHCPStatus, NULL, NULL, NULL, BBFDM_BOTH},
+{"Renew", &DMWRITE, DMT_BOOL, get_DHCPv4Client_Renew, set_DHCPv4Client_Renew, NULL, NULL, BBFDM_BOTH},
+{"IPAddress", &DMREAD, DMT_STRING, get_DHCPv4Client_IPAddress, NULL, NULL, NULL, BBFDM_BOTH},
+{"SubnetMask", &DMREAD, DMT_STRING, get_DHCPv4Client_SubnetMask, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPRouters", &DMREAD, DMT_STRING, get_DHCPv4Client_IPRouters, NULL, NULL, NULL, BBFDM_BOTH},
+{"DNSServers", &DMREAD, DMT_STRING, get_DHCPv4Client_DNSServers, NULL, NULL, NULL, BBFDM_BOTH},
+{"LeaseTimeRemaining", &DMREAD, DMT_INT, get_DHCPv4Client_LeaseTimeRemaining, NULL, NULL, NULL, BBFDM_BOTH},
+{"DHCPServer", &DMREAD, DMT_STRING, get_DHCPv4Client_DHCPServer, NULL, NULL, NULL, BBFDM_BOTH},
+{"PassthroughEnable", &DMWRITE, DMT_BOOL, get_DHCPv4Client_PassthroughEnable, set_DHCPv4Client_PassthroughEnable, NULL, NULL, BBFDM_BOTH},
+{"PassthroughDHCPPool", &DMWRITE, DMT_STRING, get_DHCPv4Client_PassthroughDHCPPool, set_DHCPv4Client_PassthroughDHCPPool, NULL, NULL, BBFDM_BOTH},
+{"SentOptionNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv4Client_SentOptionNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"ReqOptionNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv4Client_ReqOptionNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv4.Client.{i}.SentOption.{i}. *** */
+DMLEAF tDHCPv4ClientSentOptionParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv4ClientSentOption_Enable, set_DHCPv4ClientSentOption_Enable, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DHCPv4ClientSentOption_Alias, set_DHCPv4ClientSentOption_Alias, NULL, NULL, BBFDM_BOTH},
+{"Tag", &DMWRITE, DMT_UNINT, get_DHCPv4ClientSentOption_Tag, set_DHCPv4ClientSentOption_Tag, NULL, NULL, BBFDM_BOTH},
+{"Value", &DMWRITE, DMT_HEXBIN, get_DHCPv4ClientSentOption_Value, set_DHCPv4ClientSentOption_Value, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv4.Client.{i}.ReqOption.{i}. *** */
+DMLEAF tDHCPv4ClientReqOptionParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv4ClientReqOption_Enable, set_DHCPv4ClientReqOption_Enable, NULL, NULL, BBFDM_BOTH},
+{"Order", &DMWRITE, DMT_UNINT, get_DHCPv4ClientReqOption_Order, set_DHCPv4ClientReqOption_Order, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DHCPv4ClientReqOption_Alias, set_DHCPv4ClientReqOption_Alias, NULL, NULL, BBFDM_BOTH},
+{"Tag", &DMWRITE, DMT_UNINT, get_DHCPv4ClientReqOption_Tag, set_DHCPv4ClientReqOption_Tag, NULL, NULL, BBFDM_BOTH},
+{"Value", &DMREAD, DMT_HEXBIN, get_DHCPv4ClientReqOption_Value, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDHCPv4ServerParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv4Server_Enable, set_DHCPv4Server_Enable, NULL, NULL, BBFDM_BOTH},
+{"PoolNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv4Server_PoolNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** DHCPv4.Server. ***/
+DMOBJ tDhcpv4ServerObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Pool", &DMWRITE, add_dhcp_server, delete_dhcp_server, NULL, browseDhcpInst, NULL, NULL, tDhcpServerPoolObj, tDhcpServerPoolParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** DHCPv4.Server.Pool.{i}. ***/
+DMOBJ tDhcpServerPoolObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"StaticAddress", &DMWRITE, add_dhcp_staticaddress, delete_dhcp_staticaddress, NULL, browseDhcpStaticInst, NULL, NULL, NULL, tDhcpServerPoolAddressParams, NULL, BBFDM_BOTH},
+{"Option", &DMWRITE, addObjDHCPv4ServerPoolOption, delObjDHCPv4ServerPoolOption, NULL, browseDHCPv4ServerPoolOptionInst, NULL, NULL, NULL, tDHCPv4ServerPoolOptionParams, NULL, BBFDM_BOTH},
+{"Client", &DMREAD, NULL, NULL, NULL, browseDhcpClientInst, NULL, NULL, tDhcpServerPoolClientObj, tDhcpServerPoolClientParams, get_dhcp_client_linker},
+{0}
+};
+
+/*** DHCPv4.Server.Pool.{i}.Client.{i}. ***/
+DMOBJ tDhcpServerPoolClientObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"IPv4Address", &DMREAD, NULL, NULL, NULL, browseDhcpClientIPv4Inst, NULL, NULL, NULL, tDhcpServerPoolClientIPv4AddressParams, NULL, BBFDM_BOTH},
+{"Option", &DMREAD, NULL, NULL, NULL, browseDHCPv4ServerPoolClientOptionInst, NULL, NULL, NULL, tDHCPv4ServerPoolClientOptionParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDhcpServerPoolParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_server_pool_alias, set_server_pool_alias, NULL, NULL, BBFDM_BOTH},
+{"DNSServers", &DMWRITE, DMT_STRING, get_dns_server, set_dns_server, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_dhcp_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Order", &DMWRITE, DMT_UNINT, get_dhcp_sever_pool_order, set_dhcp_sever_pool_order, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"DHCPServerConfigurable", &DMWRITE, DMT_BOOL, get_dhcp_configurable, set_dhcp_configurable, NULL, NULL, BBFDM_BOTH},
+{"Enable", &DMWRITE, DMT_BOOL, get_dhcp_enable, set_dhcp_enable, NULL, NULL, BBFDM_BOTH},
+{"MinAddress", &DMWRITE, DMT_STRING, get_dhcp_interval_address_min, set_dhcp_address_min, NULL, NULL, BBFDM_BOTH},
+{"MaxAddress", &DMWRITE, DMT_STRING,get_dhcp_interval_address_max, set_dhcp_address_max, NULL, NULL, BBFDM_BOTH},
+{"ReservedAddresses", &DMWRITE, DMT_STRING, get_dhcp_reserved_addresses, set_dhcp_reserved_addresses, NULL, NULL, BBFDM_BOTH},
+{"SubnetMask", &DMWRITE, DMT_STRING,get_dhcp_subnetmask, set_dhcp_subnetmask, NULL, NULL, BBFDM_BOTH},
+{"IPRouters", &DMWRITE, DMT_STRING, get_dhcp_iprouters, set_dhcp_iprouters, NULL, NULL, BBFDM_BOTH},
+{"LeaseTime", &DMWRITE, DMT_INT, get_dhcp_leasetime, set_dhcp_leasetime, NULL, NULL, BBFDM_BOTH},
+{"DomainName", &DMWRITE, DMT_STRING, get_dhcp_domainname, set_dhcp_domainname, NULL, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_dhcp_interface, set_dhcp_interface_linker_parameter, NULL, NULL, BBFDM_BOTH},
+{"StaticAddressNumberOfEntries", &DMWRITE, DMT_UNINT, get_static_address_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"OptionNumberOfEntries", &DMWRITE, DMT_UNINT, get_option_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"ClientNumberOfEntries", &DMWRITE, DMT_UNINT, get_clients_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** DHCPv4.Server.Pool.{i}.StaticAddress.{i}. ***/
+DMLEAF tDhcpServerPoolAddressParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_dhcp_static_alias, set_dhcp_static_alias, NULL, NULL, BBFDM_BOTH},
+{"Chaddr", &DMWRITE, DMT_STRING, get_dhcp_staticaddress_chaddr, set_dhcp_staticaddress_chaddr, NULL, NULL, BBFDM_BOTH},
+{"Yiaddr", &DMWRITE, DMT_STRING, get_dhcp_staticaddress_yiaddr, set_dhcp_staticaddress_yiaddr, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** DHCPv4.Server.Pool.{i}.Client.{i}. ***/
+DMLEAF tDhcpServerPoolClientParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Chaddr", &DMREAD, DMT_STRING, get_dhcp_client_chaddr, NULL, NULL, NULL, BBFDM_BOTH},
+{"Active", &DMREAD, DMT_STRING, get_dhcp_client_active, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*** DHCPv4.Server.Pool.{i}.Client.{i}.IPv4Address.{i}. ***/
+DMLEAF tDhcpServerPoolClientIPv4AddressParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"LeaseTimeRemaining", &DMREAD, DMT_TIME, get_dhcp_client_ipv4address_leasetime, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPAddress", &DMREAD, DMT_TIME, get_dhcp_client_ipv4address_ip_address, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv4.Server.Pool.{i}.Option.{i}. *** */
+DMLEAF tDHCPv4ServerPoolOptionParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv4ServerPoolOption_Enable, set_DHCPv4ServerPoolOption_Enable, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DHCPv4ServerPoolOption_Alias, set_DHCPv4ServerPoolOption_Alias, NULL, NULL, BBFDM_BOTH},
+{"Tag", &DMWRITE, DMT_UNINT, get_DHCPv4ServerPoolOption_Tag, set_DHCPv4ServerPoolOption_Tag, NULL, NULL, BBFDM_BOTH},
+{"Value", &DMWRITE, DMT_HEXBIN, get_DHCPv4ServerPoolOption_Value, set_DHCPv4ServerPoolOption_Value, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv4.Server.Pool.{i}.Client.{i}.Option.{i}. *** */
+DMLEAF tDHCPv4ServerPoolClientOptionParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Tag", &DMREAD, DMT_UNINT, get_DHCPv4ServerPoolClientOption_Tag, NULL, NULL, NULL, BBFDM_BOTH},
+{"Value", &DMREAD, DMT_HEXBIN, get_DHCPv4ServerPoolClientOption_Value, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv4.Relay. *** */
+DMOBJ tDHCPv4RelayObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker*/
+{"Forwarding", &DMWRITE, addObjDHCPv4RelayForwarding, delObjDHCPv4RelayForwarding, NULL, browseDHCPv4RelayForwardingInst, NULL, NULL, NULL, tDHCPv4RelayForwardingParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDHCPv4RelayParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv4Relay_Enable, set_DHCPv4Relay_Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_DHCPv4Relay_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"ForwardingNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv4Relay_ForwardingNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+/* *** Device.DHCPv4.Relay.Forwarding.{i}. *** */
+DMLEAF tDHCPv4RelayForwardingParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv4RelayForwarding_Enable, set_DHCPv4RelayForwarding_Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_DHCPv4RelayForwarding_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DHCPv4RelayForwarding_Alias, set_DHCPv4RelayForwarding_Alias, NULL, NULL, BBFDM_BOTH},
+{"Order", &DMWRITE, DMT_UNINT, get_DHCPv4RelayForwarding_Order, set_DHCPv4RelayForwarding_Order, NULL, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_DHCPv4RelayForwarding_Interface, set_DHCPv4RelayForwarding_Interface, NULL, NULL, BBFDM_BOTH},
+{"VendorClassID", &DMWRITE, DMT_STRING, get_DHCPv4RelayForwarding_VendorClassID, set_DHCPv4RelayForwarding_VendorClassID, NULL, NULL, BBFDM_BOTH},
+{"VendorClassIDExclude", &DMWRITE, DMT_BOOL, get_DHCPv4RelayForwarding_VendorClassIDExclude, set_DHCPv4RelayForwarding_VendorClassIDExclude, NULL, NULL, BBFDM_BOTH},
+{"VendorClassIDMode", &DMWRITE, DMT_STRING, get_DHCPv4RelayForwarding_VendorClassIDMode, set_DHCPv4RelayForwarding_VendorClassIDMode, NULL, NULL, BBFDM_BOTH},
+{"ClientID", &DMWRITE, DMT_HEXBIN, get_DHCPv4RelayForwarding_ClientID, set_DHCPv4RelayForwarding_ClientID, NULL, NULL, BBFDM_BOTH},
+{"ClientIDExclude", &DMWRITE, DMT_BOOL, get_DHCPv4RelayForwarding_ClientIDExclude, set_DHCPv4RelayForwarding_ClientIDExclude, NULL, NULL, BBFDM_BOTH},
+{"UserClassID", &DMWRITE, DMT_HEXBIN, get_DHCPv4RelayForwarding_UserClassID, set_DHCPv4RelayForwarding_UserClassID, NULL, NULL, BBFDM_BOTH},
+{"UserClassIDExclude", &DMWRITE, DMT_BOOL, get_DHCPv4RelayForwarding_UserClassIDExclude, set_DHCPv4RelayForwarding_UserClassIDExclude, NULL, NULL, BBFDM_BOTH},
+{"Chaddr", &DMWRITE, DMT_STRING, get_DHCPv4RelayForwarding_Chaddr, set_DHCPv4RelayForwarding_Chaddr, NULL, NULL, BBFDM_BOTH},
+{"ChaddrMask", &DMWRITE, DMT_STRING, get_DHCPv4RelayForwarding_ChaddrMask, set_DHCPv4RelayForwarding_ChaddrMask, NULL, NULL, BBFDM_BOTH},
+{"ChaddrExclude", &DMWRITE, DMT_BOOL, get_DHCPv4RelayForwarding_ChaddrExclude, set_DHCPv4RelayForwarding_ChaddrExclude, NULL, NULL, BBFDM_BOTH},
+{"LocallyServed", &DMWRITE, DMT_BOOL, get_DHCPv4RelayForwarding_LocallyServed, set_DHCPv4RelayForwarding_LocallyServed, NULL, NULL, BBFDM_BOTH},
+{"DHCPServerIPAddress", &DMWRITE, DMT_STRING, get_DHCPv4RelayForwarding_DHCPServerIPAddress, set_DHCPv4RelayForwarding_DHCPServerIPAddress, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/**************************************************************************
+* LINKER
+***************************************************************************/
+int get_dhcp_client_linker(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker) {
+ if (data && ((struct client_args *)data)->key) {
+ *linker = ((struct client_args *)data)->key;
+ return 0;
+ } else {
+ *linker = "";
+ return 0;
+ }
+}
+
+/*************************************************************
+ * INIT
+/*************************************************************/
+inline int init_dhcp_args(struct dhcp_args *args, struct uci_section *s, char *interface)
+{
+ args->interface = interface;
+ args->dhcp_sec = s;
+ return 0;
+}
+inline int init_args_dhcp_host(struct dhcp_static_args *args, struct uci_section *s)
+{
+ args->dhcpsection = s;
+ return 0;
+}
+
+inline int init_dhcp_client_args(struct client_args *args, json_object *client, char *key)
+{
+ args->client = client;
+ args->key = key;
+ return 0;
+}
+
+/*************************************************************
+ * Other functions
+/*************************************************************/
+struct uci_section* exist_other_section_same_order(struct uci_section *dmmap_sect, char * package, char* sect_type, char *order) {
+ struct uci_section *s;
+ uci_path_foreach_option_eq(icwmpd, package, sect_type, "order", order, s) {
+ if(strcmp(section_name(s), section_name(dmmap_sect)) != 0){
+ return s;
+ }
+ }
+ return NULL;
+}
+
+int set_section_order(char *package, char *dmpackage, char* sect_type, struct uci_section *dmmap_sect, struct uci_section *conf, int set_force, char* order)
+{
+ char *v= NULL, *sect_name, *incrorder;
+ struct uci_section *s, *dm;
+ dmuci_get_value_by_section_string(dmmap_sect, "order", &v);
+ if((v!=NULL || strlen(v)>0) && strcmp(v, order) == 0)
+ return 0;
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "order", order);
+ if(conf==NULL){
+ dmuci_get_value_by_section_string(dmmap_sect, "section_name", §_name);
+ get_config_section_of_dmmap_section(package, sect_type, sect_name, &s);
+ } else
+ s= conf;
+
+ if(strcmp(order, "1") != 0 && s!=NULL){
+ dmuci_set_value_by_section(s, "force", "");
+ }
+
+ if(set_force==1 && strcmp(order, "1") == 0 && s!=NULL) {
+ dmuci_set_value_by_section(s, "force", "1");
+ }
+
+ if ((dm = exist_other_section_same_order(dmmap_sect, dmpackage, sect_type, order)) != NULL) {
+ dmuci_get_value_by_section_string(dm, "section_name", §_name);
+ get_config_section_of_dmmap_section(package, sect_type, sect_name, &s);
+ dmasprintf(&incrorder, "%d", atoi(order)+1);
+ if(s!=NULL && strcmp(order, "1") == 0){
+ dmuci_set_value_by_section(s, "force", "");
+ }
+ set_section_order(package, dmpackage, sect_type, dm, s, set_force, incrorder);
+ }
+ return 0;
+
+}
+
+/*******************ADD-DEL OBJECT*********************/
+int add_dhcp_server(char *refparam, struct dmctx *ctx, void *data, char **instancepara)
+{
+ char *value, *v;
+ char *instance;
+ struct uci_section *s = NULL, *dmmap_dhcp= NULL;
+
+ check_create_dmmap_package("dmmap_dhcp");
+ instance = get_last_instance_icwmpd("dmmap_dhcp", "dhcp", "dhcp_instance");
+ dmuci_add_section("dhcp", "dhcp", &s, &value);
+ dmuci_set_value_by_section(s, "start", "100");
+ dmuci_set_value_by_section(s, "leasetime", "12h");
+ dmuci_set_value_by_section(s, "limit", "150");
+
+ dmuci_add_section_icwmpd("dmmap_dhcp", "dhcp", &dmmap_dhcp, &v);
+ dmuci_set_value_by_section(dmmap_dhcp, "section_name", section_name(s));
+ *instancepara = update_instance_icwmpd(dmmap_dhcp, instance, "dhcp_instance");
+ return 0;
+}
+
+int delete_dhcp_server(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ int found = 0;
+ char *lan_name;
+ struct uci_section *s = NULL;
+ struct uci_section *ss = NULL, *dmmap_section= NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(is_section_unnamed(section_name(((struct dhcp_args *)data)->dhcp_sec))){
+ LIST_HEAD(dup_list);
+ delete_sections_save_next_sections("dmmap_dhcp", "dhcp", "dhcp_instance", section_name(((struct dhcp_args *)data)->dhcp_sec), atoi(instance), &dup_list);
+ update_dmmap_sections(&dup_list, "dhcp_instance", "dmmap_dhcp", "dhcp");
+ dmuci_delete_by_section_unnamed(((struct dhcp_args *)data)->dhcp_sec, NULL, NULL);
+ } else {
+ get_dmmap_section_of_config_section("dmmap_dhcp", "dhcp", section_name(((struct dhcp_args *)data)->dhcp_sec), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section_unnamed_icwmpd(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(((struct dhcp_args *)data)->dhcp_sec, NULL, NULL);
+ }
+
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("dhcp", "dhcp", s) {
+ if (found != 0){
+ get_dmmap_section_of_config_section("dmmap_dhcp", "dhcp", section_name(s), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL){
+ get_dmmap_section_of_config_section("dmmap_dhcp", "dhcp", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ break;
+ }
+ return 0;
+}
+
+int add_dhcp_staticaddress(char *refparam, struct dmctx *ctx, void *data, char **instancepara)
+{
+ char *value, *v;
+ char *instance;
+ struct uci_section *s = NULL, *dmmap_dhcp_host= NULL;
+
+ check_create_dmmap_package("dmmap_dhcp");
+ instance = get_last_instance_lev2_icwmpd("dhcp", "host", "dmmap_dhcp", "ldhcpinstance", "dhcp", ((struct dhcp_args *)data)->interface);
+ dmuci_add_section("dhcp", "host", &s, &value);
+ dmuci_set_value_by_section(s, "dhcp", ((struct dhcp_args *)data)->interface);
+
+
+ dmuci_add_section_icwmpd("dmmap_dhcp", "host", &dmmap_dhcp_host, &v);
+ dmuci_set_value_by_section(dmmap_dhcp_host, "section_name", section_name(s));
+ *instancepara = update_instance_icwmpd(dmmap_dhcp_host, instance, "ldhcpinstance");
+ return 0;
+}
+
+int delete_dhcp_staticaddress(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ int found = 0;
+ char *lan_name;
+ struct uci_section *s = NULL, *dmmap_section = NULL;
+ struct uci_section *ss = NULL;
+ struct dhcp_static_args *dhcpargs = (struct dhcp_static_args *)data;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(is_section_unnamed(section_name(dhcpargs->dhcpsection))){
+ LIST_HEAD(dup_list);
+ delete_sections_save_next_sections("dmmap_dhcp", "host", "ldhcpinstance", section_name(dhcpargs->dhcpsection), atoi(instance), &dup_list);
+ update_dmmap_sections(&dup_list, "ldhcpinstance", "dmmap_dhcp", "host");
+ dmuci_delete_by_section_unnamed(dhcpargs->dhcpsection, NULL, NULL);
+ } else {
+ get_dmmap_section_of_config_section("dmmap_dhcp", "host", section_name(dhcpargs->dhcpsection), &dmmap_section);
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(dhcpargs->dhcpsection, NULL, NULL);
+ }
+
+ break;
+ case DEL_ALL:
+ uci_foreach_option_eq("dhcp", "host", "dhcp", ((struct dhcp_args *)data)->interface, s) {
+ if (found != 0){
+ get_dmmap_section_of_config_section("dmmap_dhcp", "host", section_name(ss), &dmmap_section);
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL){
+ get_dmmap_section_of_config_section("dmmap_dhcp", "host", section_name(ss), &dmmap_section);
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ break;
+ }
+ return 0;
+}
+
+int addObjDHCPv4Client(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ struct uci_section *s, *dmmap_sect;
+ char *wan_eth, *value, *wanname, *instancepara, *v;
+
+ check_create_dmmap_package("dmmap_dhcp_client");
+ instancepara = get_last_instance_icwmpd("dmmap_dhcp_client", "interface", "cwmp_dhcpv4client_instance");
+ dmuci_get_option_value_string("ports", "WAN", "ifname", &wan_eth);
+ dmasprintf(&wanname, "%s.1", wan_eth);
+ dmuci_add_section("network", "interface", &s, &value);
+ dmuci_set_value_by_section(s, "proto", "dhcp");
+ dmuci_set_value_by_section(s, "ifname", wanname);
+ dmuci_set_value_by_section(s, "type", "anywan");
+ dmuci_add_section_icwmpd("dmmap_dhcp_client", "interface", &dmmap_sect, &v);
+ dmuci_set_value_by_section(dmmap_sect, "section_name", section_name(s));
+ *instance = update_instance_icwmpd(dmmap_sect, instancepara, "cwmp_dhcpv4client_instance");
+ return 0;
+}
+
+int delObjDHCPv4Client(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ struct uci_section *s, *dmmap_section, *stmp;
+ json_object *res, *jobj;
+
+ char *v;
+ char *type, *ipv4addr = "", *ipv6addr = "", *proto, *inst, *mask4;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(dhcp_client_args->dhcp_client_conf != NULL){
+ dmuci_set_value_by_section(dhcp_client_args->dhcp_client_conf, "proto", "static");
+ if(strlen(dhcp_client_args->ip) == 0){
+ dmasprintf(&ipv4addr, "%s.%s.%s.%s", instance, instance, instance, instance);
+ dmasprintf(&mask4, "%s", "255.255.255.0");
+ } else {
+ dmasprintf(&ipv4addr, "%s", dhcp_client_args->ip);
+ dmasprintf(&mask4, "%s", dhcp_client_args->mask);
+ }
+ dmuci_set_value_by_section(dhcp_client_args->dhcp_client_conf, "ipaddr", ipv4addr);
+ dmuci_set_value_by_section(dhcp_client_args->dhcp_client_conf, "netmask", mask4);
+ }
+ dmuci_delete_by_section_unnamed_icwmpd(dhcp_client_args->dhcp_client_dm, NULL, NULL);
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if (strcmp(type, "alias") == 0 || strcmp(section_name(s), "loopback")==0)
+ continue;
+ dmuci_get_value_by_section_string(s, "ipaddr", &ipv4addr);
+ dmuci_get_value_by_section_string(s, "netmask", &mask4);
+ if (ipv4addr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(s), String}}, 1, &res);
+ if (res)
+ {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ ipv4addr = dmjson_get_value(jobj, 1, "address");
+ mask4= dmjson_get_value(jobj, 1, "mask");
+ }
+ }
+ dmuci_get_value_by_section_string(s, "ip6addr", &ipv6addr);
+ if (ipv6addr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(s), String}}, 1, &res);
+ if (res)
+ {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv6-address");
+ ipv6addr = dmjson_get_value(jobj, 1, "address");
+ }
+ }
+ dmuci_get_value_by_section_string(s, "proto", &proto);
+ if (ipv4addr[0] == '\0' && ipv6addr[0] == '\0' && strcmp(proto, "dhcp") != 0 && strcmp(proto, "dhcpv6") != 0 && strcmp(type, "bridge") != 0)
+ continue;
+
+ dmuci_set_value_by_section(s, "proto", "static");
+
+ get_dmmap_section_of_config_section("dmmap_dhcp_client", "interface", section_name(s), &dmmap_section);
+ if(strlen(ipv4addr) == 0){
+ if(dmmap_section != NULL)
+ dmuci_get_value_by_section_string(dmmap_section, "cwmp_dhcpv4client_instance", &v);
+ else
+ dmasprintf(&v, "%d", 0);
+
+ dmasprintf(&ipv4addr, "%s.%s.%s.%s", v, v, v, v);
+ dmasprintf(&mask4, "%s", "255.255.255.0");
+ }
+ dmuci_set_value_by_section(s, "ipaddr", ipv4addr);
+ dmuci_set_value_by_section(s, "netmask", mask4);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ }
+ uci_path_foreach_sections_safe(icwmpd, "dmmap_dhcp_client", "interface", stmp, s) {
+ dmuci_delete_by_section_unnamed_icwmpd(s, NULL, NULL);
+ }
+ break;
+ }
+ return 0;
+}
+
+int addObjDHCPv4ClientSentOption(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*) data;
+ struct uci_section *s, *dmmap_sect;
+ char *value, *instancepara, *v;
+
+ check_create_dmmap_package("dmmap_dhcp_client");
+ instancepara= get_last_instance_lev2_icwmpd_dmmap_opt("dmmap_dhcp_client", "send_option", "cwmp_dhcpv4_sentopt_instance", "section_name", section_name(dhcp_client_args->dhcp_client_conf));
+ dmuci_add_section_icwmpd("dmmap_dhcp_client", "send_option", &dmmap_sect, &value);
+ if(dhcp_client_args->dhcp_client_conf != NULL)
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(dhcp_client_args->dhcp_client_conf));
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "option_tag", "0");
+ *instance = update_instance_icwmpd(dmmap_sect, instancepara, "cwmp_dhcpv4_sentopt_instance");
+ return 0;
+}
+
+int delObjDHCPv4ClientSentOption(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *s, *stmp;
+ char *list= NULL, *opt_value= NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(strcmp(((struct dhcp_client_option_args*) data)->option_tag, "0") != 0)
+ {
+ dmasprintf(&opt_value, "%s:%s", ((struct dhcp_client_option_args*) data)->option_tag, ((struct dhcp_client_option_args*) data)->value);
+ dmuci_get_value_by_section_string(((struct dhcp_client_option_args*) data)->client_sect, "sendopts", &list);
+ if(list != NULL){
+ remove_elt_from_str_list(&list, opt_value);
+ dmuci_set_value_by_section(((struct dhcp_client_option_args*) data)->client_sect, "sendopts", list);
+ }
+ }
+ dmuci_delete_by_section_unnamed_icwmpd(((struct dhcp_client_option_args*) data)->opt_sect, NULL, NULL);
+ break;
+ case DEL_ALL:
+ dmuci_set_value_by_section(((struct dhcp_client_args*) data)->dhcp_client_conf, "sendopts", "");
+ uci_path_foreach_sections_safe(icwmpd, "dmmap_dhcp_client", "send_option", stmp, s) {
+ dmuci_delete_by_section_unnamed_icwmpd(s, NULL, NULL);
+ }
+ break;
+ }
+ return 0;
+}
+
+int addObjDHCPv4ClientReqOption(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*) data;
+ struct uci_section *s, *dmmap_sect;
+ char *value, *instancepara, *v;
+
+ check_create_dmmap_package("dmmap_dhcp_client");
+ instancepara= get_last_instance_lev2_icwmpd_dmmap_opt("dmmap_dhcp_client", "req_option", "cwmp_dhcpv4_sentopt_instance", "section_name", section_name(dhcp_client_args->dhcp_client_conf));
+ dmuci_add_section_icwmpd("dmmap_dhcp_client", "req_option", &dmmap_sect, &value);
+ if(dhcp_client_args->dhcp_client_conf != NULL)
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(dhcp_client_args->dhcp_client_conf));
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "option_tag", "0");
+ *instance = update_instance_icwmpd(dmmap_sect, instancepara, "cwmp_dhcpv4_sentopt_instance");
+ return 0;
+}
+
+int delObjDHCPv4ClientReqOption(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *s, *stmp;
+ char *list= NULL, *opt_value= NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(strcmp(((struct dhcp_client_option_args*) data)->option_tag, "0") != 0)
+ {
+ dmuci_get_value_by_section_string(((struct dhcp_client_option_args*) data)->client_sect, "reqopts", &list);
+ if(list != NULL){
+ remove_elt_from_str_list(&list, ((struct dhcp_client_option_args*) data)->option_tag);
+ dmuci_set_value_by_section(((struct dhcp_client_option_args*) data)->client_sect, "reqopts", list);
+ }
+ }
+ dmuci_delete_by_section_unnamed_icwmpd(((struct dhcp_client_option_args*) data)->opt_sect, NULL, NULL);
+ break;
+ case DEL_ALL:
+ dmuci_set_value_by_section(((struct dhcp_client_args*) data)->dhcp_client_conf, "reqopts", "");
+ uci_path_foreach_sections_safe(icwmpd, "dmmap_dhcp_client", "req_option", stmp, s) {
+ dmuci_delete_by_section_unnamed_icwmpd(s, NULL, NULL);
+ }
+ break;
+ }
+ return 0;
+}
+
+int addObjDHCPv4ServerPoolOption(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ struct dhcp_args *dhcp_arg = (struct dhcp_args*)data;
+ struct uci_section *s, *dmmap_sect;
+ char *value, *instancepara, *v;
+
+ check_create_dmmap_package("dmmap_dhcp");
+ instancepara= get_last_instance_lev2_icwmpd_dmmap_opt("dmmap_dhcp", "servpool_option", "cwmp_dhcpv4_servpool_option_instance", "section_name", section_name(dhcp_arg->dhcp_sec));
+ dmuci_add_section_icwmpd("dmmap_dhcp", "servpool_option", &dmmap_sect, &value);
+ if(dhcp_arg->dhcp_sec != NULL)
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(dhcp_arg->dhcp_sec));
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "option_tag", "0");
+ *instance = update_instance_icwmpd(dmmap_sect, instancepara, "cwmp_dhcpv4_servpool_option_instance");
+ return 0;
+}
+
+int delObjDHCPv4ServerPoolOption(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *s, *stmp;
+ char *list= NULL, *opt_value= NULL;
+ struct uci_list *dhcp_options_list = NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(strcmp(((struct dhcp_client_option_args*) data)->option_tag, "0") != 0)
+ {
+ dmasprintf(&opt_value, "%s,%s", ((struct dhcp_client_option_args*) data)->option_tag, ((struct dhcp_client_option_args*) data)->value);
+ dmuci_get_value_by_section_list(((struct dhcp_client_option_args*) data)->client_sect, "dhcp_option", &dhcp_options_list);
+ if(dhcp_options_list != NULL){
+ dmuci_del_list_value_by_section(((struct dhcp_client_option_args*) data)->client_sect, "dhcp_option", opt_value);
+ }
+ }
+ dmuci_delete_by_section_unnamed_icwmpd(((struct dhcp_client_option_args*) data)->opt_sect, NULL, NULL);
+ break;
+ case DEL_ALL:
+ dmuci_set_value_by_section(((struct dhcp_args*) data)->dhcp_sec, "dhcp_option", "");
+ uci_path_foreach_sections_safe(icwmpd, "dmmap_dhcp", "servpool_option", stmp, s) {
+ dmuci_delete_by_section_unnamed_icwmpd(s, NULL, NULL);
+ }
+ break;
+ }
+ return 0;
+}
+
+int addObjDHCPv4RelayForwarding(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ struct uci_section *s, *dmmap_sect;
+ char *wan_eth, *value, *bridgerelay, *instancepara, *v;
+
+ check_create_dmmap_package("dmmap_dhcp_relay");
+ instancepara = get_last_instance_icwmpd("dmmap_dhcp_relay", "interface", "cwmp_dhcpv4relay_instance");
+ dmuci_add_section("network", "interface", &s, &value);
+ dmuci_set_value_by_section(s, "proto", "relay");
+ dmuci_add_section_icwmpd("dmmap_dhcp_relay", "interface", &dmmap_sect, &v);
+ dmuci_set_value_by_section(dmmap_sect, "section_name", section_name(s));
+ *instance = update_instance_icwmpd(dmmap_sect, instancepara, "cwmp_dhcpv4relay_instance");
+ return 0;
+}
+
+int delObjDHCPv4RelayForwarding(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct dhcp_client_args *dhcp_relay_args = (struct dhcp_client_args*)data;
+ struct uci_section *s = NULL;
+ struct uci_section *ss = NULL;
+ struct uci_section *dmmap_section;
+ char *proto= NULL;
+ int found= 0;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(is_section_unnamed(section_name(dhcp_relay_args->dhcp_client_conf))){
+ LIST_HEAD(dup_list);
+ delete_sections_save_next_sections("dmmap_dhcp_relay", "interface", "cwmp_dhcpv4relay_instance", section_name(dhcp_relay_args->dhcp_client_conf), atoi(instance), &dup_list);
+ update_dmmap_sections(&dup_list, "cwmp_dhcpv4relay_instance", "dmmap_dhcp_relay", "interface");
+ dmuci_delete_by_section_unnamed(dhcp_relay_args->dhcp_client_conf, NULL, NULL);
+ } else {
+ get_dmmap_section_of_config_section("dmmap_dhcp_relay", "interface", section_name(dhcp_relay_args->dhcp_client_conf), &dmmap_section);
+ dmuci_delete_by_section_unnamed_icwmpd(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(dhcp_relay_args->dhcp_client_conf, NULL, NULL);
+ }
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("network", "interface", s) {
+ if (found != 0){
+ dmuci_get_value_by_section_string(ss, "proto", &proto);
+ if(strcmp(proto, "relay") == 0) {
+ get_dmmap_section_of_config_section("dmmap_dhcp_relay", "interface", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL){
+ dmuci_get_value_by_section_string(ss, "proto", &proto);
+ if(strcmp(proto, "relay") == 0) {
+ get_dmmap_section_of_config_section("dmmap_dhcp_relay", "interface", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+/*************************************************************
+ * GET & SET PARAM
+/*************************************************************/
+int get_server_pool_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct dhcp_args *dhcp_arg= (struct dhcp_args*)data;
+ struct uci_section *dmmap_sect;
+
+ get_dmmap_section_of_config_section("dmmap_dhcp", "dhcp", section_name(dhcp_arg->dhcp_sec), &dmmap_sect);
+ if (dmmap_sect)
+ dmuci_get_value_by_section_string(dmmap_sect, "dhcp_alias", value);
+ return 0;
+}
+
+int set_server_pool_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ struct dhcp_args *dhcp_arg= (struct dhcp_args*)data;
+ struct uci_section *dmmap_sect;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ get_dmmap_section_of_config_section("dmmap_dhcp", "dhcp", section_name(dhcp_arg->dhcp_sec), &dmmap_sect);
+ if (dmmap_sect)
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "dhcp_alias", value);
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.DNSServers!UBUBS:network.interface/status/interface,@Name/dns-server*/
+int get_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ int len;
+ struct uci_section *s = NULL;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", ((struct dhcp_args *)data)->interface, String}}, 1, &res);
+ if(res)
+ {
+ *value = dmjson_get_value_array_all(res, DELIMITOR, 1, "dns-server");
+ }
+ else
+ *value = "";
+ if ((*value)[0] == '\0') {
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "dns", value);
+ *value = dmstrdup(*value); // MEM WILL BE FREED IN DMMEMCLEAN
+ char *p = *value;
+ while (*p) {
+ if (*p == ' ' && p != *value && *(p-1) != ',')
+ *p++ = ',';
+ else
+ p++;
+ }
+ }
+ if ((*value)[0] == '\0') {
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "ipaddr", value);
+ }
+ return 0;
+}
+
+int set_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *dup, *p;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dup = dmstrdup(value);
+ p = dup;
+ while (*p) {
+ if (*p == ',')
+ *p++ = ' ';
+ else
+ p++;
+ }
+ dmuci_set_value("network", ((struct dhcp_args *)data)->interface, "dns", dup);
+ dmfree(dup);
+ return 0;
+ }
+ return 0;
+}
+
+int get_dhcp_configurable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ *value = "1";
+ return 0;
+ }
+ *value = "0";
+ return 0;
+}
+
+int set_dhcp_configurable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ if (!b) {
+ dmuci_delete_by_section(s, NULL, NULL);
+ }
+ break;
+ }
+ if (s == NULL && b) {
+ dmuci_set_value("dhcp",((struct dhcp_args *)data)->interface, NULL, "dhcp");
+ dmuci_set_value("dhcp", ((struct dhcp_args *)data)->interface, "interface", ((struct dhcp_args *)data)->interface);
+ dmuci_set_value("dhcp", ((struct dhcp_args *)data)->interface, "start", "100");
+ dmuci_set_value("dhcp", ((struct dhcp_args *)data)->interface, "limit", "150");
+ dmuci_set_value("dhcp", ((struct dhcp_args *)data)->interface, "leasetime", "12h");
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.Status!UCI:dhcp/interface,@i-1/ignore*/
+int get_dhcp_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ char *v= NULL;
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ dmuci_get_value_by_section_string(s, "ignore", &v);
+ *value = (v && *v == '1') ? "Disabled" : "Enabled";
+ return 0;
+ }
+ *value="Error_Misconfigured";
+ return 0;
+}
+
+int get_dhcp_sever_pool_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct dhcp_args *dhcp_arg= (struct dhcp_args*)data;
+ struct uci_section *dmmap_sect;
+
+ get_dmmap_section_of_config_section("dmmap_dhcp", "dhcp", section_name(dhcp_arg->dhcp_sec), &dmmap_sect);
+ if (dmmap_sect)
+ dmuci_get_value_by_section_string(dmmap_sect, "order", value);
+ return 0;
+}
+
+int set_dhcp_sever_pool_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ struct dhcp_args *dhcp_arg= (struct dhcp_args*)data;
+ struct uci_section *dmmap_sect;
+
+ get_dmmap_section_of_config_section("dmmap_dhcp", "dhcp", section_name(dhcp_arg->dhcp_sec), &dmmap_sect);
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ set_section_order("dhcp", "dmmap_dhcp", "dhcp", dmmap_sect, dhcp_arg->dhcp_sec, 1, value);
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.StaticAddressNumberOfEntries!UCI:dhcp/host/*/
+int get_static_address_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct uci_section *s;
+ int i= 0;
+
+ uci_foreach_sections("dhcp", "host", s){
+ i++;
+ }
+ dmasprintf(value, "%d", i);
+ return 0;
+}
+
+int get_option_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ struct dhcp_args *curr_dhcp_args = (struct dhcp_args*)data;
+ struct uci_list *dhcp_options_list = NULL;
+ struct uci_element *e;
+
+ int i= 0;
+
+ dmuci_get_value_by_section_list(curr_dhcp_args->dhcp_sec, "dhcp_option", &dhcp_options_list);
+ if (dhcp_options_list != NULL) {
+ uci_foreach_element(dhcp_options_list, e) {
+ i++;
+ }
+ }
+ dmasprintf(value, "%d", i);
+ return 0;
+}
+
+int get_clients_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ json_object *res = NULL, *client_obj = NULL;
+ int i= 0;
+ char *dhcp;
+
+ dmubus_call("router.network", "clients", UBUS_ARGS{}, 0, &res);
+ if (res) {
+ json_object_object_foreach(res, key, client_obj) {
+ dhcp = dmjson_get_value(client_obj, 1, "dhcp");
+ if(strcmp(dhcp, "true") == 0)
+ i++;
+ }
+ }
+ dmasprintf(value, "%d", i);
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.Enable!UCI:dhcp/interface,@i-1/ignore*/
+int get_dhcp_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ dmuci_get_value_by_section_string(s, "ignore", value);
+ if ((*value)[0] == '\0')
+ *value = "1";
+ else
+ *value = "0";
+ return 0;
+ }
+ *value = "0";
+ return 0;
+}
+
+int set_dhcp_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ if (b)
+ dmuci_set_value_by_section(s, "ignore", "");
+ else
+ dmuci_set_value_by_section(s, "ignore", "1");
+ break;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+enum enum_lanip_interval_address {
+ LANIP_INTERVAL_START,
+ LANIP_INTERVAL_END
+};
+
+int get_dhcp_interval_address(struct dmctx *ctx, void *data, char *instance, char **value, int option)
+{
+ json_object *res, *jobj;
+ char *ipaddr = "" , *mask = "", *start , *limit;
+ struct uci_section *s = NULL;
+ char bufipstart[16], bufipend[16];
+
+ *value = "";
+
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ dmuci_get_value_by_section_string(s, "start", &start);
+ if (option == LANIP_INTERVAL_END)
+ dmuci_get_value_by_section_string(s, "limit", &limit);
+ break;
+ }
+ if (s == NULL) {
+ return 0;
+ }
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "ipaddr", &ipaddr);
+ if (ipaddr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", ((struct dhcp_args *)data)->interface, String}}, 1, &res);
+ if (res)
+ {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ ipaddr = dmjson_get_value(jobj, 1, "address");
+ }
+ }
+ if (ipaddr[0] == '\0') {
+ return 0;
+ }
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "netmask", &mask);
+ if (mask[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", ((struct dhcp_args *)data)->interface, String}}, 1, &res);
+ if (res) {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ mask = dmjson_get_value(jobj, 1, "mask");
+ if (mask[0] == '\0') {
+ return 0;
+ }
+ mask = cidr2netmask(atoi(mask));
+ }
+ }
+ if (mask[0] == '\0') {
+ mask = "255.255.255.0";
+ }
+ if (option == LANIP_INTERVAL_START) {
+ ipcalc(ipaddr, mask, start, NULL, bufipstart, NULL);
+ *value = dmstrdup(bufipstart); // MEM WILL BE FREED IN DMMEMCLEAN
+ }
+ else {
+ ipcalc(ipaddr, mask, start, limit, bufipstart, bufipend);
+ *value = dmstrdup(bufipend); // MEM WILL BE FREED IN DMMEMCLEAN
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.MinAddress!UCI:dhcp/interface,@i-1/start*/
+int get_dhcp_interval_address_min(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_dhcp_interval_address(ctx, data, instance, value, LANIP_INTERVAL_START);
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.MaxAddress!UCI:dhcp/interface,@i-1/limit*/
+int get_dhcp_interval_address_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_dhcp_interval_address(ctx, data, instance, value, LANIP_INTERVAL_END);
+ return 0;
+}
+
+int set_dhcp_address_min(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ json_object *res, *jobj;
+ char *ipaddr = "", *mask = "", *start , *limit, buf[16];
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "ipaddr", &ipaddr);
+ if (ipaddr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", ((struct dhcp_args *)data)->interface, String}}, 1, &res);
+ if (res) {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ ipaddr = dmjson_get_value(jobj, 1, "address");
+ }
+ }
+ if (ipaddr[0] == '\0')
+ return 0;
+
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "netmask", &mask);
+ if (mask[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", ((struct dhcp_args *)data)->interface, String}}, 1, &res);
+ if (res) {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ mask = dmjson_get_value(jobj, 1, "mask");
+ if (mask[0] == '\0')
+ return 0;
+ mask = cidr2netmask(atoi(mask));
+ }
+ }
+ if (mask[0] == '\0')
+ mask = "255.255.255.0";
+
+ ipcalc_rev_start(ipaddr, mask, value, buf);
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ dmuci_set_value_by_section(s, "start", buf);
+ break;
+ }
+
+ return 0;
+ }
+ return 0;
+}
+
+int set_dhcp_address_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ int i_val;
+ json_object *res, *jobj;
+ char *ipaddr = "", *mask = "", *start, buf[16];
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ dmuci_get_value_by_section_string(s, "start", &start);
+ break;
+ }
+ if (!s) return 0;
+
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "ipaddr", &ipaddr);
+ if (ipaddr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", ((struct dhcp_args *)data)->interface, String}}, 1, &res);
+ if (res) {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ ipaddr = dmjson_get_value(jobj, 1, "address"); }
+ }
+ if (ipaddr[0] == '\0')
+ return 0;
+
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "netmask", &mask);
+ if (mask[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", ((struct dhcp_args *)data)->interface, String}}, 1, &res);
+ if (res) {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ mask = dmjson_get_value(jobj, 1, "mask");
+ if (mask[0] == '\0')
+ return 0;
+ mask = cidr2netmask(atoi(mask));
+ }
+ }
+ if (mask[0] == '\0')
+ mask = "255.255.255.0";
+
+ ipcalc_rev_end(ipaddr, mask, start, value, buf);
+ dmuci_set_value_by_section(s, "limit", buf);
+ return 0;
+ }
+ return 0;
+}
+
+
+int get_dhcp_reserved_addresses(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char val[512] = {0}, *p;
+ struct uci_section *s = NULL;
+ char *min, *max, *ip, *s_n_ip;
+ unsigned int n_min, n_max, n_ip;
+ *value = "";
+
+ get_dhcp_interval_address(ctx, data, instance, &min, LANIP_INTERVAL_START);
+ get_dhcp_interval_address(ctx, data, instance, &max, LANIP_INTERVAL_END);
+ if (min[0] == '\0' || max[0] == '\0')
+ return 0;
+ n_min = inet_network(min);
+ n_max = inet_network(max);
+ p = val;
+ uci_foreach_sections("dhcp", "host", s) {
+ dmuci_get_value_by_section_string(s, "ip", &ip);
+ if (ip[0] == '\0')
+ continue;
+ n_ip = inet_network(ip);
+ if (n_ip >= n_min && n_ip <= n_max) {
+ if (val[0] != '\0')
+ dmstrappendchr(p, ',');
+ dmstrappendstr(p, ip);
+ }
+ }
+ dmstrappendend(p);
+ *value = dmstrdup(val); // MEM WILL BE FREED IN DMMEMCLEAN
+ return 0;
+}
+
+int set_dhcp_reserved_addresses(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *s = NULL;
+ struct uci_section *dhcp_section = NULL;
+ char *min, *max, *ip, *val, *local_value;
+ char *pch, *spch;
+ unsigned int n_min, n_max, n_ip, ipexist= 0;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ get_dhcp_interval_address(ctx, data, instance, &min, LANIP_INTERVAL_START);
+ get_dhcp_interval_address(ctx, data, instance, &max, LANIP_INTERVAL_END);
+ n_min = inet_network(min);
+ n_max = inet_network(max);
+ local_value = dmstrdup(value);
+
+ for (pch = strtok_r(local_value, ",", &spch);
+ pch != NULL;
+ pch = strtok_r(NULL, ",", &spch)) {
+ uci_foreach_option_eq("dhcp", "host", "ip", pch, s) {
+ ipexist= 1;
+ }
+ if(ipexist)
+ continue;
+ n_ip = inet_network(pch);
+
+
+ if (n_ip < n_min || n_ip > n_max)
+ continue;
+
+ dmuci_add_section_and_rename("dhcp", "host", &dhcp_section, &val);
+ dmuci_set_value_by_section(dhcp_section, "dhcp", ((struct dhcp_args *)data)->interface);
+ dmuci_set_value_by_section(dhcp_section, "ip", pch);
+ }
+ dmfree(local_value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.SubnetMask!UCI:dhcp/interface,@i-1/netmask*/
+int get_dhcp_subnetmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *mask;
+ json_object *res, *jobj;
+ struct uci_section *s = NULL;
+ char *val;
+ *value = "";
+
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ dmuci_get_value_by_section_string(s, "netmask", value);
+ break;
+ }
+ if (s == NULL || (*value)[0] == '\0')
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "netmask", value);
+ if ((*value)[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", ((struct dhcp_args *)data)->interface, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ mask = dmjson_get_value(jobj, 1, "mask");
+ int i_mask = atoi(mask);
+ val = cidr2netmask(i_mask);
+ *value = dmstrdup(val);// MEM WILL BE FREED IN DMMEMCLEAN
+ }
+ return 0;
+}
+
+int set_dhcp_subnetmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ dmuci_set_value_by_section(s, "netmask", value);
+ return 0;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_dhcp_iprouters(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "gateway", value);
+ if ((*value)[0] == '\0') {
+ dmuci_get_option_value_string("network", ((struct dhcp_args *)data)->interface, "ipaddr", value);
+ }
+ return 0;
+}
+
+int set_dhcp_iprouters(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("network", ((struct dhcp_args *)data)->interface, "gateway", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.LeaseTime!UCI:dhcp/interface,@i-1/leasetime*/
+int get_dhcp_leasetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int len, mtime = 0;
+ char *ltime = "", *pch, *spch, *ltime_ini, *tmp, *tmp_ini;
+ struct uci_section *s = NULL;
+
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ dmuci_get_value_by_section_string(s, "leasetime", <ime);
+ break;
+ }
+ if (ltime[0] == '\0') {
+ *value = "-1";
+ return 0;
+ }
+ ltime = dmstrdup(ltime);
+ ltime_ini = dmstrdup(ltime);
+ tmp = ltime;
+ tmp_ini = ltime_ini;
+ pch = strtok_r(ltime, "h", &spch);
+ if (strcmp(pch, ltime_ini) != 0) {
+ mtime = 3600 * atoi(pch);
+ if(spch[0] != '\0') {
+ ltime += strlen(pch)+1;
+ ltime_ini += strlen(pch)+1;
+ pch = strtok_r(ltime, "m", &spch);
+ if (strcmp(pch, ltime_ini) != 0) {
+ mtime += 60 * atoi(pch);
+ if(spch[0] !='\0') {
+ ltime += strlen(pch)+1;
+ ltime_ini += strlen(pch)+1;
+ pch = strtok_r(ltime, "s", &spch);
+ if (strcmp(pch, ltime_ini) != 0) {
+ mtime += atoi(pch);
+ }
+ }
+ } else {
+ pch = strtok_r(ltime, "s", &spch);
+ if (strcmp(pch, ltime_ini) != 0)
+ mtime += atoi(pch);
+ }
+ }
+ }
+ else {
+ pch = strtok_r(ltime, "m", &spch);
+ if (strcmp(pch, ltime_ini) != 0) {
+ mtime += 60 * atoi(pch);
+ if(spch[0] !='\0') {
+ ltime += strlen(pch)+1;
+ ltime_ini += strlen(pch)+1;
+ pch = strtok_r(ltime, "s", &spch);
+ if (strcmp(pch, ltime_ini) != 0) {
+ mtime += atoi(pch);
+ }
+ }
+ } else {
+ pch = strtok_r(ltime, "s", &spch);
+ if (strcmp(pch, ltime_ini) != 0)
+ mtime += atoi(pch);
+ }
+ }
+ dmfree(tmp);
+ dmfree(tmp_ini);
+
+ dmasprintf(value, "%d", mtime); // MEM WILL BE FREED IN DMMEMCLEAN
+ return 0;
+}
+
+int set_dhcp_leasetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *s = NULL;
+ char buf[32];
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ int val = atoi(value);
+ sprintf(buf, "%ds", val);
+ dmuci_set_value_by_section(s, "leasetime", buf);
+ break;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_dhcp_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *linker;
+ linker = dmstrdup(((struct dhcp_args *)data)->interface);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value); // MEM WILL BE FREED IN DMMEMCLEAN
+ if (*value == NULL)
+ *value = "";
+ dmfree(linker);
+ return 0;
+}
+
+int set_dhcp_interface_linker_parameter(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *linker;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ adm_entry_get_linker_value(ctx, value, &linker);
+ if (linker) {
+ dmuci_set_value_by_section(((struct dhcp_args *)data)->dhcp_sec, "interface", linker);
+ dmfree(linker);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_dhcp_domainname(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *result, *str;
+ struct uci_list *val;
+ struct uci_element *e = NULL;
+ struct uci_section *s = NULL;
+ *value = "";
+
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ dmuci_get_value_by_section_list(s, "dhcp_option", &val);
+ if (val) {
+ uci_foreach_element(val, e)
+ {
+ if ((str = strstr(e->name, "15,"))) {
+ *value = dmstrdup(str + sizeof("15,") - 1); //MEM WILL BE FREED IN DMMEMCLEAN
+ return 0;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int set_dhcp_domainname(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *result, *dn, *pch;
+ struct uci_list *val;
+ struct uci_section *s = NULL;
+ struct uci_element *e = NULL, *tmp;
+ char *option = "dhcp_option", buf[64];
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcp_args *)data)->interface, s) {
+ dmuci_get_value_by_section_list(s, option, &val);
+ if (val) {
+ uci_foreach_element_safe(val, e, tmp)
+ {
+ if (strstr(tmp->name, "15,")) {
+ dmuci_del_list_value_by_section(s, "dhcp_option", tmp->name); //TODO test it
+ }
+ }
+ }
+ break;
+ }
+ goto end;
+ }
+end:
+ sprintf(buf, "15,%s", value);
+ dmuci_add_list_value_by_section(((struct dhcp_args *)data)->dhcp_sec, "dhcp_option", buf);
+ return 0;
+}
+
+int get_dhcp_static_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+ get_dmmap_section_of_config_section("dmmap_dhcp", "host", section_name(((struct dhcp_static_args *)data)->dhcpsection), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "ldhcpalias", value);
+ return 0;
+}
+
+int set_dhcp_static_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_dhcp", "host", section_name(((struct dhcp_static_args *)data)->dhcpsection), &dmmap_section);
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(dmmap_section, "ldhcpalias", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.StaticAddress.{i}.Chaddr!UCI:dhcp/host,@i-1/mac*/
+int get_dhcp_staticaddress_chaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *chaddr;
+ struct dhcp_static_args *dhcpargs = (struct dhcp_static_args *)data;
+
+ dmuci_get_value_by_section_string(dhcpargs->dhcpsection, "mac", &chaddr);
+ if (strcmp(chaddr, DHCPSTATICADDRESS_DISABLED_CHADDR) == 0)
+ dmuci_get_value_by_section_string(dhcpargs->dhcpsection, "mac_orig", value);
+ else
+ *value = chaddr;
+ return 0;
+}
+
+int set_dhcp_staticaddress_chaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *chaddr;
+ struct dhcp_static_args *dhcpargs = (struct dhcp_static_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(dhcpargs->dhcpsection, "mac", &chaddr);
+ if (strcmp(chaddr, DHCPSTATICADDRESS_DISABLED_CHADDR) == 0)
+ dmuci_set_value_by_section(dhcpargs->dhcpsection, "mac_orig", value);
+ else
+ dmuci_set_value_by_section(dhcpargs->dhcpsection, "mac", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.StaticAddress.{i}.Yiaddr!UCI:dhcp/host,@i-1/ip*/
+int get_dhcp_staticaddress_yiaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_static_args *dhcpargs = (struct dhcp_static_args *)data;
+
+ dmuci_get_value_by_section_string(dhcpargs->dhcpsection, "ip", value);
+ return 0;
+}
+
+int set_dhcp_staticaddress_yiaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_static_args *dhcpargs = (struct dhcp_static_args *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(dhcpargs->dhcpsection, "ip", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_dhcp_client_chaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = dmjson_get_value(((struct client_args *)data)->client, 1, "macaddr");
+ return 0;
+}
+
+int get_dhcp_client_active(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = dmjson_get_value(((struct client_args *)data)->client, 1, "connected");
+ return 0;
+}
+
+int get_dhcp_client_ipv4address_leasetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char time_buf[26] = {0};
+ struct tm *t_tm;
+ struct dhcp_client_ipv4address_args current_dhcp_client_ipv4address_args = *((struct dhcp_client_ipv4address_args*)data);
+
+ *value = "0001-01-01T00:00:00Z";
+ time_t t_time = current_dhcp_client_ipv4address_args.leasetime;
+ t_tm = localtime(&t_time);
+ if (t_tm == NULL)
+ return 0;
+ if(strftime(time_buf, sizeof(time_buf), "%FT%T%z", t_tm) == 0)
+ return 0;
+
+ time_buf[25] = time_buf[24];
+ time_buf[24] = time_buf[23];
+ time_buf[22] = ':';
+ time_buf[26] = '\0';
+
+ *value = dmstrdup(time_buf);
+ return 0;
+}
+
+int get_dhcp_client_ipv4address_ip_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) {
+ struct dhcp_client_ipv4address_args current_dhcp_client_ipv4address_args = *((struct dhcp_client_ipv4address_args*)data);
+
+ if(current_dhcp_client_ipv4address_args.ip != NULL && strlen(current_dhcp_client_ipv4address_args.ip)>0)
+ *value= dmstrdup(current_dhcp_client_ipv4address_args.ip);
+ else
+ *value= "";
+ return 0;
+}
+
+int get_DHCPv4_ClientNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s, *dmmap_sect;
+ int nbre_confs= 0, nbre_dmmaps= 0;
+
+ uci_foreach_option_eq("network", "interface", "proto", "dhcp", s) {
+ nbre_confs++;
+ }
+ uci_path_foreach_sections(icwmpd, "dmmap_dhcp_client", "interface", dmmap_sect) {
+ nbre_dmmaps++;
+ }
+ if(nbre_dmmaps ==0 || nbre_dmmaps < nbre_confs)
+ dmasprintf(value, "%d", nbre_confs);
+ else
+ dmasprintf(value, "%d", nbre_dmmaps);
+ return 0;
+}
+
+/*#Device.DHCPv4.Client.{i}.Enable!UCI:network/interface,@i-1/disabled*/
+int get_DHCPv4Client_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ char *v= NULL;
+
+
+ if(dhcp_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "0";
+ return 0;
+ }
+
+ dmuci_get_value_by_section_string(dhcp_client_args->dhcp_client_conf, "disabled", &v);
+
+ if (v==NULL || strlen(v)==0 || strcmp(v, "1")!=0)
+ *value= "1";
+ else
+ *value= "0";
+
+ return 0;
+}
+
+int set_DHCPv4Client_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct uci_section *s = NULL;
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b)
+ dmuci_set_value_by_section(dhcp_client_args->dhcp_client_conf, "disabled", "0");
+ else
+ dmuci_set_value_by_section(dhcp_client_args->dhcp_client_conf, "disabled", "1");
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4Client_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+
+ dmuci_get_value_by_section_string(dhcp_client_args->dhcp_client_dm, "cwmp_dhcpv4client_alias", value);
+
+ return 0;
+}
+
+int set_DHCPv4Client_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section(dhcp_client_args->dhcp_client_dm, "cwmp_dhcpv4client_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4Client_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ if(dhcp_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "";
+
+ return 0;
+ }
+ char *linker= dmstrdup(section_name(dhcp_client_args->dhcp_client_conf));
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim, dm_delim), linker, value);
+
+ return 0;
+}
+
+int set_DHCPv4Client_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ struct uci_section *s;
+ char *linker= NULL, *newvalue= NULL, *v;
+
+ switch (action) {
+ case VALUECHECK:
+ if(strlen(value) == 0 || strcmp(value, "") == 0)
+ return FAULT_9007;
+
+ if (value[strlen(value)-1]!='.') {
+ dmasprintf(&newvalue, "%s.", value);
+ adm_entry_get_linker_value(ctx, newvalue, &linker);
+ } else
+ adm_entry_get_linker_value(ctx, value, &linker);
+ uci_path_foreach_sections(icwmpd, "dmmap_dhcp_client", "interface", s) {
+ dmuci_get_value_by_section_string(s, "section_name", &v);
+ if(strcmp(v, linker) == 0)
+ return FAULT_9007;
+ }
+ uci_foreach_sections("network", "interface", s) {
+ if(strcmp(section_name(s), linker) == 0){
+ dmuci_get_value_by_section_string(s, "proto", &v);
+ if(strcmp(v, "dhcp") != 0)
+ return FAULT_9007;
+ }
+ }
+ break;
+ case VALUESET:
+ if (value[strlen(value)-1]!='.') {
+ dmasprintf(&newvalue, "%s.", value);
+ adm_entry_get_linker_value(ctx, newvalue, &linker);
+ } else
+ adm_entry_get_linker_value(ctx, value, &linker);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_args->dhcp_client_dm, "section_name", linker);
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Client.{i}.Status!UCI:network/interface,@i-1/disabled*/
+int get_DHCPv4Client_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ char *v= "";
+ if(dhcp_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "Error_Misconfigured";
+
+ return 0;
+ }
+
+ dmuci_get_value_by_section_string(dhcp_client_args->dhcp_client_conf, "disabled", &v);
+
+ if (v==NULL || strlen(v)==0 || strcmp(v, "1")!=0)
+ *value= "Enabled";
+ else
+ *value= "Disabled";
+
+ return 0;
+}
+
+/*#Device.DHCPv4.Client.{i}.DHCPStatus!UBUS:network.interface/status/interface,@Name/ipv4-address[@i-1].address*/
+int get_DHCPv4Client_DHCPStatus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ char *ipaddr;
+ json_object *res, *jobj;
+
+ if (dhcp_client_args->dhcp_client_conf == NULL)
+ return 0;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(dhcp_client_args->dhcp_client_conf), String}}, 1, &res);
+ if (res) {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ ipaddr = dmjson_get_value(jobj, 1, "address");
+ }
+
+ if (ipaddr[0] == '\0')
+ *value = "Requesting";
+ else
+ *value = "Bound";
+
+ return 0;
+}
+
+int get_DHCPv4Client_Renew(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+
+ *value = "false";
+
+ return 0;
+}
+
+int set_DHCPv4Client_Renew(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ json_object *res;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ if (dhcp_client_args->dhcp_client_conf == NULL && strcasecmp(value, "true") != 0)
+ return 0;
+
+ dmubus_call("network.interface", "renew", UBUS_ARGS{{"interface", section_name(dhcp_client_args->dhcp_client_conf), String}}, 1, &res);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4Client_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+
+ *value= dmstrdup(dhcp_client_args->ip);
+
+ return 0;
+}
+
+int get_DHCPv4Client_SubnetMask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+
+ *value= dmstrdup(dhcp_client_args->mask);
+
+ return 0;
+}
+
+/*#Device.DHCPv4.Client.{i}.IPRouters!UBUS:network.interface/status/interface,@Name/route[@i-1].target*/
+int get_DHCPv4Client_IPRouters(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ char *v, buf[256] = "";
+ json_object *jobj= NULL, *res;
+ int i = 0;
+
+ if (dhcp_client_args->dhcp_client_conf == NULL)
+ return 0;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(dhcp_client_args->dhcp_client_conf), String}}, 1, &res);
+
+ while (1) {
+ jobj = dmjson_select_obj_in_array_idx(res, i, 1, "route");
+ i++;
+
+ if (jobj == NULL)
+ break;
+
+ v = dmjson_get_value(jobj, 1, "target");
+ if (*v == '\0')
+ continue;
+ if (strcmp(v, "0.0.0.0") == 0)
+ continue;
+ if (buf[0] != '\0') {
+ strcat(buf, ",");
+ } else
+ strcat(buf, v);
+
+ }
+
+ *value = dmstrdup(buf);
+
+ return 0;
+}
+
+/*#Device.DHCPv4.Client.{i}.DNSServers!UBUS:network.interface/status/interface,@Name/dns-server*/
+int get_DHCPv4Client_DNSServers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ json_object *res;
+
+ if (dhcp_client_args->dhcp_client_conf == NULL)
+ return 0;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(dhcp_client_args->dhcp_client_conf), String}}, 1, &res);
+
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value_array_all(res, DELIMITOR, 1, "dns-server");
+
+ return 0;
+}
+
+/*#Device.DHCPv4.Client.{i}.LeaseTimeRemaining!UBUS:network.interface/status/interface,@Name/data.leasetime*/
+int get_DHCPv4Client_LeaseTimeRemaining(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ json_object *res;
+ char *str;
+
+ if (dhcp_client_args->dhcp_client_conf == NULL)
+ return 0;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(dhcp_client_args->dhcp_client_conf), String}}, 1, &res);
+ if (!res){
+ *value= "";
+ return 0;
+ }
+
+ *value = dmjson_get_value(res, 2, "data", "leasetime");
+ return 0;
+}
+
+int get_DHCPv4Client_DHCPServer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv4Client_PassthroughEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+
+ *value = "0";
+
+ return 0;
+}
+
+int set_DHCPv4Client_PassthroughEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4Client_PassthroughDHCPPool(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "";
+ return 0;
+}
+
+int set_DHCPv4Client_PassthroughDHCPPool(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Client.{i}.SentOptionNumberOfEntries!UCI:network/interface,@i-1/sendopts*/
+int get_DHCPv4Client_SentOptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args* dhcp_client_args= (struct dhcp_client_args*)data;
+ char *v= NULL, **sendopts;
+ int length;
+
+ if(dhcp_client_args->dhcp_client_conf != NULL)
+ dmuci_get_value_by_section_string(dhcp_client_args->dhcp_client_conf, "sendopts", &v);
+
+ if(v==NULL){
+ *value= "0";
+ return 0;
+ }
+
+ sendopts= strsplit(v, " ", &length);
+ dmasprintf(value, "%d", length);
+
+ return 0;
+}
+
+/*#Device.DHCPv4.Client.{i}.ReqOptionNumberOfEntries!UCI:network/interface,@i-1/reqopts*/
+int get_DHCPv4Client_ReqOptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args* dhcp_client_args= (struct dhcp_client_args*)data;
+ char *v, **sendopts;
+ int length;
+
+ if(dhcp_client_args->dhcp_client_conf != NULL)
+ dmuci_get_value_by_section_string(dhcp_client_args->dhcp_client_conf, "reqopts", &v);
+
+ if(v==NULL){
+ *value= "0";
+ return 0;
+ }
+
+ sendopts= strsplit(v, " ", &length);
+
+ dmasprintf(value, "%d", length);
+
+ return 0;
+}
+
+int get_DHCPv4ClientSentOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ char *v;
+ char *opttagvalue= NULL;
+
+ if(strcmp(dhcp_client_opt_args->option_tag, "0") == 0){
+ *value= "0";
+ return 0;
+ }
+
+ dmasprintf(&opttagvalue, "%s:%s", dhcp_client_opt_args->option_tag, dhcp_client_opt_args->value);
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->client_sect, "sendopts", &v);
+
+ if(is_elt_exit_in_str_list(v, opttagvalue))
+ *value = "1";
+ else
+ *value= "0";
+
+
+ return 0;
+}
+
+int set_DHCPv4ClientSentOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ bool b;
+ char *v;
+ char *opttagvalue= NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->client_sect, "sendopts", &v);
+
+ if(strcmp(dhcp_client_opt_args->option_tag, "0") == 0)
+ return 0;
+
+ dmasprintf(&opttagvalue, "%s:%s", dhcp_client_opt_args->option_tag, dhcp_client_opt_args->value);
+
+ if (b) {
+ if(!is_elt_exit_in_str_list(v, opttagvalue)){
+ add_elt_to_str_list(&v, opttagvalue);
+ dmuci_set_value_by_section(dhcp_client_opt_args->client_sect, "sendopts", v);
+ }
+ } else {
+ remove_elt_from_str_list(&v, opttagvalue);
+ dmuci_set_value_by_section(dhcp_client_opt_args->client_sect, "sendopts", v);
+ }
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ClientSentOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->opt_sect, "cwmp_dhcpv4_sentopt_alias", value);
+
+ return 0;
+}
+
+int set_DHCPv4ClientSentOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "cwmp_dhcpv4_sentopt_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ClientSentOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ *value= dmstrdup(dhcp_client_opt_args->option_tag);
+
+ return 0;
+}
+
+int set_DHCPv4ClientSentOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ char *pch, *spch, *list, *v, *opttagvalue, **sendopts, *oldopttagvalue;
+ int length;
+
+ switch (action) {
+ case VALUECHECK:
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->client_sect, "sendopts", &v);
+ if(v==NULL)
+ return 0;
+
+ list= dmstrdup(v);
+ for (pch = strtok_r(list, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) {
+ sendopts= strsplit(pch, ":", &length);
+ if(strcmp(sendopts[0], value) == 0)
+ return FAULT_9007;
+ }
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->client_sect, "sendopts", &v);
+ dmasprintf(&oldopttagvalue, "%s:%s", dhcp_client_opt_args->option_tag, dhcp_client_opt_args->value);
+ if (v != NULL && strlen(v)>0)
+ remove_elt_from_str_list(&v, oldopttagvalue);
+ dmasprintf(&opttagvalue, "%s:%s", value, dhcp_client_opt_args->value&&strlen(dhcp_client_opt_args->value)>0?dhcp_client_opt_args->value:"0");
+ add_elt_to_str_list(&v, opttagvalue);
+ dmuci_set_value_by_section(dhcp_client_opt_args->client_sect, "sendopts", v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "option_tag", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ClientSentOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+
+ *value= dmstrdup(dhcp_client_opt_args->value);
+
+ return 0;
+}
+
+int set_DHCPv4ClientSentOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ char *v, *opttagvalue, *oldopttagvalue;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->client_sect, "sendopts", &v);
+ dmasprintf(&oldopttagvalue, "%s:%s", dhcp_client_opt_args->option_tag, dhcp_client_opt_args->value);
+ remove_elt_from_str_list(&v, oldopttagvalue);
+ dmasprintf(&opttagvalue, "%s:%s", dhcp_client_opt_args->option_tag, value);
+ add_elt_to_str_list(&v, opttagvalue);
+ dmuci_set_value_by_section(dhcp_client_opt_args->client_sect, "sendopts", v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "option_value", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ClientReqOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ char *v;
+ char *opttagvalue= NULL;
+
+ if(strcmp(dhcp_client_opt_args->option_tag, "0") == 0){
+ *value= "0";
+ return 0;
+ }
+
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->client_sect, "reqopts", &v);
+
+ if(is_elt_exit_in_str_list(v, dhcp_client_opt_args->option_tag))
+ *value = "1";
+ else
+ *value= "0";
+
+ return 0;
+}
+
+int set_DHCPv4ClientReqOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ bool b;
+ char *v;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->client_sect, "reqopts", &v);
+
+ if(strcmp(dhcp_client_opt_args->option_tag, "0") == 0)
+ return 0;
+
+ if (b) {
+ if(!is_elt_exit_in_str_list(v, dhcp_client_opt_args->option_tag)){
+ add_elt_to_str_list(&v, dhcp_client_opt_args->option_tag);
+ dmuci_set_value_by_section(dhcp_client_opt_args->client_sect, "reqopts", v);
+ }
+ } else {
+ remove_elt_from_str_list(&v, dhcp_client_opt_args->option_tag);
+ dmuci_set_value_by_section(dhcp_client_opt_args->client_sect, "reqopts", v);
+ }
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ClientReqOption_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv4ClientReqOption_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ClientReqOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->opt_sect, "cwmp_dhcpv4_reqtopt_alias", value);
+
+ return 0;
+}
+
+int set_DHCPv4ClientReqOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "cwmp_dhcpv4_reqtopt_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ClientReqOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ *value= dmstrdup(dhcp_client_opt_args->option_tag);
+ return 0;
+}
+
+int set_DHCPv4ClientReqOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+
+ char *pch, *spch, *list, *v, *opttagvalue, **sendopts, *oldopttagvalue;
+ int length;
+
+ switch (action) {
+ case VALUECHECK:
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->client_sect, "reqopts", &v);
+ if(v==NULL)
+ return 0;
+ list= dmstrdup(v);
+ for (pch = strtok_r(list, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) {
+ if(strcmp(pch, value) == 0)
+ return FAULT_9007;
+ }
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->client_sect, "reqopts", &v);
+ if (v != NULL && strlen(v)>0)
+ remove_elt_from_str_list(&v, dhcp_client_opt_args->option_tag);
+ add_elt_to_str_list(&v, value);
+ dmuci_set_value_by_section(dhcp_client_opt_args->client_sect, "reqopts", v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "option_tag", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ClientReqOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv4Server_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv4Server_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_DHCPServerIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_DHCPServerIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ServerPoolOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ char *v;
+ char *opttagvalue= NULL;
+ struct uci_list *dhcp_option_list;
+ struct uci_element *e;
+ char **buf;
+ int length;
+
+ if(strcmp(dhcp_client_opt_args->option_tag, "0") == 0){
+ *value= "0";
+ return 0;
+ }
+
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+ if (dhcp_option_list != NULL) {
+ uci_foreach_element(dhcp_option_list, e) {
+ buf= strsplit(e->name, ",", &length);
+ if(strcmp(buf[0], dhcp_client_opt_args->option_tag) == 0) {
+ *value= "1";
+ return 0;
+ }
+ }
+ }
+
+ *value= "0";
+ return 0;
+}
+
+int set_DHCPv4ServerPoolOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ struct uci_list *dhcp_option_list;
+ struct uci_element *e;
+ char **buf, *opt_value;
+ int length;
+ bool test= false, b;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+
+ if(strcmp(dhcp_client_opt_args->option_tag, "0") == 0)
+ return 0;
+
+
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+ dmasprintf(&opt_value, "%s,%s", dhcp_client_opt_args->option_tag, dhcp_client_opt_args->value);
+
+ if (dhcp_option_list != NULL) {
+ uci_foreach_element(dhcp_option_list, e) {
+ buf= strsplit(e->name, ",", &length);
+ if(strcmp(buf[0], dhcp_client_opt_args->option_tag) == 0) {
+ test= true;
+ if(!b)
+ dmuci_del_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", opt_value);
+ break;
+ }
+ }
+ }
+ if(!test && b)
+ dmuci_add_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", opt_value);
+
+ }
+ return 0;
+}
+
+int get_DHCPv4Server_PoolNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s;
+ int i= 0;
+
+ uci_foreach_sections("dhcp", "dhcp", s) {
+ i++;
+ }
+ dmasprintf(value, "%d", i);
+ return 0;
+}
+
+int get_DHCPv4ServerPoolOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->opt_sect, "cwmp_dhcpv4_servpool_option_alias", value);
+ return 0;
+}
+
+int set_DHCPv4ServerPoolOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "cwmp_dhcpv4_servpool_option_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ServerPoolOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ *value= dmstrdup(dhcp_client_opt_args->option_tag);
+ return 0;
+}
+
+int set_DHCPv4ServerPoolOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ char *opttagvalue, **option, *oldopttagvalue;
+ int length;
+ struct uci_list *dhcp_option_list= NULL;
+ struct uci_element *e;
+
+ switch (action) {
+ case VALUECHECK:
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+
+ if(dhcp_option_list==NULL)
+ return 0;
+
+ uci_foreach_element(dhcp_option_list, e) {
+ option= strsplit(e->name, ",", &length);
+ if (strcmp(option[0], value)==0)
+ return FAULT_9007;
+ }
+ break;
+ case VALUESET:
+ dmasprintf(&oldopttagvalue, "%s,%s", dhcp_client_opt_args->option_tag, dhcp_client_opt_args->value);
+ dmasprintf(&opttagvalue, "%s,%s", value, dhcp_client_opt_args->value);
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+ dmuci_del_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", oldopttagvalue);
+ dmuci_add_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", opttagvalue);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "option_tag", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ServerPoolOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ *value= dmstrdup(dhcp_client_opt_args->value);
+ return 0;
+}
+
+int set_DHCPv4ServerPoolOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_option_args* dhcp_client_opt_args= (struct dhcp_client_option_args*)data;
+ char *opttagvalue, **option, *oldopttagvalue;
+ int length;
+ struct uci_list *dhcp_option_list= NULL;
+ struct uci_element *e;
+
+ switch (action) {
+ case VALUECHECK:
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+
+ if(dhcp_option_list==NULL)
+ return 0;
+
+ uci_foreach_element(dhcp_option_list, e) {
+ option= strsplit(e->name, ",", &length);
+ if (strcmp(option[0], value)==0)
+ return FAULT_9007;
+ }
+ break;
+ case VALUESET:
+ dmasprintf(&oldopttagvalue, "%s,%s", dhcp_client_opt_args->option_tag, dhcp_client_opt_args->value);
+ dmasprintf(&opttagvalue, "%s,%s", dhcp_client_opt_args->option_tag, value);
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+ dmuci_del_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", oldopttagvalue);
+ dmuci_add_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", opttagvalue);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "option_value", value);
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Relay.Forwarding.{i}.Enable!UCI:network/interface,@i-1/disabled*/
+int get_DHCPv4RelayForwarding_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ char *v= NULL;
+
+
+ if(dhcp_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "0";
+ return 0;
+ }
+
+ dmuci_get_value_by_section_string(dhcp_client_args->dhcp_client_conf, "disabled", &v);
+
+ if (v==NULL || strlen(v)==0 || strcmp(v, "1")!=0)
+ *value= "1";
+ else
+ *value= "0";
+
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct uci_section *s = NULL;
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b)
+ dmuci_set_value_by_section(dhcp_client_args->dhcp_client_conf, "disabled", "0");
+ else
+ dmuci_set_value_by_section(dhcp_client_args->dhcp_client_conf, "disabled", "1");
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ struct uci_section *dmmap_section;
+ char *v;
+
+ dmuci_get_value_by_section_string(dhcp_client_args->dhcp_client_dm, "cwmp_dhcpv4relay_alias", value);
+
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ struct uci_section *dmmap_section;
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section(dhcp_client_args->dhcp_client_dm, "cwmp_dhcpv4relay_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ if(dhcp_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "";
+
+ return 0;
+ }
+ char *linker= dmstrdup(section_name(dhcp_client_args->dhcp_client_conf));
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim, dm_delim), linker, value);
+
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ struct uci_section *s;
+ char *linker= NULL, *newvalue= NULL, *v;
+
+ switch (action) {
+ case VALUECHECK:
+ if(strlen(value) == 0 || strcmp(value, "") == 0)
+ return FAULT_9007;
+
+ if (value[strlen(value)-1]!='.') {
+ dmasprintf(&newvalue, "%s.", value);
+ adm_entry_get_linker_value(ctx, newvalue, &linker);
+ } else
+ adm_entry_get_linker_value(ctx, value, &linker);
+ if(linker == NULL)
+ return FAULT_9007;
+ uci_path_foreach_sections(icwmpd, "dmmap_dhcp_relay", "interface", s) {
+ dmuci_get_value_by_section_string(s, "section_name", &v);
+ if(strcmp(v, linker) == 0)
+ return FAULT_9007;
+ }
+ uci_foreach_sections("network", "interface", s) {
+ if(strcmp(section_name(s), linker) == 0){
+ dmuci_get_value_by_section_string(s, "proto", &v);
+ if(strcmp(v, "relay") != 0)
+ return FAULT_9007;
+ }
+ }
+ break;
+ case VALUESET:
+ if (value[strlen(value)-1]!='.') {
+ dmasprintf(&newvalue, "%s.", value);
+ adm_entry_get_linker_value(ctx, newvalue, &linker);
+ } else
+ adm_entry_get_linker_value(ctx, value, &linker);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_args->dhcp_client_dm, "section_name", linker);
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Relay.Forwarding.{i}.VendorClassID!UCI:network/interface,@i-1/vendorclass*/
+int get_DHCPv4RelayForwarding_VendorClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_relay_args = (struct dhcp_client_args*)data;
+ char *vendorclass;
+ if(dhcp_relay_args->vendorclassidclassifier == NULL)
+ return 0;
+ dmuci_get_value_by_section_string(dhcp_relay_args->vendorclassidclassifier, "vendorclass", value);
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_VendorClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_args *dhcp_relay_args = (struct dhcp_client_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ if(dhcp_relay_args->vendorclassidclassifier == NULL)
+ return 0;
+ dmuci_set_value_by_section(dhcp_relay_args->vendorclassidclassifier, "vendorclass", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_VendorClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value="false";
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_VendorClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_VendorClassIDMode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value= "Prefix";
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_VendorClassIDMode(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Relay.Forwarding.{i}.Chaddr!UCI:network/interface,@i-1/mac*/
+int get_DHCPv4RelayForwarding_Chaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_relay_args = (struct dhcp_client_args*)data;
+ char *mac, *mac1, *mac2, *mac3, *mac4, *mac5, *mac6, **macarray, *res= NULL, *tmp= "";
+ int length, i;
+
+ if(dhcp_relay_args->macclassifier == NULL) {
+ *value= "";
+ return 0;
+ }
+ dmuci_get_value_by_section_string(dhcp_relay_args->macclassifier, "mac", &mac);
+ macarray= strsplit(mac, ":", &length);
+ res= (char*)dmcalloc(18, sizeof(char));
+ tmp=res;
+ for(i= 0; i<6; i++){
+ if(strcmp(macarray[i], "*") == 0) {
+ sprintf(tmp, "%s", "00");
+ } else{
+ sprintf(tmp, "%s", macarray[i]);
+ }
+ tmp+=2;
+
+ if(i<5){
+ sprintf(tmp, "%s", ":");
+ tmp++;
+ }
+ }
+ dmasprintf(value, "%s", res);
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_Chaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Relay.Forwarding.{i}.ChaddrMask!UCI:network/interface,@i-1/mac*/
+int get_DHCPv4RelayForwarding_ChaddrMask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_relay_args = (struct dhcp_client_args*)data;
+ char *mac, *mac1, *mac2, *mac3, *mac4, *mac5, *mac6, **macarray, *res= NULL, *tmp= "";
+ int length, i;
+
+ if(dhcp_relay_args->macclassifier == NULL) {
+ *value= "";
+ return 0;
+ }
+ dmuci_get_value_by_section_string(dhcp_relay_args->macclassifier, "mac", &mac);
+ macarray= strsplit(mac, ":", &length);
+ res= (char*)dmcalloc(18, sizeof(char));
+ tmp=res;
+ for(i= 0; i<6; i++){
+ if(strcmp(macarray[i], "*") == 0) {
+ sprintf(tmp, "%s", "00");
+ } else{
+ sprintf(tmp, "%s", "FF");
+ }
+ tmp+=2;
+
+ if(i<5){
+ sprintf(tmp, "%s", ":");
+ tmp++;
+ }
+ }
+ dmasprintf(value, "%s", res);
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_ChaddrMask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_ChaddrExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value="true";
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_ChaddrExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_LocallyServed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_LocallyServed(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ServerPoolClientOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+/*#Device.DHCPv4.Relay.Forwarding.{i}.Status!UCI:network/interface,@i-1/disabled*/
+int get_DHCPv4RelayForwarding_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)data;
+ char *v= NULL;
+ if(dhcp_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "Error_Misconfigured";
+
+ return 0;
+ }
+ dmuci_get_value_by_section_string(dhcp_client_args->dhcp_client_conf, "disabled", &v);
+ if (v==NULL || strlen(v)==0 || strcmp(v, "1")!=0)
+ *value= "Enabled";
+ else
+ *value= "Disabled";
+
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_ClientID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_ClientID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_ClientIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value= "true";
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_ClientIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv4.Relay.Forwarding.{i}.UserClassID!UCI:network/interface,@i-1/userclass*/
+int get_DHCPv4RelayForwarding_UserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcp_client_args *dhcp_relay_args = (struct dhcp_client_args*)data;
+ char *vendorclass;
+ if(dhcp_relay_args->userclassclassifier == NULL)
+ return 0;
+ dmuci_get_value_by_section_string(dhcp_relay_args->userclassclassifier, "userclass", value);
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_UserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcp_client_args *dhcp_relay_args = (struct dhcp_client_args*)data;
+ char *user;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ if(dhcp_relay_args->userclassclassifier == NULL)
+ return 0;
+ dmuci_set_value_by_section(dhcp_relay_args->userclassclassifier, "userclass", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4RelayForwarding_UserClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value= "false";
+ return 0;
+}
+
+int set_DHCPv4RelayForwarding_UserClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4ServerPoolClientOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv4Relay_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *path = "/etc/rc.d/*relayd";
+ if (check_file(path))
+ *value = "1";
+ else
+ *value = "0";
+ return 0;
+}
+
+int set_DHCPv4Relay_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b)
+ dmcmd("/etc/init.d/relayd", 1, "enable");
+ else
+ dmcmd("/etc/init.d/relayd", 1, "disable");
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv4Relay_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *path = "/etc/rc.d/*relayd";
+ if (check_file(path))
+ *value = "Enabled";
+ else
+ *value = "Disabled";
+ return 0;
+}
+
+int get_DHCPv4Relay_ForwardingNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s, *dmmap_sect;
+ int nbre_confs= 0, nbre_dmmaps= 0;
+
+ uci_foreach_option_eq("network", "interface", "proto", "relay", s) {
+ nbre_confs++;
+ }
+ uci_path_foreach_sections(icwmpd, "dmmap_dhcp_relay", "interface", dmmap_sect) {
+ nbre_dmmaps++;
+ }
+ if(nbre_dmmaps ==0 || nbre_dmmaps < nbre_confs)
+ dmasprintf(value, "%d", nbre_confs);
+ else
+ dmasprintf(value, "%d", nbre_dmmaps);
+ return 0;
+}
+
+/*************************************************************
+ * ENTRY METHOD
+/*************************************************************/
+/*#Device.DHCPv4.Server.Pool.{i}.!UCI:dhcp/dhcp/dmmap_dhcp*/
+int browseDhcpInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s;
+ char *interface, *idhcp = NULL, *idhcp_last = NULL, *v;
+ struct dhcp_args curr_dhcp_args = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap("dhcp", "dhcp", "dmmap_dhcp", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ dmuci_get_value_by_section_string(p->config_section, "interface", &interface);
+ init_dhcp_args(&curr_dhcp_args, p->config_section, interface);
+ idhcp = handle_update_instance(1, dmctx, &idhcp_last, update_instance_alias_icwmpd, 3, p->dmmap_section, "dhcp_instance", "dhcp_alias");
+ dmuci_get_value_by_section_string(p->dmmap_section, "order", &v);
+ if(v==NULL || strlen(v) == 0)
+ set_section_order("dhcp", "dmmap_dhcp", "dhcp", p->dmmap_section, p->config_section, 0, idhcp);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_dhcp_args, idhcp) == DM_STOP)
+ break;
+ }
+
+ free_dmmap_config_dup_list(&dup_list);
+
+ return 0;
+}
+
+/*#Device.DHCPv4.Server.Pool.{i}.StaticAddress.{i}.!UCI:dhcp/host/dmmap_dhcp*/
+int browseDhcpStaticInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *sss = NULL;
+ char *idhcp = NULL, *idhcp_last = NULL;
+ struct dhcp_static_args curr_dhcp_staticargs = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap_cont("dhcp", "host", "dmmap_dhcp", "dhcp", ((struct dhcp_args *)prev_data)->interface, &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ idhcp = handle_update_instance(2, dmctx, &idhcp_last, update_instance_alias_icwmpd, 3, p->dmmap_section, "ldhcpinstance", "ldhcpalias");
+ init_args_dhcp_host(&curr_dhcp_staticargs, p->config_section);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_dhcp_staticargs, idhcp) == DM_STOP)
+ break;
+ }
+
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
+
+int browseDhcpClientInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *sss = NULL;
+ char *idx = NULL, *idx_last = NULL;
+ json_object *res = NULL, *client_obj = NULL;
+ char *dhcp, *network;
+ int id = 0;
+ struct client_args curr_dhcp_client_args = {0};
+
+ dmubus_call("router.network", "clients", UBUS_ARGS{}, 0, &res);
+ if (res) {
+ json_object_object_foreach(res, key, client_obj) {
+ dhcp = dmjson_get_value(client_obj, 1, "dhcp");
+ if(strcmp(dhcp, "true") == 0)
+ {
+ network = dmjson_get_value(client_obj, 1, "network");
+ if(strcmp(network, ((struct dhcp_args *)prev_data)->interface) == 0)
+ {
+ init_dhcp_client_args(&curr_dhcp_client_args, client_obj, key);
+ idx = handle_update_instance(2, dmctx, &idx_last, update_instance_without_section, 1, ++id);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_dhcp_client_args, idx) == DM_STOP)
+ break;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int browseDhcpClientIPv4Inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ unsigned int leasetime;
+ char *macaddr;
+ char mac[32], ip[32], buf[512];
+ json_object *passed_args;
+ FILE *fp;
+ struct dhcp_client_ipv4address_args current_dhcp_client_ipv4address_args = {0};
+ int id = 0;
+ char *idx = NULL, *idx_last = NULL;
+
+ fp = fopen(DHCP_LEASES_FILE, "r");
+ if (fp == NULL)
+ return 0;
+ while (fgets (buf , 256 , fp) != NULL) {
+ sscanf(buf, "%u %s %s", &leasetime, mac, ip);
+ passed_args= ((struct client_args*)prev_data)->client;
+ macaddr=dmjson_get_value(passed_args, 1, "macaddr");
+ if(!strcmp(mac, macaddr)){
+ current_dhcp_client_ipv4address_args.ip= dmstrdup(ip);
+ current_dhcp_client_ipv4address_args.mac= dmstrdup(macaddr);
+ current_dhcp_client_ipv4address_args.leasetime= leasetime;
+
+ idx = handle_update_instance(2, dmctx, &idx_last, update_instance_without_section, 1, ++id);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)¤t_dhcp_client_ipv4address_args, idx) == DM_STOP)
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*#Device.DHCPv4.Client.{i}.!UCI:network/interface/dmmap_dhcp_client*/
+int browseDHCPv4ClientInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ char *instance, *instnbr = NULL, *v;
+ struct dmmap_dup *p;
+ char *type, *ipv4addr = "", *ipv6addr = "", *proto, *inst, *mask4= NULL;
+ json_object *res, *jobj;
+ struct dhcp_client_args dhcp_client_arg = {0};
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap_eq_no_delete("network", "interface", "dmmap_dhcp_client", "proto", "dhcp", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+
+ if(p->config_section != NULL){
+
+ dmuci_get_value_by_section_string(p->config_section, "type", &type);
+ if (strcmp(type, "alias") == 0 || strcmp(section_name(p->config_section), "loopback")==0)
+ continue;
+
+ dmuci_get_value_by_section_string(p->config_section, "ipaddr", &ipv4addr);
+ dmuci_get_value_by_section_string(p->config_section, "netmask", &mask4);
+ if (ipv4addr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(p->config_section), String}}, 1, &res);
+ if (res)
+ {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ ipv4addr = dmjson_get_value(jobj, 1, "address");
+ mask4= dmjson_get_value(jobj, 1, "mask");
+ }
+ }
+
+ dmuci_get_value_by_section_string(p->config_section, "ip6addr", &ipv6addr);
+ if (ipv6addr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(p->config_section), String}}, 1, &res);
+ if (res)
+ {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv6-address");
+ ipv6addr = dmjson_get_value(jobj, 1, "address");
+ }
+ }
+
+ dmuci_get_value_by_section_string(p->config_section, "proto", &proto);
+ dmuci_get_value_by_section_string(p->config_section, "ip_int_instance", &inst);
+
+ if (ipv4addr[0] == '\0' && ipv6addr[0] == '\0' && strcmp(proto, "dhcp") != 0 && strcmp(proto, "dhcpv6") != 0 && strcmp(inst, "") == 0 && strcmp(type, "bridge") != 0) {
+ p->config_section=NULL;
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, p->dmmap_section, "section_name", "");
+ }
+ }
+
+ if (ipv4addr == NULL || strlen(ipv4addr)==0)
+ dhcp_client_arg.ip = dmstrdup("");
+ else
+ dhcp_client_arg.ip = dmstrdup(ipv4addr);
+ if (mask4 == NULL || strlen(mask4)==0)
+ dhcp_client_arg.mask = dmstrdup("");
+ else
+ dhcp_client_arg.mask = dmstrdup(mask4);
+
+ dhcp_client_arg.dhcp_client_conf = p->config_section;
+ dhcp_client_arg.dhcp_client_dm= p->dmmap_section;
+
+ instance= handle_update_instance(1, dmctx, &instnbr, update_instance_alias_icwmpd, 3, (void *)p->dmmap_section, "cwmp_dhcpv4client_instance", "cwmp_dhcpv4client_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, &dhcp_client_arg, instance) == DM_STOP)
+ break;
+ }
+ return 0;
+}
+
+int browseDHCPv4ClientSentOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)prev_data;
+ struct uci_section *dmmap_sect;
+ struct dhcp_client_option_args dhcp_client_opt_args = {0};
+ char *instance, *instnbr = NULL, *v1, *v2, **sentopts, **buf= NULL, *tmp, *optionvalue, *v= NULL;
+ int length= 0, lgh2, i, j;
+
+ if(dhcp_client_args->dhcp_client_conf != NULL)
+ dmuci_get_value_by_section_string(dhcp_client_args->dhcp_client_conf, "sendopts", &v);
+
+ if(v != NULL)
+ sentopts= strsplit(v, " ", &length);
+
+ check_create_dmmap_package("dmmap_dhcp_client");
+
+ for (i= 0; idhcp_client_conf), "option_tag", buf[0])) == NULL) {
+ dmuci_add_section_icwmpd("dmmap_dhcp_client", "send_option", &dmmap_sect, &v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "option_tag", buf[0]);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(dhcp_client_args->dhcp_client_conf));
+ }
+ optionvalue=dmstrdup(buf[1]);
+ if(lgh2>2){
+ for(j=2; jdhcp_client_conf?section_name(dhcp_client_args->dhcp_client_conf):"", dmmap_sect) {
+ dmuci_get_value_by_section_string(dmmap_sect, "option_tag", &v1);
+ dmuci_get_value_by_section_string(dmmap_sect, "option_value", &v2);
+ dhcp_client_opt_args.client_sect= dhcp_client_args->dhcp_client_conf;
+ dhcp_client_opt_args.option_tag= dmstrdup(v1);
+ dhcp_client_opt_args.value= dmstrdup(v2);
+ dhcp_client_opt_args.opt_sect= dmmap_sect;
+
+ instance= handle_update_instance(1, dmctx, &instnbr, update_instance_alias_icwmpd, 3, dmmap_sect, "cwmp_dhcpv4_sentopt_instance", "cwmp_dhcpv4_sentopt_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, &dhcp_client_opt_args, instance) == DM_STOP)
+ break;
+ }
+ return 0;
+}
+
+int browseDHCPv4ClientReqOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct dhcp_client_args *dhcp_client_args = (struct dhcp_client_args*)prev_data;
+ struct uci_section *dmmap_sect;
+ struct dhcp_client_option_args dhcp_client_opt_args = {0};
+ char *instance, *instnbr = NULL, *v1, **reqtopts, *v= NULL;
+ int length= 0, lgh2, i, j;
+
+ if (dhcp_client_args->dhcp_client_conf != NULL)
+ dmuci_get_value_by_section_string(dhcp_client_args->dhcp_client_conf, "reqopts", &v);
+ if (v!= NULL)
+ reqtopts= strsplit(v, " ", &length);
+
+ check_create_dmmap_package("dmmap_dhcp_client");
+ for (i= 0; idhcp_client_conf), "option_tag", reqtopts[i])) == NULL) {
+ dmuci_add_section_icwmpd("dmmap_dhcp_client", "req_option", &dmmap_sect, &v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "option_tag", reqtopts[i]);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(dhcp_client_args->dhcp_client_conf));
+ }
+ }
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_dhcp_client", "req_option", "section_name", dhcp_client_args->dhcp_client_conf?section_name(dhcp_client_args->dhcp_client_conf):"", dmmap_sect) {
+ dmuci_get_value_by_section_string(dmmap_sect, "option_tag", &v1);
+ dhcp_client_opt_args.client_sect= dhcp_client_args->dhcp_client_conf;
+ dhcp_client_opt_args.option_tag= dmstrdup(v1);
+ dhcp_client_opt_args.value= dmstrdup("");
+ dhcp_client_opt_args.opt_sect= dmmap_sect;
+
+ instance= handle_update_instance(1, dmctx, &instnbr, update_instance_alias_icwmpd, 3, dmmap_sect, "cwmp_dhcpv4_reqtopt_instance", "cwmp_dhcpv4_reqtopt_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, &dhcp_client_opt_args, instance) == DM_STOP)
+ break;
+ }
+ return 0;
+}
+
+int browseDHCPv4ServerPoolOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_list *dhcp_options_list = NULL;
+ struct uci_element *e;
+ struct dhcp_args *curr_dhcp_args = (struct dhcp_args*)prev_data;
+ struct uci_section *dmmap_sect;
+ char **tagvalue= NULL;
+ char *instance, *instnbr = NULL, *optionvalue= NULL, *tmp, *v1, *v2, *v;
+ int length, j;
+ struct dhcp_client_option_args dhcp_client_opt_args = {0};
+
+ dmuci_get_value_by_section_list(curr_dhcp_args->dhcp_sec, "dhcp_option", &dhcp_options_list);
+ if (dhcp_options_list != NULL) {
+ uci_foreach_element(dhcp_options_list, e) {
+ tagvalue= strsplit(e->name, ",", &length);
+ if ((dmmap_sect = get_dup_section_in_dmmap_eq("dmmap_dhcp", "servpool_option", section_name(curr_dhcp_args->dhcp_sec), "option_tag", tagvalue[0])) == NULL) {
+ dmuci_add_section_icwmpd("dmmap_dhcp", "servpool_option", &dmmap_sect, &v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "option_tag", tagvalue[0]);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(curr_dhcp_args->dhcp_sec));
+ }
+ optionvalue=dmstrdup(tagvalue[1]);
+ if(length>2){
+ for(j=2; jdhcp_sec), dmmap_sect) {
+ dmuci_get_value_by_section_string(dmmap_sect, "option_tag", &v1);
+ dmuci_get_value_by_section_string(dmmap_sect, "option_value", &v2);
+ dhcp_client_opt_args.client_sect= curr_dhcp_args->dhcp_sec;
+ dhcp_client_opt_args.option_tag= strdup(v1);
+ dhcp_client_opt_args.value= strdup(v2);
+ dhcp_client_opt_args.opt_sect= dmmap_sect;
+ instance= handle_update_instance(1, dmctx, &instnbr, update_instance_alias_icwmpd, 3, dmmap_sect, "cwmp_dhcpv4_servpool_option_instance", "cwmp_dhcpv4_servpool_option_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, &dhcp_client_opt_args, instance) == DM_STOP)
+ break;
+ }
+ return 0;
+}
+
+int browseDHCPv4ServerPoolClientOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ //TODO
+ return 0;
+}
+
+char *get_dhcp_network_from_relay_list(char *net_list){
+ struct uci_section *s;
+ char **net_list_arr, *v;
+ int length, i;
+
+ net_list_arr= strsplit(net_list, " ", &length);
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "proto", &v);
+ for(i=0; iconfig_section != NULL){
+
+ dmuci_get_value_by_section_string(p->config_section, "type", &type);
+
+ if (strcmp(type, "alias") == 0 || strcmp(section_name(p->config_section), "loopback")==0)
+ continue;
+
+ dmuci_get_value_by_section_string(p->config_section, "ipaddr", &ipv4addr);
+
+ dmuci_get_value_by_section_string(p->config_section, "netmask", &mask4);
+
+ if (ipv4addr[0] == '\0') {
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(p->config_section), String}}, 1, &res);
+
+ if (res)
+ {
+
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+
+ ipv4addr = dmjson_get_value(jobj, 1, "address");
+
+ mask4= dmjson_get_value(jobj, 1, "mask");
+
+ }
+
+ }
+
+ dmuci_get_value_by_section_string(p->config_section, "ip6addr", &ipv6addr);
+
+ if (ipv6addr[0] == '\0') {
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(p->config_section), String}}, 1, &res);
+
+ if (res)
+ {
+
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv6-address");
+
+ ipv6addr = dmjson_get_value(jobj, 1, "address");
+
+ }
+
+ }
+
+ dmuci_get_value_by_section_string(p->config_section, "proto", &proto);
+
+ dmuci_get_value_by_section_string(p->config_section, "ip_int_instance", &inst);
+
+ if (ipv4addr[0] == '\0' && ipv6addr[0] == '\0' && strcmp(inst, "") == 0 && strcmp(type, "bridge") != 0 && strcmp(proto, "relay") != 0) {
+ p->config_section=NULL;
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, p->dmmap_section, "section_name", "");
+ }
+
+ }
+
+ if (ipv4addr == NULL || strlen(ipv4addr)==0)
+ dhcp_relay_arg.ip = dmstrdup("");
+ else
+ dhcp_relay_arg.ip = dmstrdup(ipv4addr);
+ if (mask4 == NULL || strlen(mask4)==0)
+ dhcp_relay_arg.mask = dmstrdup("");
+ else
+ dhcp_relay_arg.mask = dmstrdup(mask4);
+ if(p->config_section != NULL)
+ dmuci_get_value_by_section_string(p->config_section, "network", &v);
+ else
+ v= dmstrdup("");
+
+ dhcp_network= get_dhcp_network_from_relay_list(v);
+ if(dhcp_network && strlen(dhcp_network)>0){
+ dhcp_relay_arg.macclassifier= get_dhcp_classifier("mac", dhcp_network);
+ dhcp_relay_arg.vendorclassidclassifier= get_dhcp_classifier("vendorclass", dhcp_network);
+ dhcp_relay_arg.userclassclassifier= get_dhcp_classifier("userclass", dhcp_network);
+ } else {
+ dhcp_relay_arg.macclassifier= NULL;
+ dhcp_relay_arg.vendorclassidclassifier= NULL;
+ dhcp_relay_arg.userclassclassifier= NULL;
+ }
+ dhcp_relay_arg.dhcp_client_conf = p->config_section;
+
+ dhcp_relay_arg.dhcp_client_dm= p->dmmap_section;
+ instance= handle_update_instance(1, dmctx, &instnbr, update_instance_alias_icwmpd, 3, (void *)p->dmmap_section, "cwmp_dhcpv4relay_instance", "cwmp_dhcpv4relay_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, &dhcp_relay_arg, instance) == DM_STOP)
+ break;
+
+
+ }
+ return 0;
+}
diff --git a/dmtree/tr181/dhcpv4.h b/dmtree/tr181/dhcpv4.h
new file mode 100644
index 00000000..2486233a
--- /dev/null
+++ b/dmtree/tr181/dhcpv4.h
@@ -0,0 +1,241 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2016 Inteno Broadband Technology AB
+ * Author: Anis Ellouze
+ *
+ */
+
+#ifndef __DHCP_H
+#define __DHCP_H
+
+#include
+
+struct dhcp_args
+{
+ struct uci_section *dhcp_sec;
+ char *interface;
+};
+
+struct dhcp_static_args
+{
+ struct uci_section *dhcpsection;
+};
+
+struct client_args
+{
+ json_object *client;
+ char *key;
+};
+
+struct dhcp_client_ipv4address_args {
+ char *mac;
+ char *ip;
+ unsigned int leasetime;
+};
+
+struct dhcp_client_args {
+ struct uci_section *dhcp_client_conf;
+ struct uci_section *dhcp_client_dm;
+ struct uci_section *macclassifier;
+ struct uci_section *vendorclassidclassifier;
+ struct uci_section *userclassclassifier;
+ char *ip;
+ char *mask;
+};
+
+struct dhcp_client_option_args {
+ struct uci_section *opt_sect;
+ struct uci_section *client_sect;
+ char *option_tag;
+ char *value;
+};
+
+extern DMOBJ tDhcpv4Obj[];
+extern DMOBJ tDhcpv4ServerObj[];
+extern DMOBJ tDhcpServerPoolObj[];
+extern DMOBJ tDhcpServerPoolClientObj[];
+extern DMLEAF tDhcpServerPoolParams[];
+extern DMLEAF tDhcpServerPoolAddressParams[];
+extern DMLEAF tDhcpServerPoolClientParams[];
+extern DMLEAF tDhcpServerPoolClientIPv4AddressParams[];
+
+extern DMLEAF tDHCPv4Params[];
+extern DMOBJ tDHCPv4ClientObj[];
+extern DMLEAF tDHCPv4ClientParams[];
+extern DMLEAF tDHCPv4ClientSentOptionParams[];
+extern DMLEAF tDHCPv4ClientReqOptionParams[];
+extern DMOBJ tDHCPv4ServerObj[];
+extern DMLEAF tDHCPv4ServerParams[];
+extern DMLEAF tDHCPv4ServerPoolOptionParams[];
+extern DMLEAF tDHCPv4ServerPoolClientIPv4AddressParams[];
+extern DMLEAF tDHCPv4ServerPoolClientOptionParams[];
+extern DMOBJ tDHCPv4RelayObj[];
+extern DMLEAF tDHCPv4RelayParams[];
+extern DMLEAF tDHCPv4RelayForwardingParams[];
+
+int browseDhcpInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDhcpStaticInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDhcpClientInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDhcpClientIPv4Inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv4ClientInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv4ClientSentOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv4ClientReqOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv4ServerPoolOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv4ServerPoolClientOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv4RelayForwardingInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int add_dhcp_server(char *refparam, struct dmctx *ctx, void *data, char **instancepara);
+int delete_dhcp_server(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int add_dhcp_staticaddress(char *refparam, struct dmctx *ctx, void *data, char **instancepara);
+int delete_dhcp_staticaddress(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int addObjDHCPv4Client(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjDHCPv4Client(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int addObjDHCPv4ClientSentOption(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjDHCPv4ClientSentOption(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int addObjDHCPv4ClientReqOption(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjDHCPv4ClientReqOption(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int addObjDHCPv4ServerPoolOption(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjDHCPv4ServerPoolOption(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int addObjDHCPv4RelayForwarding(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjDHCPv4RelayForwarding(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+
+int get_server_pool_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_configurable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_interval_address_min(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_interval_address_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_reserved_addresses(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_subnetmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_iprouters(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_leasetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_domainname(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_static_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_staticaddress_chaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_staticaddress_yiaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_client_chaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_client_ipv4address_ip_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_client_ipv4address_leasetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_sever_pool_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_static_address_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_option_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_clients_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_dhcp_client_active(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int set_server_pool_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_configurable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_address_min(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_address_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_reserved_addresses(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_subnetmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_iprouters(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_leasetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_domainname(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_interface_linker_parameter(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_static_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_staticaddress_chaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_staticaddress_yiaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_dhcp_sever_pool_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int get_dhcp_client_linker(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+int set_section_order(char *package, char *dmpackage, char* sect_type, struct uci_section *dmmap_sect, struct uci_section *conf, int set_force, char* order);
+
+int get_DHCPv4_ClientNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Client_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4Client_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4Client_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4Client_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4Client_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4Client_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4Client_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Client_DHCPStatus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Client_Renew(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4Client_Renew(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4Client_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Client_SubnetMask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Client_IPRouters(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Client_DNSServers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Client_LeaseTimeRemaining(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Client_DHCPServer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Client_PassthroughEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4Client_PassthroughEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4Client_PassthroughDHCPPool(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4Client_PassthroughDHCPPool(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4Client_SentOptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Client_ReqOptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4ClientSentOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ClientSentOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ClientSentOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ClientSentOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ClientSentOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ClientSentOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ClientSentOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ClientSentOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ClientReqOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ClientReqOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ClientReqOption_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ClientReqOption_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ClientReqOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ClientReqOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ClientReqOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ClientReqOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ClientReqOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Server_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4Server_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ServerPoolOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ServerPoolOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4Server_PoolNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4ServerPoolOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ServerPoolOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ServerPoolOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ServerPoolOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ServerPoolOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4ServerPoolOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ServerPoolClientOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4RelayForwarding_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4RelayForwarding_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_VendorClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_VendorClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_VendorClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_VendorClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_VendorClassIDMode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_VendorClassIDMode(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_ClientID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_ClientID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_ClientIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_ClientIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_UserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_UserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_UserClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_UserClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_Chaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_Chaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_ChaddrMask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_ChaddrMask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_ChaddrExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_ChaddrExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_LocallyServed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_LocallyServed(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4RelayForwarding_DHCPServerIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4RelayForwarding_DHCPServerIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4ServerPoolClientOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Relay_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv4Relay_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv4Relay_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv4Relay_ForwardingNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+#endif
diff --git a/dmtree/tr181/dhcpv6.c b/dmtree/tr181/dhcpv6.c
new file mode 100644
index 00000000..5907efdd
--- /dev/null
+++ b/dmtree/tr181/dhcpv6.c
@@ -0,0 +1,2076 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Omar Kallel
+*/
+
+#include
+#include
+#include
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcwmp.h"
+#include "dmcommon.h"
+#include "dmentry.h"
+#include "dhcpv4.h"
+#include "dhcpv6.h"
+#include "dmjson.h"
+
+/* *** Device.DHCPv6. *** */
+DMOBJ tDHCPv6Obj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Client", &DMWRITE, addObjDHCPv6Client, delObjDHCPv6Client, NULL, browseDHCPv6ClientInst, NULL, NULL, tDHCPv6ClientObj, tDHCPv6ClientParams, NULL, BBFDM_BOTH},
+{"Server", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDHCPv6ServerObj, tDHCPv6ServerParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDHCPv6Params[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"ClientNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv6_ClientNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Client.{i}. *** */
+DMOBJ tDHCPv6ClientObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Server", &DMREAD, NULL, NULL, NULL, browseDHCPv6ClientServerInst, NULL, NULL, NULL, tDHCPv6ClientServerParams, NULL, BBFDM_BOTH},
+{"SentOption", &DMWRITE, addObjDHCPv6ClientSentOption, delObjDHCPv6ClientSentOption, NULL, browseDHCPv6ClientSentOptionInst, NULL, NULL, NULL, tDHCPv6ClientSentOptionParams, NULL, BBFDM_BOTH},
+{"ReceivedOption", &DMREAD, NULL, NULL, NULL, browseDHCPv6ClientReceivedOptionInst, NULL, NULL, NULL, tDHCPv6ClientReceivedOptionParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDHCPv6ClientParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv6Client_Enable, set_DHCPv6Client_Enable, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DHCPv6Client_Alias, set_DHCPv6Client_Alias, NULL, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_DHCPv6Client_Interface, set_DHCPv6Client_Interface, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_DHCPv6Client_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"DUID", &DMREAD, DMT_HEXBIN, get_DHCPv6Client_DUID, NULL, NULL, NULL, BBFDM_BOTH},
+{"RequestAddresses", &DMWRITE, DMT_BOOL, get_DHCPv6Client_RequestAddresses, set_DHCPv6Client_RequestAddresses, NULL, NULL, BBFDM_BOTH},
+{"RequestPrefixes", &DMWRITE, DMT_BOOL, get_DHCPv6Client_RequestPrefixes, set_DHCPv6Client_RequestPrefixes, NULL, NULL, BBFDM_BOTH},
+{"RapidCommit", &DMWRITE, DMT_BOOL, get_DHCPv6Client_RapidCommit, set_DHCPv6Client_RapidCommit, NULL, NULL, BBFDM_BOTH},
+{"Renew", &DMWRITE, DMT_BOOL, get_DHCPv6Client_Renew, set_DHCPv6Client_Renew, NULL, NULL, BBFDM_BOTH},
+{"SuggestedT1", &DMWRITE, DMT_INT, get_DHCPv6Client_SuggestedT1, set_DHCPv6Client_SuggestedT1, NULL, NULL, BBFDM_BOTH},
+{"SuggestedT2", &DMWRITE, DMT_INT, get_DHCPv6Client_SuggestedT2, set_DHCPv6Client_SuggestedT2, NULL, NULL, BBFDM_BOTH},
+{"SupportedOptions", &DMREAD, DMT_STRING, get_DHCPv6Client_SupportedOptions, NULL, NULL, NULL, BBFDM_BOTH},
+{"RequestedOptions", &DMWRITE, DMT_STRING, get_DHCPv6Client_RequestedOptions, set_DHCPv6Client_RequestedOptions, NULL, NULL, BBFDM_BOTH},
+{"ServerNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv6Client_ServerNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"SentOptionNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv6Client_SentOptionNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"ReceivedOptionNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv6Client_ReceivedOptionNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Client.{i}.Server.{i}. *** */
+DMLEAF tDHCPv6ClientServerParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"SourceAddress", &DMREAD, DMT_STRING, get_DHCPv6ClientServer_SourceAddress, NULL, NULL, NULL, BBFDM_BOTH},
+{"DUID", &DMREAD, DMT_HEXBIN, get_DHCPv6ClientServer_DUID, NULL, NULL, NULL, BBFDM_BOTH},
+{"InformationRefreshTime", &DMREAD, DMT_TIME, get_DHCPv6ClientServer_InformationRefreshTime, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Client.{i}.SentOption.{i}. *** */
+DMLEAF tDHCPv6ClientSentOptionParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv6ClientSentOption_Enable, set_DHCPv6ClientSentOption_Enable, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DHCPv6ClientSentOption_Alias, set_DHCPv6ClientSentOption_Alias, NULL, NULL, BBFDM_BOTH},
+{"Tag", &DMWRITE, DMT_UNINT, get_DHCPv6ClientSentOption_Tag, set_DHCPv6ClientSentOption_Tag, NULL, NULL, BBFDM_BOTH},
+{"Value", &DMWRITE, DMT_HEXBIN, get_DHCPv6ClientSentOption_Value, set_DHCPv6ClientSentOption_Value, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Client.{i}.ReceivedOption.{i}. *** */
+DMLEAF tDHCPv6ClientReceivedOptionParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Tag", &DMREAD, DMT_UNINT, get_DHCPv6ClientReceivedOption_Tag, NULL, NULL, NULL, BBFDM_BOTH},
+{"Value", &DMREAD, DMT_HEXBIN, get_DHCPv6ClientReceivedOption_Value, NULL, NULL, NULL, BBFDM_BOTH},
+{"Server", &DMREAD, DMT_STRING, get_DHCPv6ClientReceivedOption_Server, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Server. *** */
+DMOBJ tDHCPv6ServerObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Pool", &DMWRITE, addObjDHCPv6ServerPool, delObjDHCPv6ServerPool, NULL, browseDHCPv6ServerPoolInst, NULL, NULL, tDHCPv6ServerPoolObj, tDHCPv6ServerPoolParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDHCPv6ServerParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv6Server_Enable, set_DHCPv6Server_Enable, NULL, NULL, BBFDM_BOTH},
+{"PoolNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv6Server_PoolNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Server.Pool.{i}. *** */
+DMOBJ tDHCPv6ServerPoolObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Client", &DMREAD, NULL, NULL, NULL, browseDHCPv6ServerPoolClientInst, NULL, NULL, tDHCPv6ServerPoolClientObj, tDHCPv6ServerPoolClientParams, NULL, BBFDM_BOTH},
+{"Option", &DMWRITE, addObjDHCPv6ServerPoolOption, delObjDHCPv6ServerPoolOption, NULL, browseDHCPv6ServerPoolOptionInst, NULL, NULL, NULL, tDHCPv6ServerPoolOptionParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDHCPv6ServerPoolParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv6ServerPool_Enable, set_DHCPv6ServerPool_Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_DHCPv6ServerPool_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DHCPv6ServerPool_Alias, set_DHCPv6ServerPool_Alias, NULL, NULL, BBFDM_BOTH},
+{"Order", &DMWRITE, DMT_UNINT, get_DHCPv6ServerPool_Order, set_DHCPv6ServerPool_Order, NULL, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_DHCPv6ServerPool_Interface, set_DHCPv6ServerPool_Interface, NULL, NULL, BBFDM_BOTH},
+{"DUID", &DMWRITE, DMT_HEXBIN, get_DHCPv6ServerPool_DUID, set_DHCPv6ServerPool_DUID, NULL, NULL, BBFDM_BOTH},
+{"DUIDExclude", &DMWRITE, DMT_BOOL, get_DHCPv6ServerPool_DUIDExclude, set_DHCPv6ServerPool_DUIDExclude, NULL, NULL, BBFDM_BOTH},
+{"VendorClassID", &DMWRITE, DMT_HEXBIN, get_DHCPv6ServerPool_VendorClassID, set_DHCPv6ServerPool_VendorClassID, NULL, NULL, BBFDM_BOTH},
+{"VendorClassIDExclude", &DMWRITE, DMT_BOOL, get_DHCPv6ServerPool_VendorClassIDExclude, set_DHCPv6ServerPool_VendorClassIDExclude, NULL, NULL, BBFDM_BOTH},
+{"UserClassID", &DMWRITE, DMT_HEXBIN, get_DHCPv6ServerPool_UserClassID, set_DHCPv6ServerPool_UserClassID, NULL, NULL, BBFDM_BOTH},
+{"UserClassIDExclude", &DMWRITE, DMT_BOOL, get_DHCPv6ServerPool_UserClassIDExclude, set_DHCPv6ServerPool_UserClassIDExclude, NULL, NULL, BBFDM_BOTH},
+{"SourceAddress", &DMWRITE, DMT_STRING, get_DHCPv6ServerPool_SourceAddress, set_DHCPv6ServerPool_SourceAddress, NULL, NULL, BBFDM_BOTH},
+{"SourceAddressMask", &DMWRITE, DMT_STRING, get_DHCPv6ServerPool_SourceAddressMask, set_DHCPv6ServerPool_SourceAddressMask, NULL, NULL, BBFDM_BOTH},
+{"SourceAddressExclude", &DMWRITE, DMT_BOOL, get_DHCPv6ServerPool_SourceAddressExclude, set_DHCPv6ServerPool_SourceAddressExclude, NULL, NULL, BBFDM_BOTH},
+{"IANAEnable", &DMWRITE, DMT_BOOL, get_DHCPv6ServerPool_IANAEnable, set_DHCPv6ServerPool_IANAEnable, NULL, NULL, BBFDM_BOTH},
+{"IANAManualPrefixes", &DMWRITE, DMT_STRING, get_DHCPv6ServerPool_IANAManualPrefixes, set_DHCPv6ServerPool_IANAManualPrefixes, NULL, NULL, BBFDM_BOTH},
+{"IANAPrefixes", &DMREAD, DMT_STRING, get_DHCPv6ServerPool_IANAPrefixes, NULL, NULL, NULL, BBFDM_BOTH},
+{"IAPDEnable", &DMWRITE, DMT_BOOL, get_DHCPv6ServerPool_IAPDEnable, set_DHCPv6ServerPool_IAPDEnable, NULL, NULL, BBFDM_BOTH},
+{"IAPDManualPrefixes", &DMWRITE, DMT_STRING, get_DHCPv6ServerPool_IAPDManualPrefixes, set_DHCPv6ServerPool_IAPDManualPrefixes, NULL, NULL, BBFDM_BOTH},
+{"IAPDPrefixes", &DMREAD, DMT_STRING, get_DHCPv6ServerPool_IAPDPrefixes, NULL, NULL, NULL, BBFDM_BOTH},
+{"IAPDAddLength", &DMWRITE, DMT_UNINT, get_DHCPv6ServerPool_IAPDAddLength, set_DHCPv6ServerPool_IAPDAddLength, NULL, NULL, BBFDM_BOTH},
+{"ClientNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv6ServerPool_ClientNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"OptionNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv6ServerPool_OptionNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Server.Pool.{i}.Client.{i}. *** */
+DMOBJ tDHCPv6ServerPoolClientObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"IPv6Address", &DMREAD, NULL, NULL, NULL, browseDHCPv6ServerPoolClientIPv6AddressInst, NULL, NULL, NULL, tDHCPv6ServerPoolClientIPv6AddressParams, NULL, BBFDM_BOTH},
+{"IPv6Prefix", &DMREAD, NULL, NULL, NULL, browseDHCPv6ServerPoolClientIPv6PrefixInst, NULL, NULL, NULL, tDHCPv6ServerPoolClientIPv6PrefixParams, NULL, BBFDM_BOTH},
+{"Option", &DMREAD, NULL, NULL, NULL, browseDHCPv6ServerPoolClientOptionInst, NULL, NULL, NULL, tDHCPv6ServerPoolClientOptionParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDHCPv6ServerPoolClientParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_DHCPv6ServerPoolClient_Alias, set_DHCPv6ServerPoolClient_Alias, NULL, NULL, BBFDM_BOTH},
+{"SourceAddress", &DMREAD, DMT_STRING, get_DHCPv6ServerPoolClient_SourceAddress, NULL, NULL, NULL, BBFDM_BOTH},
+{"Active", &DMREAD, DMT_BOOL, get_DHCPv6ServerPoolClient_Active, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPv6AddressNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv6ServerPoolClient_IPv6AddressNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPv6PrefixNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv6ServerPoolClient_IPv6PrefixNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"OptionNumberOfEntries", &DMREAD, DMT_UNINT, get_DHCPv6ServerPoolClient_OptionNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Server.Pool.{i}.Client.{i}.IPv6Address.{i}. *** */
+DMLEAF tDHCPv6ServerPoolClientIPv6AddressParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"IPAddress", &DMREAD, DMT_STRING, get_DHCPv6ServerPoolClientIPv6Address_IPAddress, NULL, NULL, NULL, BBFDM_BOTH},
+{"PreferredLifetime", &DMREAD, DMT_TIME, get_DHCPv6ServerPoolClientIPv6Address_PreferredLifetime, NULL, NULL, NULL, BBFDM_BOTH},
+{"ValidLifetime", &DMREAD, DMT_TIME, get_DHCPv6ServerPoolClientIPv6Address_ValidLifetime, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Server.Pool.{i}.Client.{i}.IPv6Prefix.{i}. *** */
+DMLEAF tDHCPv6ServerPoolClientIPv6PrefixParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Prefix", &DMREAD, DMT_STRING, get_DHCPv6ServerPoolClientIPv6Prefix_Prefix, NULL, NULL, NULL, BBFDM_BOTH},
+{"PreferredLifetime", &DMREAD, DMT_TIME, get_DHCPv6ServerPoolClientIPv6Prefix_PreferredLifetime, NULL, NULL, NULL, BBFDM_BOTH},
+{"ValidLifetime", &DMREAD, DMT_TIME, get_DHCPv6ServerPoolClientIPv6Prefix_ValidLifetime, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Server.Pool.{i}.Client.{i}.Option.{i}. *** */
+DMLEAF tDHCPv6ServerPoolClientOptionParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Tag", &DMREAD, DMT_UNINT, get_DHCPv6ServerPoolClientOption_Tag, NULL, NULL, NULL, BBFDM_BOTH},
+{"Value", &DMREAD, DMT_HEXBIN, get_DHCPv6ServerPoolClientOption_Value, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DHCPv6.Server.Pool.{i}.Option.{i}. *** */
+DMLEAF tDHCPv6ServerPoolOptionParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DHCPv6ServerPoolOption_Enable, set_DHCPv6ServerPoolOption_Enable, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DHCPv6ServerPoolOption_Alias, set_DHCPv6ServerPoolOption_Alias, NULL, NULL, BBFDM_BOTH},
+{"Tag", &DMWRITE, DMT_UNINT, get_DHCPv6ServerPoolOption_Tag, set_DHCPv6ServerPoolOption_Tag, NULL, NULL, BBFDM_BOTH},
+{"Value", &DMWRITE, DMT_HEXBIN, get_DHCPv6ServerPoolOption_Value, set_DHCPv6ServerPoolOption_Value, NULL, NULL, BBFDM_BOTH},
+{"PassthroughClient", &DMWRITE, DMT_STRING, get_DHCPv6ServerPoolOption_PassthroughClient, set_DHCPv6ServerPoolOption_PassthroughClient, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+struct uci_section* get_dhcpv6_classifier(char *classifier_name, char *network) {
+ struct uci_section* s= NULL;
+ char *v;
+
+ uci_foreach_sections("dhcp", classifier_name, s) {
+ dmuci_get_value_by_section_string(s, "networkid", &v);
+ if(strcmp(v, network) == 0)
+ return s;
+ }
+ return NULL;
+}
+
+inline int init_dhcpv6_client_args(struct clientv6_args *args, json_object *client, json_object *client_param, int i)
+{
+ args->client = client;
+ args->clientparam= client_param;
+ args->idx = i;
+ return 0;
+}
+
+struct uci_section* exist_other_section_dhcp6_same_order(struct uci_section *dmmap_sect, char * package, char* sect_type, char *order) {
+ struct uci_section *s;
+ uci_path_foreach_option_eq(icwmpd, package, sect_type, "order", order, s) {
+ if(strcmp(section_name(s), section_name(dmmap_sect)) != 0){
+ return s;
+ }
+ }
+ return NULL;
+}
+
+int set_section_dhcp6_order(char *package, char *dmpackage, char* sect_type, struct uci_section *dmmap_sect, struct uci_section *conf, int set_force, char* order) {
+ char *v= NULL, *sect_name, *incrorder;
+ struct uci_section *s, *dm;
+ dmuci_get_value_by_section_string(dmmap_sect, "order", &v);
+ if((v!=NULL || strlen(v)>0) && strcmp(v, order) == 0)
+ return 0;
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "order", order);
+ if(conf==NULL){
+ dmuci_get_value_by_section_string(dmmap_sect, "section_name", §_name);
+ get_config_section_of_dmmap_section(package, sect_type, sect_name, &s);
+ } else
+ s= conf;
+
+ if(strcmp(order, "1") != 0 && s!=NULL){
+ dmuci_set_value_by_section(s, "force", "");
+ }
+
+ if(set_force==1 && strcmp(order, "1") == 0 && s!=NULL) {
+ dmuci_set_value_by_section(s, "force", "1");
+ }
+
+ if ((dm = exist_other_section_dhcp6_same_order(dmmap_sect, dmpackage, sect_type, order)) != NULL) {
+ dmuci_get_value_by_section_string(dm, "section_name", §_name);
+ get_config_section_of_dmmap_section(package, sect_type, sect_name, &s);
+ dmasprintf(&incrorder, "%d", atoi(order)+1);
+ if(s!=NULL && strcmp(order, "1") == 0){
+ dmuci_set_value_by_section(s, "force", "");
+ }
+ set_section_dhcp6_order(package, dmpackage, sect_type, dm, s, set_force, incrorder);
+ }
+ return 0;
+
+}
+
+inline int init_dhcpv6_args(struct dhcpv6_args *args, struct uci_section *s, char *interface)
+{
+ args->interface = interface;
+ args->dhcp_sec = s;
+ return 0;
+}
+
+/*#Device.DHCPv6.Client.{i}.!UCI:network/interface/dmmap_dhcpv6*/
+int browseDHCPv6ClientInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ struct dmmap_dup *p;
+ struct dhcpv6_client_args dhcpv6_client_arg = {0};
+ json_object *res, *jobj;
+ char *instance, *instnbr = NULL, *proto= NULL, *ipv6addr;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap_eq_no_delete("network", "interface", "dmmap_dhcpv6", "proto", "dhcpv6", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(p->config_section), String}}, 1, &res);
+
+ if (res)
+ {
+
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv6-address");
+
+ ipv6addr = dmjson_get_value(jobj, 1, "address");
+
+ }
+ dhcpv6_client_arg.dhcp_client_conf = p->config_section;
+
+ dhcpv6_client_arg.dhcp_client_dm= p->dmmap_section;
+ dhcpv6_client_arg.ip= strdup(ipv6addr?ipv6addr:"");
+
+ instance = handle_update_instance(1, dmctx, &instnbr, update_instance_alias, 3, p->dmmap_section, "cwmp_dhcpv6client_instance", "cwmp_dhcpv6client_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, &dhcpv6_client_arg, instance) == DM_STOP)
+ break;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
+
+int browseDHCPv6ClientServerInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ //TODO
+ return 0;
+}
+
+int browseDHCPv6ClientSentOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ //TODO
+ return 0;
+}
+
+int browseDHCPv6ClientReceivedOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ //TODO
+ return 0;
+}
+
+/*#Device.DHCPv6.Server.Pool.{i}.!UCI:dhcp/dhcp/dmmap_dhcpv6*/
+int browseDHCPv6ServerPoolInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s;
+ char *interface, *idhcp = NULL, *idhcp_last = NULL, *v;
+ struct dhcpv6_args curr_dhcp6_args = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap_eq("dhcp", "dhcp", "dmmap_dhcpv6", "dhcpv6", "server", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ dmuci_get_value_by_section_string(p->config_section, "interface", &interface);
+ init_dhcpv6_args(&curr_dhcp6_args, p->config_section, interface);
+ idhcp = handle_update_instance(1, dmctx, &idhcp_last, update_instance_alias_icwmpd, 3, p->dmmap_section, "dhcpv6_serv_pool_instance", "dhcpv6_serv_pool_alias");
+ dmuci_get_value_by_section_string(p->dmmap_section, "order", &v);
+ if(v==NULL || strlen(v) == 0)
+ set_section_dhcp6_order("dhcp", "dmmap_dhcpv6", "dhcp", p->dmmap_section, p->config_section, 0, idhcp);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_dhcp6_args, idhcp) == DM_STOP)
+ break;
+ }
+
+ free_dmmap_config_dup_list(&dup_list);
+
+ return 0;
+}
+
+int browseDHCPv6ServerPoolClientInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct dhcpv6_args *dhcp_arg= (struct dhcpv6_args*)prev_data;
+ json_object *res, *res1, *jobj, *dev_obj= NULL, *net_obj= NULL;
+ struct clientv6_args curr_dhcp_client_args = {0};
+ char *device;
+ int i= 0;
+ char *idx = NULL, *idx_last = NULL;
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(dhcp_arg->dhcp_sec), String}}, 1, &res1);
+ device = dmjson_get_value(res1, 1, "device");
+ dmubus_call("dhcp", "ipv6leases", UBUS_ARGS{}, 0, &res);
+ if(!res)
+ return 0;
+ dev_obj = dmjson_get_obj(res, 1, "device");
+ if (!dev_obj)
+ return 0;
+
+ net_obj = dmjson_get_obj(dev_obj, 1, device);
+ if (!net_obj)
+ return 0;
+
+ while (1) {
+ jobj = dmjson_select_obj_in_array_idx(net_obj, i, 1, "leases");
+ if (jobj == NULL)
+ break;
+ init_dhcpv6_client_args(&curr_dhcp_client_args, jobj, NULL, i);
+ i++;
+ idx = handle_update_instance(2, dmctx, &idx_last, update_instance_without_section, 1, i);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_dhcp_client_args, idx) == DM_STOP)
+ break;
+ }
+ return 0;
+}
+
+int browseDHCPv6ServerPoolOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_list *dhcp_options_list = NULL;
+ struct uci_element *e;
+ struct dhcpv6_args *curr_dhcp_args = (struct dhcpv6_args*)prev_data;
+ struct uci_section *dmmap_sect;
+ char **tagvalue= NULL;
+ char *instance, *instnbr = NULL, *optionvalue= NULL, *tmp, *v1, *v2, *v;
+ int length, j;
+ struct dhcpv6_client_option_args dhcp_client_opt_args = {0};
+
+ dmuci_get_value_by_section_list(curr_dhcp_args->dhcp_sec, "dhcp_option", &dhcp_options_list);
+ if (dhcp_options_list != NULL) {
+ uci_foreach_element(dhcp_options_list, e) {
+ tagvalue= strsplit(e->name, ",", &length);
+ if ((dmmap_sect = get_dup_section_in_dmmap_eq("dmmap_dhcpv6", "servpool_option", section_name(curr_dhcp_args->dhcp_sec), "option_tag", tagvalue[0])) == NULL) {
+ dmuci_add_section_icwmpd("dmmap_dhcpv6", "servpool_option", &dmmap_sect, &v);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "option_tag", tagvalue[0]);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(curr_dhcp_args->dhcp_sec));
+ }
+ optionvalue=dmstrdup(tagvalue[1]);
+ if(length>2){
+ for(j=2; jdhcp_sec), dmmap_sect) {
+ dmuci_get_value_by_section_string(dmmap_sect, "option_tag", &v1);
+ dmuci_get_value_by_section_string(dmmap_sect, "option_value", &v2);
+ dhcp_client_opt_args.client_sect= curr_dhcp_args->dhcp_sec;
+ dhcp_client_opt_args.option_tag= strdup(v1);
+ dhcp_client_opt_args.value= strdup(v2);
+ dhcp_client_opt_args.opt_sect= dmmap_sect;
+ instance= handle_update_instance(1, dmctx, &instnbr, update_instance_alias_icwmpd, 3, dmmap_sect, "cwmp_dhcpv6_servpool_option_instance", "cwmp_dhcpv6_servpool_option_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, &dhcp_client_opt_args, instance) == DM_STOP)
+ break;
+ }
+ return 0;
+}
+
+int browseDHCPv6ServerPoolClientIPv6AddressInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct clientv6_args *dhcpv6_serv_pool_client= (struct clientv6_args *)prev_data;
+ json_object *address_obj= NULL, *prefix_obj= NULL;
+ struct clientv6_args curr_dhcv6_address_args = {0};
+ char *idx = NULL, *idx_last = NULL;
+ int i= 0;
+
+ while (1) {
+ address_obj = dmjson_select_obj_in_array_idx(dhcpv6_serv_pool_client->client, i, 1, "ipv6-addr");
+ if (address_obj == NULL)
+ break;
+ init_dhcpv6_client_args(&curr_dhcv6_address_args, dhcpv6_serv_pool_client->client, address_obj, i);
+ i++;
+ idx = handle_update_instance(2, dmctx, &idx_last, update_instance_without_section, 1, i);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_dhcv6_address_args, idx) == DM_STOP)
+ break;
+ }
+
+ return 0;
+}
+
+int browseDHCPv6ServerPoolClientIPv6PrefixInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct clientv6_args *dhcpv6_serv_pool_client= (struct clientv6_args *)prev_data;
+ json_object *address_obj= NULL, *prefix_obj= NULL;
+ struct clientv6_args curr_dhcv6_address_args = {0};
+ char *idx = NULL, *idx_last = NULL;
+ int i= 0;
+
+ while (1) {
+ address_obj = dmjson_select_obj_in_array_idx(dhcpv6_serv_pool_client->client, i, 1, "ipv6-prefix");
+ if (address_obj == NULL)
+ break;
+ init_dhcpv6_client_args(&curr_dhcv6_address_args, dhcpv6_serv_pool_client->client, address_obj, i);
+ i++;
+ idx = handle_update_instance(2, dmctx, &idx_last, update_instance_without_section, 1, i);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_dhcv6_address_args, idx) == DM_STOP)
+ break;
+ }
+
+ return 0;
+}
+
+int browseDHCPv6ServerPoolClientOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ //TODO
+ return 0;
+}
+
+
+int addObjDHCPv6Client(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ struct uci_section *s, *dmmap_sect;
+ char *wan_eth, *value, *wanname, *instancepara, *v;
+
+ check_create_dmmap_package("dmmap_dhcpv6");
+ instancepara = get_last_instance_icwmpd("dmmap_dhcpv6", "interface", "cwmp_dhcpv6client_instance");
+ dmuci_add_section("network", "interface", &s, &value);
+ dmuci_set_value_by_section(s, "proto", "dhcpv6");
+ dmuci_set_value_by_section(s, "ifname", "@wan");
+ dmuci_set_value_by_section(s, "type", "anywan");
+ dmuci_add_section_icwmpd("dmmap_dhcpv6", "interface", &dmmap_sect, &v);
+ dmuci_set_value_by_section(dmmap_sect, "section_name", section_name(s));
+ *instance = update_instance_icwmpd(dmmap_sect, instancepara, "cwmp_dhcpv6client_instance");
+ return 0;
+}
+
+int delObjDHCPv6Client(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+ struct uci_section *s, *dmmap_section, *ss;
+ int found= 0;
+
+ char *proto;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(dhcpv6_client_args->dhcp_client_conf != NULL && is_section_unnamed(section_name(dhcpv6_client_args->dhcp_client_conf))){
+ LIST_HEAD(dup_list);
+ delete_sections_save_next_sections("dmmap_dhcpv6", "interface", "cwmp_dhcpv6client_instance", section_name(dhcpv6_client_args->dhcp_client_conf), atoi(instance), &dup_list);
+ update_dmmap_sections(&dup_list, "cwmp_dhcpv6client_instance", "dmmap_dhcpv6", "interface");
+ dmuci_delete_by_section_unnamed(dhcpv6_client_args->dhcp_client_conf, NULL, NULL);
+ } else {
+ get_dmmap_section_of_config_section("dmmap_dhcpv6", "interface", section_name(dhcpv6_client_args->dhcp_client_conf), &dmmap_section);
+ dmuci_delete_by_section_unnamed_icwmpd(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(dhcpv6_client_args->dhcp_client_conf, NULL, NULL);
+ }
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("network", "interface", s) {
+ if (found != 0){
+ dmuci_get_value_by_section_string(ss, "proto", &proto);
+ if(strcmp(proto, "dhcpv6") == 0) {
+ get_dmmap_section_of_config_section("dmmap_dhcpv6", "interface", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL){
+ dmuci_get_value_by_section_string(ss, "proto", &proto);
+ if(strcmp(proto, "dhcpv6") == 0) {
+ get_dmmap_section_of_config_section("dmmap_dhcpv6", "interface", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+int addObjDHCPv6ClientSentOption(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ //TODO
+ return 0;
+}
+
+int delObjDHCPv6ClientSentOption(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ switch (del_action) {
+ case DEL_INST:
+ //TODO
+ break;
+ case DEL_ALL:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int addObjDHCPv6ServerPool(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ char *value, *v;
+ char *instancepara;
+ struct uci_section *s = NULL, *dmmap_dhcp= NULL;
+
+ check_create_dmmap_package("dmmap_dhcpv6");
+ instancepara = get_last_instance_icwmpd("dmmap_dhcpv6", "dhcp", "dhcpv6_serv_pool_instance");
+ dmuci_add_section("dhcp", "dhcp", &s, &value);
+ dmuci_set_value_by_section(s, "dhcpv6", "server");
+ dmuci_set_value_by_section(s, "start", "100");
+ dmuci_set_value_by_section(s, "leasetime", "12h");
+ dmuci_set_value_by_section(s, "limit", "150");
+
+ dmuci_add_section_icwmpd("dmmap_dhcpv6", "dhcp", &dmmap_dhcp, &v);
+ dmuci_set_value_by_section(dmmap_dhcp, "section_name", section_name(s));
+ *instance = update_instance_icwmpd(dmmap_dhcp, instancepara, "dhcpv6_serv_pool_instance");
+ return 0;
+}
+
+int delObjDHCPv6ServerPool(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ int found = 0;
+ char *lan_name;
+ struct uci_section *s = NULL;
+ struct uci_section *ss = NULL, *dmmap_section= NULL;
+ char *dhcpv6= NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(is_section_unnamed(section_name(((struct dhcpv6_args *)data)->dhcp_sec))){
+ LIST_HEAD(dup_list);
+ delete_sections_save_next_sections("dmmap_dhcpv6", "dhcp", "dhcpv6_serv_pool_instance", section_name(((struct dhcpv6_args *)data)->dhcp_sec), atoi(instance), &dup_list);
+ update_dmmap_sections(&dup_list, "dhcpv6_serv_pool_instance", "dmmap_dhcpv6", "dhcp");
+ dmuci_delete_by_section_unnamed(((struct dhcpv6_args *)data)->dhcp_sec, NULL, NULL);
+ } else {
+ get_dmmap_section_of_config_section("dmmap_dhcpv6", "dhcp", section_name(((struct dhcpv6_args *)data)->dhcp_sec), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section_unnamed_icwmpd(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(((struct dhcpv6_args *)data)->dhcp_sec, NULL, NULL);
+ }
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("dhcp", "dhcp", s) {
+ if (found != 0){
+ dmuci_get_value_by_section_string(ss, "dhcpv6", &dhcpv6);
+ if(strcmp(dhcpv6, "server") == 0){
+ get_dmmap_section_of_config_section("dmmap_dhcpv6", "dhcp", section_name(s), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL){
+ dmuci_get_value_by_section_string(ss, "dhcpv6", &dhcpv6);
+ if(strcmp(dhcpv6, "server") == 0){
+ get_dmmap_section_of_config_section("dmmap_dhcpv6", "dhcp", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+int addObjDHCPv6ServerPoolOption(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ struct dhcpv6_args *dhcp_arg = (struct dhcpv6_args*)data;
+ struct uci_section *s, *dmmap_sect;
+ char *value, *instancepara, *v;
+
+ check_create_dmmap_package("dmmap_dhcpv6");
+ instancepara= get_last_instance_lev2_icwmpd_dmmap_opt("dmmap_dhcpv6", "servpool_option", "cwmp_dhcpv6_servpool_option_instance", "section_name", section_name(dhcp_arg->dhcp_sec));
+ dmuci_add_section_icwmpd("dmmap_dhcpv6", "servpool_option", &dmmap_sect, &value);
+ if(dhcp_arg->dhcp_sec != NULL)
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "section_name", section_name(dhcp_arg->dhcp_sec));
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "option_tag", "0");
+ *instance = update_instance_icwmpd(dmmap_sect, instancepara, "cwmp_dhcpv6_servpool_option_instance");
+ return 0;
+}
+
+int delObjDHCPv6ServerPoolOption(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *s, *stmp;
+ char *list= NULL, *opt_value= NULL;
+ struct uci_list *dhcp_options_list = NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(strcmp(((struct dhcpv6_client_option_args*) data)->option_tag, "0") != 0)
+ {
+ dmasprintf(&opt_value, "%s,%s", ((struct dhcpv6_client_option_args*) data)->option_tag, ((struct dhcpv6_client_option_args*) data)->value);
+ dmuci_get_value_by_section_list(((struct dhcpv6_client_option_args*) data)->client_sect, "dhcp_option", &dhcp_options_list);
+ if(dhcp_options_list != NULL){
+ dmuci_del_list_value_by_section(((struct dhcpv6_client_option_args*) data)->client_sect, "dhcp_option", opt_value);
+ }
+ }
+ dmuci_delete_by_section_unnamed_icwmpd(((struct dhcpv6_client_option_args*) data)->opt_sect, NULL, NULL);
+ break;
+ case DEL_ALL:
+ dmuci_set_value_by_section(((struct dhcpv6_args*) data)->dhcp_sec, "dhcp_option", "");
+ uci_path_foreach_sections_safe(icwmpd, "dmmap_dhcpv6", "servpool_option", stmp, s) {
+ dmuci_delete_by_section_unnamed_icwmpd(s, NULL, NULL);
+ }
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6_ClientNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+ char *proto;
+
+ uci_path_foreach_sections(icwmpd, "dmmap_dhcpv6", "interface", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+/*#Device.DHCPv6.Client.{i}.Enable!UCI:network/interface,@i-1/disabled*/
+int get_DHCPv6Client_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+ char *v= NULL;
+
+
+ if(dhcpv6_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "0";
+ return 0;
+ }
+
+ dmuci_get_value_by_section_string(dhcpv6_client_args->dhcp_client_conf, "disabled", &v);
+ if (v==NULL || strlen(v)==0 || strcmp(v, "1")!=0)
+ *value= "1";
+ else
+ *value= "0";
+ return 0;
+}
+
+int set_DHCPv6Client_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b)
+ dmuci_set_value_by_section(dhcpv6_client_args->dhcp_client_conf, "disabled", "0");
+ else
+ dmuci_set_value_by_section(dhcpv6_client_args->dhcp_client_conf, "disabled", "1");
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6Client_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+
+ dmuci_get_value_by_section_string(dhcpv6_client_args->dhcp_client_dm, "cwmp_dhcpv6client_alias", value);
+ return 0;
+}
+
+int set_DHCPv6Client_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section(dhcpv6_client_args->dhcp_client_dm, "cwmp_dhcpv6client_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6Client_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+ if(dhcpv6_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "";
+
+ return 0;
+ }
+
+ char *linker= dmstrdup(section_name(dhcpv6_client_args->dhcp_client_conf));
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim, dm_delim), linker, value);
+ return 0;
+}
+
+int set_DHCPv6Client_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+ struct uci_section *s;
+ char *linker= NULL, *newvalue= NULL, *v;
+ struct uci_section *dm;
+
+ switch (action) {
+ case VALUECHECK:
+ if(strlen(value) == 0 || strcmp(value, "") == 0){
+ return FAULT_9007;
+ }
+
+ if (value[strlen(value)-1]!='.') {
+ dmasprintf(&newvalue, "%s.", value);
+ adm_entry_get_linker_value(ctx, newvalue, &linker);
+ } else
+ adm_entry_get_linker_value(ctx, value, &linker);
+ uci_path_foreach_sections(icwmpd, "dmmap_dhcpv6", "interface", s) {
+ dmuci_get_value_by_section_string(s, "section_name", &v);
+ if(strcmp(v, linker) == 0)
+ return FAULT_9007;
+ }
+ uci_foreach_sections("network", "interface", s) {
+ if(strcmp(section_name(s), linker) == 0){
+ dmuci_get_value_by_section_string(s, "proto", &v);
+ if(strcmp(v, "dhcpv6") != 0)
+ return FAULT_9007;
+ }
+ }
+ break;
+ case VALUESET:
+ if (value[strlen(value)-1]!='.') {
+ dmasprintf(&newvalue, "%s.", value);
+ adm_entry_get_linker_value(ctx, newvalue, &linker);
+ } else
+ adm_entry_get_linker_value(ctx, value, &linker);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcpv6_client_args->dhcp_client_dm, "section_name", linker);
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv6.Client.{i}.Status!UCI:network/interface,@i-1/disabled*/
+int get_DHCPv6Client_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+ char *v= "";
+ if(dhcpv6_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "Error_Misconfigured";
+
+ return 0;
+ }
+
+ dmuci_get_value_by_section_string(dhcpv6_client_args->dhcp_client_conf, "disabled", &v);
+
+ if (v==NULL || strlen(v)==0 || strcmp(v, "1")!=0)
+ *value= "Enabled";
+ else
+ *value= "Disabled";
+
+ return 0;
+}
+
+/*#Device.DHCPv6.Client.{i}.DUID!UBUS:network.interface/status/interface,@Name/data.passthru*/
+int get_DHCPv6Client_DUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+ json_object *res;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(dhcpv6_client_args->dhcp_client_conf), String}}, 1, &res);
+ if (res)
+ {
+ *value = dmjson_get_value(res, 2, "data", "passthru");
+ }
+ return 0;
+}
+
+/*#Device.DHCPv6.Client.{i}.RequestAddresses!UCI:network/interface,@i-1/reqaddress*/
+int get_DHCPv6Client_RequestAddresses(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+ char *v= "";
+ if(dhcpv6_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "";
+
+ return 0;
+ }
+
+ dmuci_get_value_by_section_string(dhcpv6_client_args->dhcp_client_conf, "reqaddress", &v);
+ if(strcmp(v, "none") == 0)
+ *value= "0";
+ else
+ *value= "1";
+ return 0;
+}
+
+int set_DHCPv6Client_RequestAddresses(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b)
+ dmuci_set_value_by_section(dhcpv6_client_args->dhcp_client_conf, "reqaddress", "force");
+ else
+ dmuci_set_value_by_section(dhcpv6_client_args->dhcp_client_conf, "reqaddress", "none");
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv6.Client.{i}.RequestPrefixes!UCI:network/interface,@i-1/reqprefix*/
+int get_DHCPv6Client_RequestPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+ char *v= "";
+ if(dhcpv6_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "";
+
+ return 0;
+ }
+
+ dmuci_get_value_by_section_string(dhcpv6_client_args->dhcp_client_conf, "reqprefix", &v);
+ if(strcmp(v, "no") == 0)
+ *value= "0";
+ else
+ *value= "1";
+ return 0;
+}
+
+int set_DHCPv6Client_RequestPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b)
+ dmuci_set_value_by_section(dhcpv6_client_args->dhcp_client_conf, "reqprefix", "auto");
+ else
+ dmuci_set_value_by_section(dhcpv6_client_args->dhcp_client_conf, "reqprefix", "no");
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6Client_RapidCommit(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6Client_RapidCommit(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6Client_Renew(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value= "false";
+ return 0;
+}
+
+int set_DHCPv6Client_Renew(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_client_args *dhcp_client_args = (struct dhcpv6_client_args*)data;
+ json_object *res;
+ bool b;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (dhcp_client_args->dhcp_client_conf == NULL && !b)
+ return 0;
+
+ dmubus_call("network.interface", "renew", UBUS_ARGS{{"interface", section_name(dhcp_client_args->dhcp_client_conf), String}}, 1, &res);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6Client_SuggestedT1(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6Client_SuggestedT1(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6Client_SuggestedT2(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6Client_SuggestedT2(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6Client_SupportedOptions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+/*#Device.DHCPv6.Client.{i}.RequestedOptions!UCI:network/interface,@i-1/reqopts*/
+int get_DHCPv6Client_RequestedOptions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+
+ if(dhcpv6_client_args->dhcp_client_conf == NULL)
+ {
+ *value= "";
+
+ return 0;
+ }
+
+ dmuci_get_value_by_section_string(dhcpv6_client_args->dhcp_client_conf, "reqopts", value);
+ return 0;
+}
+
+int set_DHCPv6Client_RequestedOptions(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_client_args *dhcpv6_client_args = (struct dhcpv6_client_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section(dhcpv6_client_args->dhcp_client_conf, "reqopts", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6Client_ServerNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6Client_SentOptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6Client_ReceivedOptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ClientServer_SourceAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ClientServer_DUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ClientServer_InformationRefreshTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ClientSentOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ClientSentOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ClientSentOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ClientSentOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ClientSentOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ClientSentOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ClientSentOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ClientSentOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ClientReceivedOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ClientReceivedOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ClientReceivedOption_Server(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6Server_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *path = "/etc/rc.d/*odhcpd";
+ if (check_file(path))
+ *value = "1";
+ else
+ *value = "0";
+ return 0;
+}
+
+int set_DHCPv6Server_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b)
+ dmcmd("/etc/init.d/odhcpd", 1, "enable");
+ else
+ dmcmd("/etc/init.d/odhcpd", 1, "disable");
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6Server_PoolNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s;
+ int i= 0;
+ char *v= NULL;
+
+ uci_foreach_sections("dhcp", "dhcp", s) {
+ dmuci_get_value_by_section_string(s, "dhcpv6", &v);
+ if (v!=NULL && strcmp(v, "server") == 0)
+ i++;
+ }
+ dmasprintf(value, "%d", i);
+ return 0;
+}
+
+/*#Device.DHCPv6.Server.Pool.{i}.Enable!UCI:dhcp/dhcp,@i-1/ignore*/
+int get_DHCPv6ServerPool_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{ struct uci_section *s = NULL;
+
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcpv6_args *)data)->interface, s) {
+ dmuci_get_value_by_section_string(s, "ignore", value);
+ if ((*value)[0] == '\0')
+ *value = "1";
+ else
+ *value = "0";
+ return 0;
+ }
+ *value = "0";
+ return 0;
+}
+
+int set_DHCPv6ServerPool_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcpv6_args *)data)->interface, s) {
+ if (b)
+ dmuci_set_value_by_section(s, "ignore", "");
+ else
+ dmuci_set_value_by_section(s, "ignore", "1");
+ break;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv6.Server.Pool.{i}.Status!UCI:dhcp/dhcp,@i-1/ignore*/
+int get_DHCPv6ServerPool_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ char *v= NULL;
+ uci_foreach_option_eq("dhcp", "dhcp", "interface", ((struct dhcpv6_args *)data)->interface, s) {
+ dmuci_get_value_by_section_string(s, "ignore", &v);
+ *value = (v && *v == '1') ? "Disabled" : "Enabled";
+ return 0;
+ }
+ *value="Error_Misconfigured";
+ return 0;
+}
+
+int get_DHCPv6ServerPool_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_args *dhcpv6_arg= (struct dhcpv6_args*)data;
+ struct uci_section *dmmap_sect;
+
+ get_dmmap_section_of_config_section("dmmap_dhcpv6", "dhcp", section_name(dhcpv6_arg->dhcp_sec), &dmmap_sect);
+ if (dmmap_sect)
+ dmuci_get_value_by_section_string(dmmap_sect, "dhcpv6_serv_pool_alias", value);
+ return 0;
+}
+
+int set_DHCPv6ServerPool_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_args *dhcpv6_arg= (struct dhcpv6_args*)data;
+ struct uci_section *dmmap_sect;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ get_dmmap_section_of_config_section("dmmap_dhcpv6", "dhcp", section_name(dhcpv6_arg->dhcp_sec), &dmmap_sect);
+ if (dmmap_sect)
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dmmap_sect, "dhcpv6_serv_pool_alias", value);
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_args *dhcp_arg= (struct dhcpv6_args*)data;
+ struct uci_section *dmmap_sect;
+
+ get_dmmap_section_of_config_section("dmmap_dhcpv6", "dhcp", section_name(dhcp_arg->dhcp_sec), &dmmap_sect);
+ if (dmmap_sect)
+ dmuci_get_value_by_section_string(dmmap_sect, "order", value);
+ return 0;
+}
+
+int set_DHCPv6ServerPool_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_args *dhcp_arg= (struct dhcpv6_args*)data;
+ struct uci_section *dmmap_sect;
+
+ get_dmmap_section_of_config_section("dmmap_dhcpv6", "dhcp", section_name(dhcp_arg->dhcp_sec), &dmmap_sect);
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ set_section_order("dhcp", "dmmap_dhcpv6", "dhcp", dmmap_sect, dhcp_arg->dhcp_sec, 1, value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *linker;
+ linker = dmstrdup(((struct dhcpv6_args *)data)->interface);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
+ if (*value == NULL)
+ *value = "";
+ dmfree(linker);
+ return 0;
+}
+
+int set_DHCPv6ServerPool_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *linker;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ adm_entry_get_linker_value(ctx, value, &linker);
+ if (linker) {
+ dmuci_set_value_by_section(((struct dhcpv6_args *)data)->dhcp_sec, "interface", linker);
+ dmfree(linker);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_DUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ServerPool_DUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_DUIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ServerPool_DUIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv6.Server.Pool.{i}.VendorClassID!UCI:dhcp/dhcp,@i-1/vendorclass*/
+int get_DHCPv6ServerPool_VendorClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_args *dhcpv6_client_args = (struct dhcpv6_args*)data;
+
+ struct uci_section *vendorclassidclassifier= get_dhcpv6_classifier("vendorclass", dhcpv6_client_args->interface);
+ if(vendorclassidclassifier == NULL)
+ return 0;
+ dmuci_get_value_by_section_string(vendorclassidclassifier, "vendorclass", value);
+ return 0;
+}
+
+int set_DHCPv6ServerPool_VendorClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_args *dhcpv6_client_args = (struct dhcpv6_args*)data;
+ struct uci_section *vendorclassidclassifier= NULL;
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ vendorclassidclassifier= get_dhcpv6_classifier("vendorclass", dhcpv6_client_args->interface);
+ if(vendorclassidclassifier == NULL)
+ return 0;
+ dmuci_set_value_by_section(vendorclassidclassifier, "vendorclass", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_VendorClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value="false";
+ return 0;
+}
+
+int set_DHCPv6ServerPool_VendorClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DHCPv6.Server.Pool.{i}.UserClassID!UCI:dhcp/dhcp,@i-1/userclass*/
+int get_DHCPv6ServerPool_UserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_args *dhcpv6_client_args = (struct dhcpv6_args*)data;
+
+ struct uci_section *userclassidclassifier= get_dhcpv6_classifier("userclass", dhcpv6_client_args->interface);
+ if(userclassidclassifier == NULL)
+ return 0;
+ dmuci_get_value_by_section_string(userclassidclassifier, "userclass", value);
+ return 0;
+}
+
+int set_DHCPv6ServerPool_UserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_args *dhcpv6_client_args = (struct dhcpv6_args*)data;
+
+ struct uci_section *userclassidclassifier;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ userclassidclassifier= get_dhcpv6_classifier("userclass", dhcpv6_client_args->interface);
+ if(userclassidclassifier == NULL)
+ return 0;
+ dmuci_set_value_by_section(userclassidclassifier, "userclass", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_UserClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value= "false";
+ return 0;
+}
+
+int set_DHCPv6ServerPool_UserClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_SourceAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_args *dhcpv6_client_args = (struct dhcpv6_args*)data;
+ struct uci_section *macaddrclassifier;
+ char *mac, *mac1, *mac2, *mac3, *mac4, *mac5, *mac6, **macarray, *res= NULL, *tmp= "";
+ int length, i;
+
+ macaddrclassifier= get_dhcpv6_classifier("mac", dhcpv6_client_args->interface);
+ if(macaddrclassifier == NULL) {
+ *value= "";
+ return 0;
+ }
+ dmuci_get_value_by_section_string(macaddrclassifier, "mac", &mac);
+ macarray= strsplit(mac, ":", &length);
+ res= (char*)dmcalloc(18, sizeof(char));
+ tmp=res;
+ for(i= 0; i<6; i++){
+ if(strcmp(macarray[i], "*") == 0) {
+ sprintf(tmp, "%s", "00");
+ } else{
+ sprintf(tmp, "%s", macarray[i]);
+ }
+ tmp+=2;
+
+ if(i<5){
+ sprintf(tmp, "%s", ":");
+ tmp++;
+ }
+ }
+ dmasprintf(value, "%s", res);
+ return 0;
+}
+
+int set_DHCPv6ServerPool_SourceAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_SourceAddressMask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_args *dhcp_relay_args = (struct dhcpv6_args*)data;
+ struct uci_section *macaddrclassifier;
+ char *mac, *mac1, *mac2, *mac3, *mac4, *mac5, *mac6, **macarray, *res= NULL, *tmp= "";
+ int length, i;
+
+ if(macaddrclassifier == NULL) {
+ *value= "";
+ return 0;
+ }
+ dmuci_get_value_by_section_string(macaddrclassifier, "mac", &mac);
+ macarray= strsplit(mac, ":", &length);
+ res= (char*)dmcalloc(18, sizeof(char));
+ tmp=res;
+ for(i= 0; i<6; i++){
+ if(strcmp(macarray[i], "*") == 0) {
+ sprintf(tmp, "%s", "00");
+ } else{
+ sprintf(tmp, "%s", "FF");
+ }
+ tmp+=2;
+
+ if(i<5){
+ sprintf(tmp, "%s", ":");
+ tmp++;
+ }
+ }
+ dmasprintf(value, "%s", res);
+ return 0;
+}
+
+int set_DHCPv6ServerPool_SourceAddressMask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_SourceAddressExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ServerPool_SourceAddressExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_IANAEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ServerPool_IANAEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_IANAManualPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ServerPool_IANAManualPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_IANAPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ServerPool_IAPDEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ServerPool_IAPDEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_IAPDManualPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ServerPool_IAPDManualPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_IAPDPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ServerPool_IAPDAddLength(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ServerPool_IAPDAddLength(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPool_ClientNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_args *dhcp_arg= (struct dhcpv6_args*)data;
+ json_object *res, *res1, *jobj, *dev_obj= NULL, *net_obj= NULL;
+ struct clientv6_args curr_dhcp_client_args = {0};
+ char *device;
+ int i= 0;
+ char *idx = NULL, *idx_last = NULL;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(dhcp_arg->dhcp_sec), String}}, 1, &res1);
+ device = dmjson_get_value(res1, 1, "device");
+ dmubus_call("dhcp", "ipv6leases", UBUS_ARGS{}, 0, &res);
+ if(!res)
+ return 0;
+ dev_obj = dmjson_get_obj(res, 1, "device");
+ if (!dev_obj)
+ return 0;
+
+ net_obj = dmjson_get_obj(dev_obj, 1, device);
+ if (!net_obj)
+ return 0;
+
+ while (1) {
+
+ jobj = dmjson_select_obj_in_array_idx(net_obj, i, 1, "leases");
+ if (jobj == NULL)
+ break;
+ i++;
+ }
+ dmasprintf(value, "%d", i);
+ return 0;
+}
+
+int get_DHCPv6ServerPool_OptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_args *curr_dhcp_args = (struct dhcpv6_args*)data;
+ struct uci_list *dhcp_options_list = NULL;
+ struct uci_element *e;
+
+ int i= 0;
+
+ dmuci_get_value_by_section_list(curr_dhcp_args->dhcp_sec, "dhcp_option", &dhcp_options_list);
+ if (dhcp_options_list != NULL) {
+ uci_foreach_element(dhcp_options_list, e) {
+ i++;
+ }
+ }
+ dmasprintf(value, "%d", i);
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClient_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ServerPoolClient_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClient_SourceAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClient_Active(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClient_IPv6AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct clientv6_args *dhcpv6_serv_pool_client= (struct clientv6_args *)data;
+ json_object *address_obj= NULL, *prefix_obj= NULL;
+ struct clientv6_args curr_dhcv6_address_args = {0};
+ char *idx = NULL, *idx_last = NULL;
+ int i= 0;
+
+ while (1) {
+ address_obj = dmjson_select_obj_in_array_idx(dhcpv6_serv_pool_client->client, i, 1, "ipv6-addr");
+ if (address_obj == NULL)
+ break;
+ i++;
+ }
+ dmasprintf(value, "%d", i);
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClient_IPv6PrefixNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct clientv6_args *dhcpv6_serv_pool_client= (struct clientv6_args *)data;
+ json_object *address_obj= NULL, *prefix_obj= NULL;
+ struct clientv6_args curr_dhcv6_address_args = {0};
+ char *idx = NULL, *idx_last = NULL;
+ int i= 0;
+
+ while (1) {
+ address_obj = dmjson_select_obj_in_array_idx(dhcpv6_serv_pool_client->client, i, 1, "ipv6-prefix");
+ if (address_obj == NULL)
+ break;
+ i++;
+ }
+ dmasprintf(value, "%d", i);
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClient_OptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClientIPv6Address_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct clientv6_args *dhcpv6_serv_pool_client_ip6address= (struct clientv6_args *)data;
+ *value = dmjson_get_value(dhcpv6_serv_pool_client_ip6address->clientparam, 1, "address");
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClientIPv6Address_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct clientv6_args *dhcpv6_serv_pool_client_ip6address= (struct clientv6_args *)data;
+ *value = dmjson_get_value(dhcpv6_serv_pool_client_ip6address->clientparam, 1, "preferred-lifetime");
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClientIPv6Address_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct clientv6_args *dhcpv6_serv_pool_client_ip6address= (struct clientv6_args *)data;
+ *value = dmjson_get_value(dhcpv6_serv_pool_client_ip6address->clientparam, 1, "valid-lifetime");
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClientIPv6Prefix_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct clientv6_args *dhcpv6_serv_pool_client_ip6address= (struct clientv6_args *)data;
+ *value = dmjson_get_value(dhcpv6_serv_pool_client_ip6address->clientparam, 1, "address");
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClientIPv6Prefix_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct clientv6_args *dhcpv6_serv_pool_client_ip6address= (struct clientv6_args *)data;
+ *value = dmjson_get_value(dhcpv6_serv_pool_client_ip6address->clientparam, 1, "preferred-lifetime");
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClientIPv6Prefix_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct clientv6_args *dhcpv6_serv_pool_client_ip6address= (struct clientv6_args *)data;
+ *value = dmjson_get_value(dhcpv6_serv_pool_client_ip6address->clientparam, 1, "valid-lifetime");
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClientOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ServerPoolClientOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_DHCPv6ServerPoolOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_option_args* dhcp_client_opt_args= (struct dhcpv6_client_option_args*)data;
+ char *v;
+ char *opttagvalue= NULL;
+ struct uci_list *dhcp_option_list;
+ struct uci_element *e;
+ char **buf;
+ int length;
+
+ if(strcmp(dhcp_client_opt_args->option_tag, "0") == 0){
+ *value= "0";
+ return 0;
+ }
+
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+ if (dhcp_option_list != NULL) {
+ uci_foreach_element(dhcp_option_list, e) {
+ buf= strsplit(e->name, ",", &length);
+ if(strcmp(buf[0], dhcp_client_opt_args->option_tag) == 0) {
+ *value= "1";
+ return 0;
+ }
+ }
+ }
+
+ *value= "0";
+ return 0;
+}
+
+int set_DHCPv6ServerPoolOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_client_option_args* dhcp_client_opt_args= (struct dhcpv6_client_option_args*)data;
+ struct uci_list *dhcp_option_list;
+ struct uci_element *e;
+ char **buf, *opt_value;
+ int length;
+ bool test= false, b;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+
+ if(strcmp(dhcp_client_opt_args->option_tag, "0") == 0)
+ return 0;
+
+
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+ dmasprintf(&opt_value, "%s,%s", dhcp_client_opt_args->option_tag, dhcp_client_opt_args->value);
+
+ if (dhcp_option_list != NULL) {
+ uci_foreach_element(dhcp_option_list, e) {
+ buf= strsplit(e->name, ",", &length);
+ if(strcmp(buf[0], dhcp_client_opt_args->option_tag) == 0) {
+ test= true;
+ if(!b){
+ dmuci_del_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", opt_value);
+ }
+ break;
+ }
+ }
+ }
+ if(!test && b){
+ dmuci_add_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", opt_value);
+ }
+
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPoolOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_option_args* dhcp_client_opt_args= (struct dhcpv6_client_option_args*)data;
+
+ dmuci_get_value_by_section_string(dhcp_client_opt_args->opt_sect, "cwmp_dhcpv6_servpool_option_alias", value);
+ return 0;
+
+}
+
+int set_DHCPv6ServerPoolOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_client_option_args* dhcp_client_opt_args= (struct dhcpv6_client_option_args*)data;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "cwmp_dhcpv6_servpool_option_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPoolOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_option_args* dhcp_client_opt_args= (struct dhcpv6_client_option_args*)data;
+ *value= dmstrdup(dhcp_client_opt_args->option_tag);
+ return 0;
+}
+
+int set_DHCPv6ServerPoolOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_client_option_args* dhcp_client_opt_args= (struct dhcpv6_client_option_args*)data;
+ char *opttagvalue, **option, *oldopttagvalue;
+ int length;
+ struct uci_list *dhcp_option_list= NULL;
+ struct uci_element *e;
+
+ switch (action) {
+ case VALUECHECK:
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+
+ if(dhcp_option_list==NULL)
+ return 0;
+
+ uci_foreach_element(dhcp_option_list, e) {
+ option= strsplit(e->name, ",", &length);
+ if (strcmp(option[0], value)==0)
+ return FAULT_9007;
+ }
+ break;
+ case VALUESET:
+ dmasprintf(&oldopttagvalue, "%s,%s", dhcp_client_opt_args->option_tag, dhcp_client_opt_args->value);
+ dmasprintf(&opttagvalue, "%s,%s", value, dhcp_client_opt_args->value);
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+ dmuci_del_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", oldopttagvalue);
+ dmuci_add_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", opttagvalue);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "option_tag", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPoolOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct dhcpv6_client_option_args* dhcp_client_opt_args= (struct dhcpv6_client_option_args*)data;
+ *value= dmstrdup(dhcp_client_opt_args->value);
+ return 0;
+}
+
+int set_DHCPv6ServerPoolOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct dhcpv6_client_option_args* dhcp_client_opt_args= (struct dhcpv6_client_option_args*)data;
+ char *opttagvalue, **option, *oldopttagvalue;
+ int length;
+ struct uci_list *dhcp_option_list= NULL;
+ struct uci_element *e;
+
+ switch (action) {
+ case VALUECHECK:
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+
+ if(dhcp_option_list==NULL)
+ return 0;
+
+ uci_foreach_element(dhcp_option_list, e) {
+ option= strsplit(e->name, ",", &length);
+ if (strcmp(option[0], value)==0)
+ return FAULT_9007;
+ }
+ break;
+ case VALUESET:
+ dmasprintf(&oldopttagvalue, "%s,%s", dhcp_client_opt_args->option_tag, dhcp_client_opt_args->value);
+ dmasprintf(&opttagvalue, "%s,%s", dhcp_client_opt_args->option_tag, value);
+ dmuci_get_value_by_section_list(dhcp_client_opt_args->client_sect, "dhcp_option", &dhcp_option_list);
+ dmuci_del_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", oldopttagvalue);
+ dmuci_add_list_value_by_section(dhcp_client_opt_args->client_sect, "dhcp_option", opttagvalue);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dhcp_client_opt_args->opt_sect, "option_value", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DHCPv6ServerPoolOption_PassthroughClient(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int set_DHCPv6ServerPoolOption_PassthroughClient(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ //TODO
+ break;
+ }
+ return 0;
+}
+
diff --git a/dmtree/tr181/dhcpv6.h b/dmtree/tr181/dhcpv6.h
new file mode 100644
index 00000000..041f8f2d
--- /dev/null
+++ b/dmtree/tr181/dhcpv6.h
@@ -0,0 +1,190 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Omar Kallel
+*/
+
+#ifndef __DHCPV6_H
+#define __DHCPV6_H
+
+extern DMOBJ tDHCPv6Obj[];
+extern DMLEAF tDHCPv6Params[];
+extern DMOBJ tDHCPv6ClientObj[];
+extern DMLEAF tDHCPv6ClientParams[];
+extern DMLEAF tDHCPv6ClientServerParams[];
+extern DMLEAF tDHCPv6ClientSentOptionParams[];
+extern DMLEAF tDHCPv6ClientReceivedOptionParams[];
+extern DMOBJ tDHCPv6ServerObj[];
+extern DMLEAF tDHCPv6ServerParams[];
+extern DMOBJ tDHCPv6ServerPoolObj[];
+extern DMLEAF tDHCPv6ServerPoolParams[];
+extern DMOBJ tDHCPv6ServerPoolClientObj[];
+extern DMLEAF tDHCPv6ServerPoolClientParams[];
+extern DMLEAF tDHCPv6ServerPoolClientIPv6AddressParams[];
+extern DMLEAF tDHCPv6ServerPoolClientIPv6PrefixParams[];
+extern DMLEAF tDHCPv6ServerPoolClientOptionParams[];
+extern DMLEAF tDHCPv6ServerPoolOptionParams[];
+
+struct dhcpv6_client_args {
+ struct uci_section *dhcp_client_conf;
+ struct uci_section *dhcp_client_dm;
+ char *ip;
+};
+
+struct dhcpv6_args
+{
+ struct uci_section *dhcp_sec;
+ char *interface;
+};
+
+struct clientv6_args
+{
+ json_object *client;
+ json_object *clientparam;
+ int idx;
+};
+
+struct dhcpv6_client_option_args {
+ struct uci_section *opt_sect;
+ struct uci_section *client_sect;
+ char *option_tag;
+ char *value;
+};
+
+int browseDHCPv6ClientInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv6ClientServerInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv6ClientSentOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv6ClientReceivedOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv6ServerPoolInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv6ServerPoolClientInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv6ServerPoolOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv6ServerPoolClientIPv6AddressInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv6ServerPoolClientIPv6PrefixInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDHCPv6ServerPoolClientOptionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int addObjDHCPv6Client(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjDHCPv6Client(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int addObjDHCPv6ClientSentOption(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjDHCPv6ClientSentOption(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int addObjDHCPv6ServerPool(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjDHCPv6ServerPool(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int addObjDHCPv6ServerPoolOption(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjDHCPv6ServerPoolOption(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+
+int get_DHCPv6_ClientNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6Client_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Client_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Client_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Client_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Client_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Client_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Client_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6Client_DUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6Client_RequestAddresses(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Client_RequestAddresses(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Client_RequestPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Client_RequestPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Client_RapidCommit(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Client_RapidCommit(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Client_Renew(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Client_Renew(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Client_SuggestedT1(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Client_SuggestedT1(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Client_SuggestedT2(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Client_SuggestedT2(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Client_SupportedOptions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6Client_RequestedOptions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Client_RequestedOptions(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Client_ServerNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6Client_SentOptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6Client_ReceivedOptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ClientServer_SourceAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ClientServer_DUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ClientServer_InformationRefreshTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ClientSentOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ClientSentOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ClientSentOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ClientSentOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ClientSentOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ClientSentOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ClientSentOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ClientSentOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ClientReceivedOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ClientReceivedOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ClientReceivedOption_Server(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6Server_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6Server_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6Server_PoolNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPool_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPool_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_Order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_DUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_DUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_DUIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_DUIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_VendorClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_VendorClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_VendorClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_VendorClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_UserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_UserClassID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_UserClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_UserClassIDExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_SourceAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_SourceAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_SourceAddressMask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_SourceAddressMask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_SourceAddressExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_SourceAddressExclude(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_IANAEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_IANAEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_IANAManualPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_IANAManualPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_IANAPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPool_IAPDEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_IAPDEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_IAPDManualPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_IAPDManualPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_IAPDPrefixes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPool_IAPDAddLength(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPool_IAPDAddLength(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPool_ClientNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPool_OptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClient_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPoolClient_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPoolClient_SourceAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClient_Active(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClient_IPv6AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClient_IPv6PrefixNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClient_OptionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClientIPv6Address_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClientIPv6Address_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClientIPv6Address_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClientIPv6Prefix_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClientIPv6Prefix_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClientIPv6Prefix_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClientOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolClientOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DHCPv6ServerPoolOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPoolOption_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPoolOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPoolOption_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPoolOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPoolOption_Tag(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPoolOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPoolOption_Value(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DHCPv6ServerPoolOption_PassthroughClient(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DHCPv6ServerPoolOption_PassthroughClient(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+#endif //__DHCPV6_H
+
diff --git a/dmtree/tr181/dns.c b/dmtree/tr181/dns.c
new file mode 100644
index 00000000..08f98574
--- /dev/null
+++ b/dmtree/tr181/dns.c
@@ -0,0 +1,1046 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Amin Ben Ramdhane
+*/
+
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcwmp.h"
+#include "dmcommon.h"
+#include "dmjson.h"
+#include "dmentry.h"
+#include "dns.h"
+
+/* *** Device.DNS. *** */
+DMOBJ tDNSObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Client", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDNSClientObj, tDNSClientParams, NULL, BBFDM_BOTH},
+{"Relay", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDNSRelayObj, tDNSRelayParams, NULL, BBFDM_BOTH},
+{"Diagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDNSDiagnosticsObj, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDNSParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"SupportedRecordTypes", &DMREAD, DMT_STRING, get_dns_supported_record_types, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DNS.Client. *** */
+DMOBJ tDNSClientObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Server", &DMWRITE, add_client_server, delete_client_server, NULL, browseServerInst, NULL, NULL, NULL, tDNSClientServerParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDNSClientParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_client_enable, set_client_enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_client_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"ServerNumberOfEntries", &DMREAD, DMT_UNINT, get_client_server_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DNS.Client.Server.{i}. *** */
+DMLEAF tDNSClientServerParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_server_enable, set_server_enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_server_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_server_alias, set_server_alias, NULL, NULL, BBFDM_BOTH},
+{"DNSServer", &DMWRITE, DMT_STRING, get_server_dns_server, set_server_dns_server, NULL, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_server_interface, set_server_interface, NULL, NULL, BBFDM_BOTH},
+{"Type", &DMREAD, DMT_STRING, get_server_type, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DNS.Relay. *** */
+DMOBJ tDNSRelayObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Forwarding", &DMWRITE, add_relay_forwarding, delete_relay_forwarding, NULL, browseRelayForwardingInst, NULL, NULL, NULL, tDNSRelayForwardingParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDNSRelayParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_relay_enable, set_relay_enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_relay_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"ForwardNumberOfEntries", &DMREAD, DMT_UNINT, get_relay_forward_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DNS.Relay.Forwarding.{i}. *** */
+DMLEAF tDNSRelayForwardingParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_forwarding_enable, set_forwarding_enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_forwarding_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_forwarding_alias, set_forwarding_alias, NULL, NULL, BBFDM_BOTH},
+{"DNSServer", &DMWRITE, DMT_STRING, get_forwarding_dns_server, set_forwarding_dns_server, NULL, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_forwarding_interface, set_forwarding_interface, NULL, NULL, BBFDM_BOTH},
+{"Type", &DMREAD, DMT_STRING, get_forwarding_type, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DNS.Diagnostics. *** */
+DMOBJ tDNSDiagnosticsObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"NSLookupDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDNSDiagnosticsNSLookupDiagnosticsObj, tDNSDiagnosticsNSLookupDiagnosticsParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DNS.Diagnostics.NSLookupDiagnostics. *** */
+DMOBJ tDNSDiagnosticsNSLookupDiagnosticsObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Result", &DMREAD, NULL, NULL, NULL, browseResultInst, NULL, NULL, NULL, tDNSDiagnosticsNSLookupDiagnosticsResultParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDNSDiagnosticsNSLookupDiagnosticsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"DiagnosticsState", &DMWRITE, DMT_STRING, get_nslookupdiagnostics_diagnostics_state, set_nslookupdiagnostics_diagnostics_state, NULL, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_nslookupdiagnostics_interface, set_nslookupdiagnostics_interface, NULL, NULL, BBFDM_BOTH},
+{"HostName", &DMWRITE, DMT_STRING, get_nslookupdiagnostics_host_name, set_nslookupdiagnostics_host_name, NULL, NULL, BBFDM_BOTH},
+{"DNSServer", &DMWRITE, DMT_STRING, get_nslookupdiagnostics_d_n_s_server, set_nslookupdiagnostics_d_n_s_server, NULL, NULL, BBFDM_BOTH},
+{"Timeout", &DMWRITE, DMT_UNINT, get_nslookupdiagnostics_timeout, set_nslookupdiagnostics_timeout, NULL, NULL, BBFDM_BOTH},
+{"NumberOfRepetitions", &DMWRITE, DMT_UNINT, get_nslookupdiagnostics_number_of_repetitions, set_nslookupdiagnostics_number_of_repetitions, NULL, NULL, BBFDM_BOTH},
+{"SuccessCount", &DMREAD, DMT_UNINT, get_nslookupdiagnostics_success_count, NULL, NULL, NULL, BBFDM_BOTH},
+{"ResultNumberOfEntries", &DMREAD, DMT_UNINT, get_nslookupdiagnostics_result_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DNS.Diagnostics.NSLookupDiagnostics.Result.{i}. *** */
+DMLEAF tDNSDiagnosticsNSLookupDiagnosticsResultParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Status", &DMREAD, DMT_STRING, get_result_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"AnswerType", &DMREAD, DMT_STRING, get_result_answer_type, NULL, NULL, NULL, BBFDM_BOTH},
+{"HostNameReturned", &DMREAD, DMT_STRING, get_result_host_name_returned, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPAddresses", &DMREAD, DMT_STRING, get_result_i_p_addresses, NULL, NULL, NULL, BBFDM_BOTH},
+{"DNSServerIP", &DMREAD, DMT_STRING, get_result_d_n_s_server_i_p, NULL, NULL, NULL, BBFDM_BOTH},
+{"ResponseTime", &DMREAD, DMT_UNINT, get_result_response_time, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/********************************
+ * init function
+ ********************************/
+inline int init_nslookup_results(struct NSLookupResult *args, char *Status, char *AnswerType, char *HostNameReturned, char *IPAddresses, char *DNSServerIP, char *ResponseTime)
+{
+ args->Status = Status;
+ args->AnswerType = AnswerType;
+ args->HostNameReturned = HostNameReturned;
+ args->IPAddresses = IPAddresses;
+ args->DNSServerIP = DNSServerIP;
+ args->ResponseTime = ResponseTime;
+ return 0;
+}
+
+/****************************************************************************************************************************/
+static inline char *nslookup_get(char *option, char *def)
+{
+ char *tmp;
+ dmuci_get_varstate_string("cwmp", "@nslookupdiagnostic[0]", option, &tmp);
+ if(tmp && tmp[0] == '\0')
+ return dmstrdup(def);
+ else
+ return tmp;
+}
+
+static unsigned char is_dns_server_in_dmmap(char *chk_ip, char *chk_interface)
+{
+ struct uci_section *s = NULL;
+ char *ip, *interface;
+
+ uci_path_foreach_sections(icwmpd, "dmmap_dns", "dns_server", s) {
+ dmuci_get_value_by_section_string(s, "ip", &ip);
+ dmuci_get_value_by_section_string(s, "interface", &interface);
+ if (strcmp(interface, chk_interface) == 0 && strcmp(ip, chk_ip) == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int dmmap_synchronizeDNSClientRelayServer(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ json_object *jobj, *arrobj;
+ struct uci_list *v;
+ struct uci_element *e;
+ struct uci_section *s = NULL, *sdns = NULL, *stmp, *ss;
+ char *ipdns, *str, *vip = NULL, *viface, *name;
+ int j, found;
+
+ check_create_dmmap_package("dmmap_dns");
+ uci_path_foreach_sections_safe(icwmpd, "dmmap_dns", "dns_server", stmp, s) {
+ dmuci_get_value_by_section_string(s, "ip", &vip);
+ dmuci_get_value_by_section_string(s, "interface", &viface);
+ found = 0;
+ uci_foreach_sections("network", "interface", ss) {
+ if (strcmp(section_name(ss), viface) != 0)
+ continue;
+ dmuci_get_value_by_section_list(ss, "dns", &v);
+ if (v != NULL) {
+ uci_foreach_element(v, e) {
+ if (strcmp(e->name, vip) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (found)
+ break;
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(ss), String}}, 1, &jobj);
+ dmjson_foreach_value_in_array(jobj, arrobj, ipdns, j, 1, "dns-server") {
+ if (strcmp(ipdns, vip) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+ if (!found)
+ dmuci_delete_by_section(s, NULL, NULL);
+ }
+
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_list(s, "dns", &v);
+ if (v != NULL) {
+ uci_foreach_element(v, e) {
+ if (is_dns_server_in_dmmap(e->name, section_name(s)))
+ continue;
+ dmuci_add_section_icwmpd("dmmap_dns", "dns_server", &sdns, &name);
+ dmuci_set_value_by_section(sdns, "ip", e->name);
+ dmuci_set_value_by_section(sdns, "interface", section_name(s));
+ dmuci_set_value_by_section(sdns, "enable", "1");
+ }
+ }
+ dmuci_get_value_by_section_string(s, "peerdns", &str);
+ if (str[0] == '0')
+ continue;
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(s), String}}, 1, &jobj);
+ dmjson_foreach_value_in_array(jobj, arrobj, ipdns, j, 1, "dns-server") {
+ if (ipdns[0] == '\0' || is_dns_server_in_dmmap(ipdns, section_name(s)))
+ continue;
+ dmuci_add_section_icwmpd("dmmap_dns", "dns_server", &sdns, &name);
+ dmuci_set_value_by_section(sdns, "ip", ipdns);
+ dmuci_set_value_by_section(sdns, "interface", section_name(s));
+ dmuci_set_value_by_section(sdns, "enable", "1");
+ dmuci_set_value_by_section(sdns, "peerdns", "1");
+ }
+ }
+ return 0;
+}
+
+/******************************** Browse Functions ****************************************/
+int browseServerInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ char *instance, *instnbr = NULL;
+
+ dmmap_synchronizeDNSClientRelayServer(dmctx, NULL, NULL, NULL);
+ uci_path_foreach_sections(icwmpd, "dmmap_dns", "dns_server", s)
+ {
+ instance = handle_update_instance(1, dmctx, &instnbr, update_instance_alias_icwmpd, 3, s, "dns_server_instance", "dns_server_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, instance) == DM_STOP)
+ break;
+
+ }
+ return 0;
+}
+
+int browseRelayForwardingInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ char *instance, *instnbr = NULL;
+
+ dmmap_synchronizeDNSClientRelayServer(dmctx, NULL, NULL, NULL);
+ uci_path_foreach_sections(icwmpd, "dmmap_dns", "dns_server", s)
+ {
+ instance = handle_update_instance(1, dmctx, &instnbr, update_instance_alias_icwmpd, 3, s, "dns_server_instance", "dns_server_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, instance) == DM_STOP)
+ break;
+
+ }
+ return 0;
+}
+
+int browseResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ char *instance, *idx_last = NULL;
+
+ uci_foreach_sections_state("cwmp", "NSLookupResult", s)
+ {
+ instance = handle_update_instance(2, dmctx, &idx_last, update_instance_alias, 3, (void *)s, "nslookup_res_instance", "nslookup_res_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, instance) == DM_STOP)
+ break;
+ }
+ return 0;
+}
+
+/*********************************** Add/Delet Object functions *************************/
+int add_client_server(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ struct uci_section *s = NULL;
+ char *v, *inst;
+
+ check_create_dmmap_package("dmmap_dns");
+ inst = get_last_instance_icwmpd("dmmap_dns", "dns_server", "dns_server_instance");
+ dmuci_add_list_value("network", "lan", "dns", "0.0.0.0");
+ dmuci_add_section_icwmpd("dmmap_dns", "dns_server", &s, &v);
+ dmuci_set_value_by_section(s, "ip", "0.0.0.0");
+ dmuci_set_value_by_section(s, "interface", "lan");
+ dmuci_set_value_by_section(s, "enable", "1");
+ *instance = update_instance_icwmpd(s, inst, "dns_server_instance");
+ return 0;
+}
+
+int add_relay_forwarding(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ struct uci_section *s = NULL;
+ char *v, *inst;
+
+ check_create_dmmap_package("dmmap_dns");
+ inst = get_last_instance_icwmpd("dmmap_dns", "dns_server", "dns_server_instance");
+ dmuci_add_list_value("network", "lan", "dns", "0.0.0.0");
+ dmuci_add_section_icwmpd("dmmap_dns", "dns_server", &s, &v);
+ dmuci_set_value_by_section(s, "ip", "0.0.0.0");
+ dmuci_set_value_by_section(s, "interface", "lan");
+ dmuci_set_value_by_section(s, "enable", "1");
+ *instance = update_instance_icwmpd(s, inst, "dns_server_instance");
+ return 0;
+}
+
+int delete_client_server(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *s = NULL, *ss = NULL;
+ char *interface, *ip, *str, *stmp;
+ struct uci_list *v;
+ struct uci_element *e, *tmp;
+
+ switch (del_action) {
+ case DEL_INST:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "peerdns", &str);
+ if (str[0] == '1')
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &interface);
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", &ip);
+ dmuci_del_list_value("network", interface, "dns", ip);
+ dmuci_delete_by_section((struct uci_section *)data, NULL, NULL);
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "peerdns", &str);
+ if (str[0] == '1')
+ continue;
+ dmuci_get_value_by_section_list(s, "dns", &v);
+ if (v != NULL) {
+ uci_foreach_element_safe(v, e, tmp) {
+ uci_path_foreach_option_eq_safe(icwmpd, "dmmap_dns", "dns_server", "ip", tmp->name, stmp, ss) {
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ dmuci_del_list_value_by_section(s, "dns", tmp->name);
+ }
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+int delete_relay_forwarding(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *s = NULL, *ss = NULL;
+ char *interface, *ip, *str, *stmp;
+ struct uci_list *v;
+ struct uci_element *e, *tmp;
+
+ switch (del_action) {
+ case DEL_INST:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "peerdns", &str);
+ if (str[0] == '1')
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &interface);
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", &ip);
+ dmuci_del_list_value("network", interface, "dns", ip);
+ dmuci_delete_by_section((struct uci_section *)data, NULL, NULL);
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "peerdns", &str);
+ if (str[0] == '1')
+ continue;
+ dmuci_get_value_by_section_list(s, "dns", &v);
+ if (v != NULL) {
+ uci_foreach_element_safe(v, e, tmp) {
+ uci_path_foreach_option_eq_safe(icwmpd, "dmmap_dns", "dns_server", "ip", tmp->name, stmp, ss) {
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ dmuci_del_list_value_by_section(s, "dns", tmp->name);
+ }
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+/***************************************** Get/Set Parameter functions ***********************/
+int get_dns_supported_record_types(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "A,AAAA,PTR";
+ return 0;
+}
+
+int get_client_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int get_client_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Enabled";
+ return 0;
+}
+
+int get_client_server_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ dmmap_synchronizeDNSClientRelayServer(ctx, NULL, NULL, NULL);
+ uci_path_foreach_sections(icwmpd, "dmmap_dns", "dns_server", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+int get_server_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", value);
+ return 0;
+}
+
+int get_server_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &v);
+ *value = (*v == '1') ? "Enabled" : "Disabled";
+ return 0;
+}
+
+int get_server_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dns_server_alias", value);
+ return 0;
+}
+
+int get_server_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", value);
+ return 0;
+}
+
+int get_server_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *linker;
+
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &linker);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
+ return 0;
+}
+
+int get_server_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+ *value = "Static";
+ dmuci_get_value_by_section_string((struct uci_section *)data, "peerdns", &v);
+ if (*v == '1') {
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", &v);
+ if (strchr(v, ':') == NULL) {
+ *value = "DHCPv4";
+ }
+ else {
+ *value = "DHCPv6";
+ }
+ }
+ return 0;
+}
+
+int get_relay_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *path = "/etc/rc.d/*dnsmasq";
+ if (check_file(path))
+ *value = "1";
+ else
+ *value = "0";
+ return 0;
+}
+
+int get_relay_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *path = "/etc/rc.d/*dnsmasq";
+ if (check_file(path))
+ *value = "Enabled";
+ else
+ *value = "Disabled";
+ return 0;
+}
+
+int get_relay_forward_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ dmmap_synchronizeDNSClientRelayServer(ctx, NULL, NULL, NULL);
+ uci_path_foreach_sections(icwmpd, "dmmap_dns", "dns_server", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+int get_forwarding_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", value);
+ return 0;
+}
+
+int get_forwarding_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &v);
+ *value = (*v == '1') ? "Enabled" : "Disabled";
+ return 0;
+}
+
+int get_forwarding_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dns_server_alias", value);
+ return 0;
+}
+
+int get_forwarding_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", value);
+ return 0;
+}
+
+int get_forwarding_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *linker;
+
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &linker);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
+ return 0;
+}
+
+int get_forwarding_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+ *value = "Static";
+ dmuci_get_value_by_section_string((struct uci_section *)data, "peerdns", &v);
+ if (*v == '1') {
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", &v);
+ if (strchr(v, ':') == NULL) {
+ *value = "DHCPv4";
+ }
+ else {
+ *value = "DHCPv6";
+ }
+ }
+ return 0;
+}
+
+int get_nslookupdiagnostics_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = nslookup_get("DiagnosticState", "None");
+ return 0;
+}
+
+int get_nslookupdiagnostics_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@nslookupdiagnostic[0]", "interface", value);
+ return 0;
+}
+
+int get_nslookupdiagnostics_host_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@nslookupdiagnostic[0]", "HostName", value);
+ return 0;
+}
+
+int get_nslookupdiagnostics_d_n_s_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_varstate_string("cwmp", "@nslookupdiagnostic[0]", "DNSServer", value);
+ return 0;
+}
+
+int get_nslookupdiagnostics_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = nslookup_get("Timeout", "5000");
+ return 0;
+}
+
+int get_nslookupdiagnostics_number_of_repetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = nslookup_get("NumberOfRepetitions", "1");
+ return 0;
+}
+
+int get_nslookupdiagnostics_success_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = nslookup_get("SuccessCount", "0");
+ return 0;
+}
+
+int get_nslookupdiagnostics_result_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_foreach_sections_state("cwmp", "NSLookupResult", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt); // MEM WILL BE FREED IN DMMEMCLEAN
+ return 0;
+}
+
+int get_result_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "Status", value);
+ return 0;
+}
+
+int get_result_answer_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "AnswerType", value);
+ return 0;
+}
+
+int get_result_host_name_returned(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "HostNameReturned", value);
+ return 0;
+}
+
+int get_result_i_p_addresses(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "IPAddresses", value);
+ return 0;
+}
+
+int get_result_d_n_s_server_i_p(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "DNSServerIP", value);
+ return 0;
+}
+
+int get_result_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ResponseTime", value);
+ return 0;
+}
+
+int set_client_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int set_server_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *str, *ip, *interface;
+ bool b, ob;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &str);
+ string_to_bool(value, &b);
+ string_to_bool(str, &ob);
+ if (ob == b)
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "peerdns", &str);
+ if (str[0] == '1')
+ return 0;
+ dmuci_set_value_by_section((struct uci_section *)data, "enable", b ? "1" : "0");
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &interface);
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", &ip);
+ if (b == 1) {
+ dmuci_add_list_value("network", interface, "dns", ip);
+ }
+ else {
+ dmuci_del_list_value("network", interface, "dns", ip);
+ }
+ break;
+ }
+ return 0;
+}
+
+int set_server_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "dns_server_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int set_server_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *str, *oip, *interface;
+ struct uci_list *v;
+ struct uci_element *e;
+ int count = 0, i = 0;
+ char *dns[32] = {0};
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", &oip);
+ if (strcmp(oip, value) == 0)
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "peerdns", &str);
+ if (str[0] == '1')
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &interface);
+ dmuci_get_option_value_list("network", interface, "dns", &v);
+ if (v) {
+ uci_foreach_element(v, e) {
+ if (strcmp(e->name, oip)==0)
+ dns[count] = dmstrdup(value);
+ else
+ dns[count] = dmstrdup(e->name);
+ count++;
+ }
+ }
+ dmuci_delete("network", interface, "dns", NULL);
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &str);
+ if (str[0] == '1') {
+ for (i = 0; i < count; i++) {
+ dmuci_add_list_value("network", interface, "dns", dns[i] ? dns[i] : "");
+ dmfree(dns[i]);
+ }
+ }
+ dmuci_set_value_by_section((struct uci_section *)data, "ip", value);
+ break;
+ }
+ return 0;
+}
+
+int set_server_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *str, *ointerface, *ip, *interface;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &ointerface);
+ adm_entry_get_linker_value(ctx, value, &interface);
+ if (strcmp(ointerface, interface) == 0)
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "peerdns", &str);
+ if (str[0] == '1')
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", &ip);
+ dmuci_del_list_value("network", ointerface, "dns", ip);
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &str);
+ if (str[0] == '1') {
+ dmuci_add_list_value("network", interface, "dns", ip);
+ }
+ dmuci_set_value_by_section((struct uci_section *)data, "interface", interface);
+ break;
+ }
+ return 0;
+}
+
+int set_relay_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b)
+ dmcmd("/etc/init.d/dnsmasq", 1, "enable");
+ else
+ dmcmd("/etc/init.d/dnsmasq", 1, "disable");
+ break;
+ }
+ return 0;
+}
+
+int set_forwarding_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *str, *ip, *interface;
+ bool b, ob;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &str);
+ string_to_bool(value, &b);
+ string_to_bool(str, &ob);
+ if (ob == b)
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "peerdns", &str);
+ if (str[0] == '1')
+ return 0;
+ dmuci_set_value_by_section((struct uci_section *)data, "enable", b ? "1" : "0");
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &interface);
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", &ip);
+ if (b == 1) {
+ dmuci_add_list_value("network", interface, "dns", ip);
+ }
+ else {
+ dmuci_del_list_value("network", interface, "dns", ip);
+ }
+ break;
+ }
+ return 0;
+}
+
+int set_forwarding_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "dns_server_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int set_forwarding_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *str, *oip, *interface;
+ struct uci_list *v;
+ struct uci_element *e;
+ int count = 0, i = 0;
+ char *dns[32] = {0};
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", &oip);
+ if (strcmp(oip, value) == 0)
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "peerdns", &str);
+ if (str[0] == '1')
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &interface);
+ dmuci_get_option_value_list("network", interface, "dns", &v);
+ if (v) {
+ uci_foreach_element(v, e) {
+ if (strcmp(e->name, oip)==0)
+ dns[count] = dmstrdup(value);
+ else
+ dns[count] = dmstrdup(e->name);
+ count++;
+ }
+ }
+ dmuci_delete("network", interface, "dns", NULL);
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &str);
+ if (str[0] == '1') {
+ for (i = 0; i < count; i++) {
+ dmuci_add_list_value("network", interface, "dns", dns[i] ? dns[i] : "");
+ dmfree(dns[i]);
+ }
+ }
+ dmuci_set_value_by_section((struct uci_section *)data, "ip", value);
+ break;
+ }
+ return 0;
+}
+
+int set_forwarding_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *str, *ointerface, *ip, *interface;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &ointerface);
+ adm_entry_get_linker_value(ctx, value, &interface);
+ if (strcmp(ointerface, interface) == 0)
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "peerdns", &str);
+ if (str[0] == '1')
+ return 0;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip", &ip);
+ dmuci_del_list_value("network", ointerface, "dns", ip);
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &str);
+ if (str[0] == '1') {
+ dmuci_add_list_value("network", interface, "dns", ip);
+ }
+ dmuci_set_value_by_section((struct uci_section *)data, "interface", interface);
+ break;
+ }
+ return 0;
+}
+
+int set_nslookupdiagnostics_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "Requested") == 0) {
+ NSLOOKUP_STOP
+ curr_section = (struct uci_section *)dmuci_walk_state_section("cwmp", "nslookupdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "nslookupdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@nslookupdiagnostic[0]", "DiagnosticState", value);
+ cwmp_set_end_session(END_SESSION_NSLOOKUP_DIAGNOSTIC);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int set_nslookupdiagnostics_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ NSLOOKUP_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "nslookupdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "nslookupdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@nslookupdiagnostic[0]", "interface", value);
+ return 0;
+ }
+ return 0;
+}
+
+int set_nslookupdiagnostics_host_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ NSLOOKUP_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "nslookupdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "nslookupdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@nslookupdiagnostic[0]", "HostName", value);
+ return 0;
+ }
+ return 0;
+}
+
+int set_nslookupdiagnostics_d_n_s_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ NSLOOKUP_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "nslookupdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "nslookupdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@nslookupdiagnostic[0]", "DNSServer", value);
+ return 0;
+ }
+ return 0;
+}
+
+int set_nslookupdiagnostics_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ NSLOOKUP_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "nslookupdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "nslookupdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@nslookupdiagnostic[0]", "Timeout", value);
+ return 0;
+ }
+ return 0;
+}
+
+int set_nslookupdiagnostics_number_of_repetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *tmp;
+ struct uci_section *curr_section = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ NSLOOKUP_STOP
+ curr_section = dmuci_walk_state_section("cwmp", "nslookupdiagnostic", NULL, NULL, CMP_SECTION, NULL, NULL, GET_FIRST_SECTION);
+ if(!curr_section)
+ {
+ dmuci_add_state_section("cwmp", "nslookupdiagnostic", &curr_section, &tmp);
+ }
+ dmuci_set_varstate_value("cwmp", "@nslookupdiagnostic[0]", "NumberOfRepetitions", value);
+ return 0;
+ }
+ return 0;
+}
+
+
diff --git a/dmtree/tr181/dns.h b/dmtree/tr181/dns.h
new file mode 100644
index 00000000..e0decbd8
--- /dev/null
+++ b/dmtree/tr181/dns.h
@@ -0,0 +1,98 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Amin Ben Ramdhane
+*/
+
+#ifndef _DNS_H
+#define _DNS_H
+
+extern DMOBJ tDNSObj[];
+extern DMLEAF tDNSParams[];
+extern DMLEAF tDNSClientParams[];
+extern DMOBJ tDNSClientObj[];
+extern DMLEAF tDNSClientServerParams[];
+extern DMLEAF tDNSRelayParams[];
+extern DMOBJ tDNSRelayObj[];
+extern DMLEAF tDNSRelayForwardingParams[];
+extern DMOBJ tDNSDiagnosticsObj[];
+extern DMLEAF tDNSDiagnosticsNSLookupDiagnosticsParams[];
+extern DMOBJ tDNSDiagnosticsNSLookupDiagnosticsObj[];
+extern DMLEAF tDNSDiagnosticsNSLookupDiagnosticsResultParams[];
+
+struct NSLookupResult
+{
+ char *Status;
+ char *AnswerType;
+ char *HostNameReturned;
+ char *IPAddresses;
+ char *DNSServerIP;
+ char *ResponseTime;
+};
+
+int browseServerInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseRelayForwardingInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int add_client_server(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int add_relay_forwarding(char *refparam, struct dmctx *ctx, void *data, char **instance);
+
+int delete_client_server(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int delete_relay_forwarding(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+
+int get_dns_supported_record_types(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_client_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_client_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_client_server_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_server_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_server_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_server_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_server_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_server_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_server_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_relay_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_relay_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_relay_forward_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_forwarding_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_forwarding_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_forwarding_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_forwarding_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_forwarding_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_forwarding_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nslookupdiagnostics_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nslookupdiagnostics_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nslookupdiagnostics_host_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nslookupdiagnostics_d_n_s_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nslookupdiagnostics_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nslookupdiagnostics_number_of_repetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nslookupdiagnostics_success_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nslookupdiagnostics_result_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_result_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_result_answer_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_result_host_name_returned(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_result_i_p_addresses(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_result_d_n_s_server_i_p(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_result_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int set_client_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_server_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_server_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_server_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_server_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_relay_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_forwarding_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_forwarding_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_forwarding_dns_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_forwarding_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_nslookupdiagnostics_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_nslookupdiagnostics_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_nslookupdiagnostics_host_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_nslookupdiagnostics_d_n_s_server(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_nslookupdiagnostics_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_nslookupdiagnostics_number_of_repetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+#endif
diff --git a/dmtree/tr181/dsl.c b/dmtree/tr181/dsl.c
new file mode 100644
index 00000000..e1aba539
--- /dev/null
+++ b/dmtree/tr181/dsl.c
@@ -0,0 +1,1546 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: AMIN Ben Ramdhane
+*/
+
+#include
+#include
+#include
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcwmp.h"
+#include "dmcommon.h"
+#include "dmjson.h"
+#include "dmentry.h"
+#include "dsl.h"
+
+#define DELIMITOR ","
+
+/* *** Device.DSL. *** */
+DMOBJ tDSLObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Line", &DMREAD, NULL, NULL, NULL, browseDSLLineInst, NULL, NULL, tDSLLineObj, tDSLLineParams, get_dsl_line_linker, BBFDM_BOTH},
+{"Channel", &DMREAD, NULL, NULL, NULL, browseDSLChannelInst, NULL, NULL, tDSLChannelObj, tDSLChannelParams, get_dsl_channel_linker, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDSLParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"LineNumberOfEntries", &DMREAD, DMT_UNINT, get_DSL_LineNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"ChannelNumberOfEntries", &DMREAD, DMT_UNINT, get_DSL_ChannelNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Line.{i}. *** */
+DMOBJ tDSLLineObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Stats", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDSLLineStatsObj, tDSLLineStatsParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDSLLineParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DSLLine_Enable, set_DSLLine_Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_DSLLine_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DSLLine_Alias, set_DSLLine_Alias, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_DSLLine_Name, NULL, NULL, NULL, BBFDM_BOTH},
+{"LowerLayers", &DMWRITE, DMT_STRING, get_DSLLine_LowerLayers, set_DSLLine_LowerLayers, NULL, NULL, BBFDM_BOTH},
+{"Upstream", &DMREAD, DMT_BOOL, get_DSLLine_Upstream, NULL, NULL, NULL, BBFDM_BOTH},
+{"FirmwareVersion", &DMREAD, DMT_STRING, get_DSLLine_FirmwareVersion, NULL, NULL, NULL, BBFDM_BOTH},
+{"LinkStatus", &DMREAD, DMT_STRING, get_DSLLine_LinkStatus, NULL, NULL, NULL, BBFDM_BOTH},
+{"StandardsSupported", &DMREAD, DMT_STRING, get_DSLLine_StandardsSupported, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTSE", &DMREAD, DMT_HEXBIN, get_DSLLine_XTSE, NULL, NULL, NULL, BBFDM_BOTH},
+{"StandardUsed", &DMREAD, DMT_STRING, get_DSLLine_StandardUsed, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTSUsed", &DMREAD, DMT_HEXBIN, get_DSLLine_XTSUsed, NULL, NULL, NULL, BBFDM_BOTH},
+{"LineEncoding", &DMREAD, DMT_STRING, get_DSLLine_LineEncoding, NULL, NULL, NULL, BBFDM_BOTH},
+{"AllowedProfiles", &DMREAD, DMT_STRING, get_DSLLine_AllowedProfiles, NULL, NULL, NULL, BBFDM_BOTH},
+{"CurrentProfile", &DMREAD, DMT_STRING, get_DSLLine_CurrentProfile, NULL, NULL, NULL, BBFDM_BOTH},
+{"PowerManagementState", &DMREAD, DMT_STRING, get_DSLLine_PowerManagementState, NULL, NULL, NULL, BBFDM_BOTH},
+{"SuccessFailureCause", &DMREAD, DMT_UNINT, get_DSLLine_SuccessFailureCause, NULL, NULL, NULL, BBFDM_BOTH},
+{"UPBOKLERPb", &DMREAD, DMT_STRING, get_DSLLine_UPBOKLERPb, NULL, NULL, NULL, BBFDM_BOTH},
+{"RXTHRSHds", &DMREAD, DMT_INT, get_DSLLine_RXTHRSHds, NULL, NULL, NULL, BBFDM_BOTH},
+{"ACTRAMODEds", &DMREAD, DMT_UNINT, get_DSLLine_ACTRAMODEds, NULL, NULL, NULL, BBFDM_BOTH},
+{"ACTRAMODEus", &DMREAD, DMT_UNINT, get_DSLLine_ACTRAMODEus, NULL, NULL, NULL, BBFDM_BOTH},
+{"SNRMROCus", &DMREAD, DMT_UNINT, get_DSLLine_SNRMROCus, NULL, NULL, NULL, BBFDM_BOTH},
+{"LastStateTransmittedDownstream", &DMREAD, DMT_UNINT, get_DSLLine_LastStateTransmittedDownstream, NULL, NULL, NULL, BBFDM_BOTH},
+{"LastStateTransmittedUpstream", &DMREAD, DMT_UNINT, get_DSLLine_LastStateTransmittedUpstream, NULL, NULL, NULL, BBFDM_BOTH},
+{"US0MASK", &DMREAD, DMT_UNINT, get_DSLLine_US0MASK, NULL, NULL, NULL, BBFDM_BOTH},
+{"TRELLISds", &DMREAD, DMT_INT, get_DSLLine_TRELLISds, NULL, NULL, NULL, BBFDM_BOTH},
+{"TRELLISus", &DMREAD, DMT_INT, get_DSLLine_TRELLISus, NULL, NULL, NULL, BBFDM_BOTH},
+{"ACTSNRMODEds", &DMREAD, DMT_UNINT, get_DSLLine_ACTSNRMODEds, NULL, NULL, NULL, BBFDM_BOTH},
+{"ACTSNRMODEus", &DMREAD, DMT_UNINT, get_DSLLine_ACTSNRMODEus, NULL, NULL, NULL, BBFDM_BOTH},
+{"LineNumber", &DMREAD, DMT_INT, get_DSLLine_LineNumber, NULL, NULL, NULL, BBFDM_BOTH},
+{"UpstreamMaxBitRate", &DMREAD, DMT_UNINT, get_DSLLine_UpstreamMaxBitRate, NULL, NULL, NULL, BBFDM_BOTH},
+{"DownstreamMaxBitRate", &DMREAD, DMT_UNINT, get_DSLLine_DownstreamMaxBitRate, NULL, NULL, NULL, BBFDM_BOTH},
+{"UpstreamNoiseMargin", &DMREAD, DMT_INT, get_DSLLine_UpstreamNoiseMargin, NULL, NULL, NULL, BBFDM_BOTH},
+{"DownstreamNoiseMargin", &DMREAD, DMT_INT, get_DSLLine_DownstreamNoiseMargin, NULL, NULL, NULL, BBFDM_BOTH},
+{"SNRMpbus", &DMREAD, DMT_STRING, get_DSLLine_SNRMpbus, NULL, NULL, NULL, BBFDM_BOTH},
+{"SNRMpbds", &DMREAD, DMT_STRING, get_DSLLine_SNRMpbds, NULL, NULL, NULL, BBFDM_BOTH},
+{"UpstreamAttenuation", &DMREAD, DMT_INT, get_DSLLine_UpstreamAttenuation, NULL, NULL, NULL, BBFDM_BOTH},
+{"DownstreamAttenuation", &DMREAD, DMT_INT, get_DSLLine_DownstreamAttenuation, NULL, NULL, NULL, BBFDM_BOTH},
+{"UpstreamPower", &DMREAD, DMT_INT, get_DSLLine_UpstreamPower, NULL, NULL, NULL, BBFDM_BOTH},
+{"DownstreamPower", &DMREAD, DMT_INT, get_DSLLine_DownstreamPower, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURVendor", &DMREAD, DMT_HEXBIN, get_DSLLine_XTURVendor, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURCountry", &DMREAD, DMT_HEXBIN, get_DSLLine_XTURCountry, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURANSIStd", &DMREAD, DMT_UNINT, get_DSLLine_XTURANSIStd, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURANSIRev", &DMREAD, DMT_UNINT, get_DSLLine_XTURANSIRev, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCVendor", &DMREAD, DMT_HEXBIN, get_DSLLine_XTUCVendor, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCCountry", &DMREAD, DMT_HEXBIN, get_DSLLine_XTUCCountry, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCANSIStd", &DMREAD, DMT_UNINT, get_DSLLine_XTUCANSIStd, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCANSIRev", &DMREAD, DMT_UNINT, get_DSLLine_XTUCANSIRev, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Line.{i}.Stats. *** */
+DMOBJ tDSLLineStatsObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Total", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDSLLineStatsTotalParams, NULL, BBFDM_BOTH},
+{"Showtime", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDSLLineStatsShowtimeParams, NULL, BBFDM_BOTH},
+{"LastShowtime", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDSLLineStatsLastShowtimeParams, NULL, BBFDM_BOTH},
+{"CurrentDay", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDSLLineStatsCurrentDayParams, NULL, BBFDM_BOTH},
+{"QuarterHour", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDSLLineStatsQuarterHourParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDSLLineStatsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"TotalStart", &DMREAD, DMT_UNINT, get_DSLLineStats_TotalStart, NULL, NULL, NULL, BBFDM_BOTH},
+{"ShowtimeStart", &DMREAD, DMT_UNINT, get_DSLLineStats_ShowtimeStart, NULL, NULL, NULL, BBFDM_BOTH},
+{"LastShowtimeStart", &DMREAD, DMT_UNINT, get_DSLLineStats_LastShowtimeStart, NULL, NULL, NULL, BBFDM_BOTH},
+{"CurrentDayStart", &DMREAD, DMT_UNINT, get_DSLLineStats_CurrentDayStart, NULL, NULL, NULL, BBFDM_BOTH},
+{"QuarterHourStart", &DMREAD, DMT_UNINT, get_DSLLineStats_QuarterHourStart, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Line.{i}.Stats.Total. *** */
+DMLEAF tDSLLineStatsTotalParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"ErroredSecs", &DMREAD, DMT_UNINT, get_DSLLineStatsTotal_ErroredSecs, NULL, NULL, NULL, BBFDM_BOTH},
+{"SeverelyErroredSecs", &DMREAD, DMT_UNINT, get_DSLLineStatsTotal_SeverelyErroredSecs, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Line.{i}.Stats.Showtime. *** */
+DMLEAF tDSLLineStatsShowtimeParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"ErroredSecs", &DMREAD, DMT_UNINT, get_DSLLineStatsShowtime_ErroredSecs, NULL, NULL, NULL, BBFDM_BOTH},
+{"SeverelyErroredSecs", &DMREAD, DMT_UNINT, get_DSLLineStatsShowtime_SeverelyErroredSecs, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Line.{i}.Stats.LastShowtime. *** */
+DMLEAF tDSLLineStatsLastShowtimeParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"ErroredSecs", &DMREAD, DMT_UNINT, get_DSLLineStatsLastShowtime_ErroredSecs, NULL, NULL, NULL, BBFDM_BOTH},
+{"SeverelyErroredSecs", &DMREAD, DMT_UNINT, get_DSLLineStatsLastShowtime_SeverelyErroredSecs, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Line.{i}.Stats.CurrentDay. *** */
+DMLEAF tDSLLineStatsCurrentDayParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"ErroredSecs", &DMREAD, DMT_UNINT, get_DSLLineStatsCurrentDay_ErroredSecs, NULL, NULL, NULL, BBFDM_BOTH},
+{"SeverelyErroredSecs", &DMREAD, DMT_UNINT, get_DSLLineStatsCurrentDay_SeverelyErroredSecs, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Line.{i}.Stats.QuarterHour. *** */
+DMLEAF tDSLLineStatsQuarterHourParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"ErroredSecs", &DMREAD, DMT_UNINT, get_DSLLineStatsQuarterHour_ErroredSecs, NULL, NULL, NULL, BBFDM_BOTH},
+{"SeverelyErroredSecs", &DMREAD, DMT_UNINT, get_DSLLineStatsQuarterHour_SeverelyErroredSecs, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Channel.{i}. *** */
+DMOBJ tDSLChannelObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Stats", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDSLChannelStatsObj, tDSLChannelStatsParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDSLChannelParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_DSLChannel_Enable, set_DSLChannel_Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_DSLChannel_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_DSLChannel_Alias, set_DSLChannel_Alias, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_DSLChannel_Name, NULL, NULL, NULL, BBFDM_BOTH},
+{"LowerLayers", &DMREAD, DMT_STRING, get_DSLChannel_LowerLayers, NULL, NULL, NULL, BBFDM_BOTH},
+{"LinkEncapsulationSupported", &DMREAD, DMT_STRING, get_DSLChannel_LinkEncapsulationSupported, NULL, NULL, NULL, BBFDM_BOTH},
+{"LinkEncapsulationUsed", &DMREAD, DMT_STRING, get_DSLChannel_LinkEncapsulationUsed, NULL, NULL, NULL, BBFDM_BOTH},
+{"LPATH", &DMREAD, DMT_UNINT, get_DSLChannel_LPATH, NULL, NULL, NULL, BBFDM_BOTH},
+{"INTLVDEPTH", &DMREAD, DMT_UNINT, get_DSLChannel_INTLVDEPTH, NULL, NULL, NULL, BBFDM_BOTH},
+{"INTLVBLOCK", &DMREAD, DMT_INT, get_DSLChannel_INTLVBLOCK, NULL, NULL, NULL, BBFDM_BOTH},
+{"ActualInterleavingDelay", &DMREAD, DMT_UNINT, get_DSLChannel_ActualInterleavingDelay, NULL, NULL, NULL, BBFDM_BOTH},
+{"ACTINP", &DMREAD, DMT_INT, get_DSLChannel_ACTINP, NULL, NULL, NULL, BBFDM_BOTH},
+{"INPREPORT", &DMREAD, DMT_BOOL, get_DSLChannel_INPREPORT, NULL, NULL, NULL, BBFDM_BOTH},
+{"NFEC", &DMREAD, DMT_INT, get_DSLChannel_NFEC, NULL, NULL, NULL, BBFDM_BOTH},
+{"RFEC", &DMREAD, DMT_INT, get_DSLChannel_RFEC, NULL, NULL, NULL, BBFDM_BOTH},
+{"LSYMB", &DMREAD, DMT_INT, get_DSLChannel_LSYMB, NULL, NULL, NULL, BBFDM_BOTH},
+{"UpstreamCurrRate", &DMREAD, DMT_UNINT, get_DSLChannel_UpstreamCurrRate, NULL, NULL, NULL, BBFDM_BOTH},
+{"DownstreamCurrRate", &DMREAD, DMT_UNINT, get_DSLChannel_DownstreamCurrRate, NULL, NULL, NULL, BBFDM_BOTH},
+{"ACTNDR", &DMREAD, DMT_UNINT, get_DSLChannel_ACTNDR, NULL, NULL, NULL, BBFDM_BOTH},
+{"ACTINPREIN", &DMREAD, DMT_UNINT, get_DSLChannel_ACTINPREIN, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Channel.{i}.Stats. *** */
+DMOBJ tDSLChannelStatsObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Total", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDSLChannelStatsTotalParams, NULL, BBFDM_BOTH},
+{"Showtime", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDSLChannelStatsShowtimeParams, NULL, BBFDM_BOTH},
+{"LastShowtime", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDSLChannelStatsLastShowtimeParams, NULL, BBFDM_BOTH},
+{"CurrentDay", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDSLChannelStatsCurrentDayParams, NULL, BBFDM_BOTH},
+{"QuarterHour", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDSLChannelStatsQuarterHourParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tDSLChannelStatsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"TotalStart", &DMREAD, DMT_UNINT, get_DSLChannelStats_TotalStart, NULL, NULL, NULL, BBFDM_BOTH},
+{"ShowtimeStart", &DMREAD, DMT_UNINT, get_DSLChannelStats_ShowtimeStart, NULL, NULL, NULL, BBFDM_BOTH},
+{"LastShowtimeStart", &DMREAD, DMT_UNINT, get_DSLChannelStats_LastShowtimeStart, NULL, NULL, NULL, BBFDM_BOTH},
+{"CurrentDayStart", &DMREAD, DMT_UNINT, get_DSLChannelStats_CurrentDayStart, NULL, NULL, NULL, BBFDM_BOTH},
+{"QuarterHourStart", &DMREAD, DMT_UNINT, get_DSLChannelStats_QuarterHourStart, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Channel.{i}.Stats.Total. *** */
+DMLEAF tDSLChannelStatsTotalParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"XTURFECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsTotal_XTURFECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCFECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsTotal_XTUCFECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURHECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsTotal_XTURHECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCHECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsTotal_XTUCHECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURCRCErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsTotal_XTURCRCErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCCRCErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsTotal_XTUCCRCErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Channel.{i}.Stats.Showtime. *** */
+DMLEAF tDSLChannelStatsShowtimeParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"XTURFECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsShowtime_XTURFECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCFECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsShowtime_XTUCFECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURHECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsShowtime_XTURHECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCHECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsShowtime_XTUCHECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURCRCErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsShowtime_XTURCRCErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCCRCErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsShowtime_XTUCCRCErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Channel.{i}.Stats.LastShowtime. *** */
+DMLEAF tDSLChannelStatsLastShowtimeParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"XTURFECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsLastShowtime_XTURFECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCFECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsLastShowtime_XTUCFECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURHECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsLastShowtime_XTURHECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCHECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsLastShowtime_XTUCHECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURCRCErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsLastShowtime_XTURCRCErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCCRCErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsLastShowtime_XTUCCRCErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Channel.{i}.Stats.CurrentDay. *** */
+DMLEAF tDSLChannelStatsCurrentDayParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"XTURFECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsCurrentDay_XTURFECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCFECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsCurrentDay_XTUCFECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURHECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsCurrentDay_XTURHECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCHECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsCurrentDay_XTUCHECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURCRCErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsCurrentDay_XTURCRCErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCCRCErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsCurrentDay_XTUCCRCErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.DSL.Channel.{i}.Stats.QuarterHour. *** */
+DMLEAF tDSLChannelStatsQuarterHourParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"XTURFECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsQuarterHour_XTURFECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCFECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsQuarterHour_XTUCFECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURHECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsQuarterHour_XTURHECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCHECErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsQuarterHour_XTUCHECErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTURCRCErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsQuarterHour_XTURCRCErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{"XTUCCRCErrors", &DMREAD, DMT_UNINT, get_DSLChannelStatsQuarterHour_XTUCCRCErrors, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/**************************************************************************
+* LINKER
+***************************************************************************/
+int get_dsl_line_linker(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker)
+{
+ if (data && ((struct dsl_line_args *)data)->id) {
+ dmasprintf(linker, "line_%s", ((struct dsl_line_args *)data)->id);
+ return 0;
+ }
+ *linker = "" ;
+ return 0;
+}
+
+int get_dsl_channel_linker(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker)
+{
+ if (data && ((struct dsl_line_args *)data)->id){
+ dmasprintf(linker, "channel_%s", ((struct dsl_line_args *)data)->id);
+ return 0;
+ }
+ *linker = "" ;
+ return 0;
+}
+
+/**************************************************************************
+* INIT
+***************************************************************************/
+inline int init_dsl_line(struct dsl_line_args *args, struct uci_section *s)
+{
+ args->line_sec = s;
+ return 0;
+}
+
+inline int init_dsl_channel(struct dsl_channel_args *args, struct uci_section *s)
+{
+ args->channel_sec = s;
+ return 0;
+}
+
+/*************************************************************/
+static struct uci_section *update_create_dmmap_dsl_line(char *curr_id)
+{
+ struct uci_section *s = NULL;
+ char *name, *instance;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap", "dsl_line", "id", curr_id, s) {
+ return s;
+ }
+ if (!s) {
+ dmasprintf(&instance, "%d", atoi(curr_id)+1);
+ DMUCI_ADD_SECTION(icwmpd, "dmmap", "dsl_line", &s, &name);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, "id", curr_id);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, "dsl_line_instance", instance);
+ dmfree(instance);
+ }
+ return s;
+}
+
+static struct uci_section *update_create_dmmap_dsl_channel(char *curr_id)
+{
+ struct uci_section *s = NULL;
+ char *name, *instance;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap", "dsl_channel", "id", curr_id, s) {
+ return s;
+ }
+ if (!s) {
+ dmasprintf(&instance, "%d", atoi(curr_id)+1);
+ DMUCI_ADD_SECTION(icwmpd, "dmmap", "dsl_channel", &s, &name);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, "id", curr_id);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, "dsl_channel_instance", instance);
+ dmfree(instance);
+ }
+ return s;
+}
+/*************************************************************
+ * ENTRY METHOD
+/*************************************************************/
+int browseDSLLineInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ json_object *res = NULL, *line_obj = NULL;
+ struct dsl_line_args cur_dsl_line_args = {0};
+ struct uci_section *s = NULL;
+ char *dsl_int = NULL, *dsl_int_last = NULL;
+ int entries = 0;
+
+ dmubus_call("dsl", "status", UBUS_ARGS{}, 0, &res);
+ while (res) {
+ line_obj = dmjson_select_obj_in_array_idx(res, entries, 1, "line");
+ if(line_obj) {
+ cur_dsl_line_args.id = dmjson_get_value(line_obj, 1, "id");
+ entries++;
+ s = update_create_dmmap_dsl_line(cur_dsl_line_args.id);
+ init_dsl_line(&cur_dsl_line_args, s);
+ dsl_int = handle_update_instance(1, dmctx, &dsl_int_last, update_instance_alias, 3, s, "dsl_line_instance", "dsl_line_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&cur_dsl_line_args, dsl_int) == DM_STOP)
+ break;
+ }
+ else
+ break;
+ }
+ return 0;
+}
+
+int browseDSLChannelInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ json_object *res = NULL, *line_obj = NULL, *channel_obj = NULL;
+ struct dsl_channel_args cur_dsl_channel_args = {0};
+ struct uci_section *s = NULL;
+ char *dsl_int = NULL, *dsl_int_last = NULL;
+ int entries_line = 0, entries_channel = 0;
+
+ dmubus_call("dsl", "status", UBUS_ARGS{}, 0, &res);
+ while (res) {
+ line_obj = dmjson_select_obj_in_array_idx(res, entries_line, 1, "line");
+ while (line_obj) {
+ channel_obj = dmjson_select_obj_in_array_idx(line_obj, entries_channel, 1, "channel");
+ if(channel_obj) {
+ cur_dsl_channel_args.id = dmjson_get_value(channel_obj, 1, "id");
+ entries_channel++;
+ s = update_create_dmmap_dsl_channel(cur_dsl_channel_args.id);
+ init_dsl_channel(&cur_dsl_channel_args, s);
+ dsl_int = handle_update_instance(1, dmctx, &dsl_int_last, update_instance_alias, 3, s, "dsl_channel_instance", "dsl_channel_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&cur_dsl_channel_args, dsl_int) == DM_STOP)
+ break;
+ }
+ else
+ break;
+ }
+ entries_line++;
+ if(!line_obj)
+ break;
+ }
+ return 0;
+}
+
+/**************************************************************************
+* COMMON FUNCTIONS
+***************************************************************************/
+static char *get_dsl_value_without_argument(char *command1, char *id, char *command2, char *key)
+{
+ json_object *res;
+ char command[16], *value = "0";
+
+ sprintf(command, "%s.%s", command1, id);
+ dmubus_call(command, command2, UBUS_ARGS{}, 0, &res);
+ value = dmjson_get_value(res, 1, key);
+ return value;
+}
+
+static char *get_dsl_value_without_argument_and_with_two_key(char *command1, char *id, char *command2, char *key1, char *key2)
+{
+ json_object *res;
+ char command[16], *value = "0";
+
+ sprintf(command, "%s.%s", command1, id);
+ dmubus_call(command, command2, UBUS_ARGS{}, 0, &res);
+ value = dmjson_get_value(res, 2, key1, key2);
+ return value;
+}
+
+static char *get_dsl_value_with_argument(char *command1, char *id, char *command2, char *argument, char *key)
+{
+ json_object *res;
+ char command[16], *value = "0";
+
+ sprintf(command, "%s.%s", command1, id);
+ dmubus_call(command, command2, UBUS_ARGS{{"interval", argument, String}}, 1, &res);
+ value = dmjson_get_value(res, 1, key);
+ return value;
+}
+
+static char *get_dsl_value_array_without_argument(char *command1, char *id, char *command2, char *key)
+{
+ json_object *res;
+ char command[16], *value= "0";
+
+ sprintf(command, "%s.%s", command1, id);
+ dmubus_call(command, command2, UBUS_ARGS{}, 0, &res);
+ value = dmjson_get_value_array_all(res, DELIMITOR, 1, key);
+ return value;
+}
+
+/**************************************************************************
+* GET & SET DSL PARAMETERS
+***************************************************************************/
+int get_DSL_LineNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_path_foreach_sections(icwmpd, "dmmap", "dsl_line", s) {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+int get_DSL_ChannelNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_path_foreach_sections(icwmpd, "dmmap", "dsl_channel", s) {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;;
+}
+
+/*#Device.DSL.Line.{i}.Enable!UBUS:dsl.line.0/status//status*/
+int get_DSLLine_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *status = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "status");
+ *value = (strcmp(status, "up") == 0) ? "1" : "0";
+ return 0;
+}
+
+int set_DSLLine_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Status!UBUS:dsl.line.0/status//status*/
+int get_DSLLine_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *status = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "status");
+ *value = (strcmp(status, "up") == 0) ? "Up" : "Down";
+ return 0;
+}
+
+int get_DSLLine_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct dsl_line_args *)data)->line_sec, "dsl_line_alias", value);
+ return 0;
+}
+
+int set_DSLLine_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section(((struct dsl_line_args *)data)->line_sec, "dsl_line_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DSLLine_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ((struct dsl_line_args*)data)->id;
+ return 0;
+}
+
+int get_DSLLine_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "";
+ return 0;
+}
+
+int set_DSLLine_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Upstream!UBUS:dsl.line.0/status//upstream*/
+int get_DSLLine_Upstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "upstream");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.FirmwareVersion!UBUS:dsl.line.0/status//firmware_version*/
+int get_DSLLine_FirmwareVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "firmware_version");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.LinkStatus!UBUS:dsl.line.0/status//link_status*/
+int get_DSLLine_LinkStatus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *link_status = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "link_status");
+ if(strcmp(link_status, "up") == 0)
+ *value = "Up";
+ else if(strcmp(link_status, "initializing") == 0)
+ *value = "Initializing";
+ else if(strcmp(link_status, "no_signal") == 0)
+ *value = "NoSignal";
+ else if(strcmp(link_status, "disabled") == 0)
+ *value = "Disabled";
+ else if(strcmp(link_status, "establishing") == 0)
+ *value = "EstablishingLink";
+ else if(strcmp(link_status, "error") == 0)
+ *value = "Error";
+ else
+ *value = link_status;
+ return 0;
+}
+
+static char *get_dsl_standard(char *str)
+{
+ char *dsl_standard;
+
+ if(strcmp(str, "gdmt_annexa") == 0)
+ dsl_standard = "G.992.1_Annex_A";
+ else if(strcmp(str, "gdmt_annexb") == 0)
+ dsl_standard = "G.992.1_Annex_B";
+ else if(strcmp(str, "gdmt_annexc") == 0)
+ dsl_standard = "G.992.1_Annex_C";
+ else if(strcmp(str, "t1413") == 0)
+ dsl_standard = "T1.413";
+ else if(strcmp(str, "t1413_i2") == 0)
+ dsl_standard = "T1.413i2";
+ else if(strcmp(str, "glite") == 0)
+ dsl_standard = "G.992.2";
+ else if(strcmp(str, "etsi_101_388") == 0)
+ dsl_standard = "ETSI_101_388";
+ else if(strcmp(str, "adsl2_annexa") == 0)
+ dsl_standard = "G.992.3_Annex_A";
+ else if(strcmp(str, "adsl2_annexb") == 0)
+ dsl_standard = "G.992.3_Annex_B";
+ else if(strcmp(str, "adsl2_annexc") == 0)
+ dsl_standard = "G.992.3_Annex_C";
+ else if(strcmp(str, "adsl2_annexi") == 0)
+ dsl_standard = "G.992.3_Annex_I";
+ else if(strcmp(str, "adsl2_annexj") == 0)
+ dsl_standard = "G.992.3_Annex_J";
+ else if(strcmp(str, "adsl2_annexl") == 0)
+ dsl_standard = "G.992.3_Annex_L";
+ else if(strcmp(str, "adsl2_annexm") == 0)
+ dsl_standard = "G.992.3_Annex_M";
+ else if(strcmp(str, "splitterless_adsl2") == 0)
+ dsl_standard = "G.992.4";
+ else if(strcmp(str, "adsl2p_annexa") == 0)
+ dsl_standard = "G.992.5_Annex_A";
+ else if(strcmp(str, "adsl2p_annexb") == 0)
+ dsl_standard = "G.992.5_Annex_B";
+ else if(strcmp(str, "adsl2p_annexc") == 0)
+ dsl_standard = "G.992.5_Annex_C";
+ else if(strcmp(str, "adsl2p_annexi") == 0)
+ dsl_standard = "G.992.5_Annex_I";
+ else if(strcmp(str, "adsl2p_annexj") == 0)
+ dsl_standard = "G.992.5_Annex_J";
+ else if(strcmp(str, "adsl2p_annexm") == 0)
+ dsl_standard = "G.992.5_Annex_M";
+ else if(strcmp(str, "vdsl") == 0)
+ dsl_standard = "G.993.1";
+ else if(strcmp(str, "vdsl2_annexa") == 0)
+ dsl_standard = "G.993.2_Annex_A";
+ else if(strcmp(str, "vdsl2_annexb") == 0)
+ dsl_standard = "G.993.2_Annex_B";
+ else if(strcmp(str, "vdsl2_annexc") == 0)
+ dsl_standard = "G.993.2_Annex_C";
+ else
+ dsl_standard = str;
+
+ return dsl_standard;
+}
+
+/*#Device.DSL.Line.{i}.StandardsSupported!UBUS:dsl.line.0/status//standards_supported*/
+int get_DSLLine_StandardsSupported(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *standards_supported,*pch, *spch, *tmp, *tmpPtr, *str = "";
+
+ *value = "";
+ standards_supported = get_dsl_value_array_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "standards_supported");
+ if(standards_supported[0] == '\0')
+ return 0;
+ for (pch = strtok_r(standards_supported, ",", &spch); pch != NULL; pch = strtok_r(NULL, ",", &spch))
+ {
+ tmp = get_dsl_standard(pch);
+ if(*str == '\0')
+ dmasprintf(&str, "%s", tmp);
+ else {
+ tmpPtr = str;
+ dmasprintf(&str, "%s,%s", tmpPtr, tmp);
+ }
+ }
+ *value = str;
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.XTSE!UBUS:dsl.line.0/status//xtse*/
+int get_DSLLine_XTSE(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *xtse,*pch, *spch, *tmpPtr, *str = "";
+
+ *value = "";
+ xtse = get_dsl_value_array_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "xtse");
+ if(xtse[0] == '\0')
+ return 0;
+ for (pch = strtok_r(xtse, ",", &spch); pch != NULL; pch = strtok_r(NULL, ",", &spch))
+ {
+ if(*str == '\0')
+ dmasprintf(&str, "%s", pch);
+ else {
+ tmpPtr = str;
+ dmasprintf(&str, "%s%s", tmpPtr, pch);
+ }
+ }
+ *value = str;
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.StandardUsed!UBUS:dsl.line.0/status//standard_used*/
+int get_DSLLine_StandardUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *standard_used = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "standard_used");
+ *value = get_dsl_standard(standard_used);
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.XTSUsed!UBUS:dsl.line.0/status//xtse_used*/
+int get_DSLLine_XTSUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *xtse_used,*pch, *spch, *tmpPtr, *str = "";
+
+ *value = "";
+ xtse_used = get_dsl_value_array_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "xtse_used");
+ if(xtse_used[0] == '\0')
+ return 0;
+ for (pch = strtok_r(xtse_used, ",", &spch); pch != NULL; pch = strtok_r(NULL, ",", &spch))
+ {
+ if(*str == '\0')
+ dmasprintf(&str, "%s", pch);
+ else {
+ tmpPtr = str;
+ dmasprintf(&str, "%s%s", tmpPtr, pch);
+ }
+ }
+ *value = str;
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.LineEncoding!UBUS:dsl.line.0/status//line_encoding*/
+int get_DSLLine_LineEncoding(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *line_encoding = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "line_encoding");
+ if(strcmp(line_encoding, "dmt") == 0)
+ *value = "DMT";
+ else if(strcmp(line_encoding, "cap") == 0)
+ *value = "CAP";
+ else if(strcmp(line_encoding, "2b1q") == 0)
+ *value = "2B1Q";
+ else if(strcmp(line_encoding, "43bt") == 0)
+ *value = "43BT";
+ else if(strcmp(line_encoding, "pam") == 0)
+ *value = "PAM";
+ else if(strcmp(line_encoding, "qam") == 0)
+ *value = "QAM";
+ else
+ *value = line_encoding;
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.AllowedProfiles!UBUS:dsl.line.0/status//allowed_profiles*/
+int get_DSLLine_AllowedProfiles(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_array_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "allowed_profiles");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.CurrentProfile!UBUS:dsl.line.0/status//current_profile*/
+int get_DSLLine_CurrentProfile(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "current_profile");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.PowerManagementState!UBUS:dsl.line.0/status//power_management_state*/
+int get_DSLLine_PowerManagementState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *power_management_state = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "power_management_state");
+ if(strcmp(power_management_state, "l0") == 0)
+ *value = "L0";
+ else if(strcmp(power_management_state, "l1") == 0)
+ *value = "L1";
+ else if(strcmp(power_management_state, "l2") == 0)
+ *value = "L2";
+ else if(strcmp(power_management_state, "l3") == 0)
+ *value = "L3";
+ else if(strcmp(power_management_state, "l4") == 0)
+ *value = "L4";
+ else
+ *value = power_management_state;
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.SuccessFailureCause!UBUS:dsl.line.0/status//success_failure_cause*/
+int get_DSLLine_SuccessFailureCause(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "success_failure_cause");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.UPBOKLERPb!UBUS:dsl.line.0/status//upbokler_pb*/
+int get_DSLLine_UPBOKLERPb(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_array_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "upbokler_pb");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.RXTHRSHds!UBUS:dsl.line.0/status//rxthrsh_ds*/
+int get_DSLLine_RXTHRSHds(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_array_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "rxthrsh_ds");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.ACTRAMODEds!UBUS:dsl.line.0/status//act_ra_mode.ds*/
+int get_DSLLine_ACTRAMODEds(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "act_ra_mode", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.ACTRAMODEus!UBUS:dsl.line.0/status//act_ra_mode.us*/
+int get_DSLLine_ACTRAMODEus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "act_ra_mode", "us");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.SNRMROCus!UBUS:dsl.line.0/status//snr_mroc_us*/
+int get_DSLLine_SNRMROCus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "snr_mroc_us");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.LastStateTransmittedDownstream!UBUS:dsl.line.0/status//last_state_transmitted.ds*/
+int get_DSLLine_LastStateTransmittedDownstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "last_state_transmitted", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.LastStateTransmittedUpstream!UBUS:dsl.line.0/status//last_state_transmitted.us*/
+int get_DSLLine_LastStateTransmittedUpstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "last_state_transmitted", "us");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.US0MASK!UBUS:dsl.line.0/status//us0_mask*/
+int get_DSLLine_US0MASK(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "us0_mask");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.TRELLISds!UBUS:dsl.line.0/status//trellis.ds*/
+int get_DSLLine_TRELLISds(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "trellis", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.TRELLISus!UBUS:dsl.line.0/status//trellis.us*/
+int get_DSLLine_TRELLISus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "trellis", "us");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.ACTSNRMODEds!UBUS:dsl.line.0/status//act_snr_mode.ds*/
+int get_DSLLine_ACTSNRMODEds(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "act_snr_mode", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.ACTSNRMODEus!UBUS:dsl.line.0/status//act_snr_mode.us*/
+int get_DSLLine_ACTSNRMODEus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "act_snr_mode", "us");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.LineNumber!UBUS:dsl.line.0/status//line_number*/
+int get_DSLLine_LineNumber(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "line_number");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.UpstreamMaxBitRate!UBUS:dsl.line.0/status//max_bit_rate.us*/
+int get_DSLLine_UpstreamMaxBitRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "max_bit_rate", "us");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.DownstreamMaxBitRate!UBUS:dsl.line.0/status//max_bit_rate.ds*/
+int get_DSLLine_DownstreamMaxBitRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "max_bit_rate", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.UpstreamNoiseMargin!UBUS:dsl.line.0/status//noise_margin.us*/
+int get_DSLLine_UpstreamNoiseMargin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "noise_margin", "us");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.DownstreamNoiseMargin!UBUS:dsl.line.0/status//noise_margin.ds*/
+int get_DSLLine_DownstreamNoiseMargin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "noise_margin", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.SNRMpbus!UBUS:dsl.line.0/status//snr_mpb_us*/
+int get_DSLLine_SNRMpbus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_array_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "snr_mpb_us");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.SNRMpbds!UBUS:dsl.line.0/status//snr_mpb_ds*/
+int get_DSLLine_SNRMpbds(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_array_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "snr_mpb_ds");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.UpstreamAttenuation!UBUS:dsl.line.0/status//attenuation.us*/
+int get_DSLLine_UpstreamAttenuation(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "attenuation", "us");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.DownstreamAttenuation!UBUS:dsl.line.0/status//attenuation.ds*/
+int get_DSLLine_DownstreamAttenuation(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "attenuation", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.UpstreamPower!UBUS:dsl.line.0/status//power.us*/
+int get_DSLLine_UpstreamPower(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "power", "us");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.DownstreamPower!UBUS:dsl.line.0/status//power.ds*/
+int get_DSLLine_DownstreamPower(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.line", ((struct dsl_line_args*)data)->id, "status", "power", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.XTURVendor!UBUS:dsl.line.0/status//xtur_vendor*/
+int get_DSLLine_XTURVendor(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "xtur_vendor");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.XTURCountry!UBUS:dsl.line.0/status//xtur_country*/
+int get_DSLLine_XTURCountry(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "xtur_country");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.XTURANSIStd!UBUS:dsl.line.0/status//xtur_ansi_std*/
+int get_DSLLine_XTURANSIStd(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "xtur_ansi_std");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.XTURANSIRev!UBUS:dsl.line.0/status//xtur_ansi_rev*/
+int get_DSLLine_XTURANSIRev(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "xtur_ansi_rev");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.XTUCVendor!UBUS:dsl.line.0/status//xtuc_vendor*/
+int get_DSLLine_XTUCVendor(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "xtuc_vendor");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.XTUCCountry!UBUS:dsl.line.0/status//xtuc_country*/
+int get_DSLLine_XTUCCountry(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "xtuc_country");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.XTUCANSIStd!UBUS:dsl.line.0/status//xtuc_ansi_std*/
+int get_DSLLine_XTUCANSIStd(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "status", "xtuc_ansi_std");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.XTUCANSIRev!UBUS:dsl.line.0/status//xtuc_ansi_rev*/
+int get_DSLLine_XTUCANSIRev(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line",((struct dsl_line_args*)data)->id, "status", "xtuc_ansi_rev");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.TotalStart!UBUS:dsl.line.0/stats//total_start*/
+int get_DSLLineStats_TotalStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "total_start");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.ShowtimeStart!UBUS:dsl.line.0/stats//showtime_start*/
+int get_DSLLineStats_ShowtimeStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "showtime_start");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.LastShowtimeStart!UBUS:dsl.line.0/stats//last_showtime_start*/
+int get_DSLLineStats_LastShowtimeStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "last_showtime_start");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.CurrentDayStart!UBUS:dsl.line.0/stats//current_day_start*/
+int get_DSLLineStats_CurrentDayStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "current_day_start");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.QuarterHourStart!UBUS:dsl.line.0/stats//quarter_hour_start*/
+int get_DSLLineStats_QuarterHourStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "quarter_hour_start");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.Total.ErroredSecs!UBUS:dsl.line.0/stats//total.errored_secs*/
+int get_DSLLineStatsTotal_ErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "total", "errored_secs");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.Total.SeverelyErroredSecs!UBUS:dsl.line.0/stats//total.severely_errored_secs*/
+int get_DSLLineStatsTotal_SeverelyErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "total", "severely_errored_secs");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.Showtime.ErroredSecs!UBUS:dsl.line.0/stats//showtime.severely_errored_secs*/
+int get_DSLLineStatsShowtime_ErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "showtime", "errored_secs");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.Showtime.SeverelyErroredSecs!UBUS:dsl.line.0/stats//showtime.severely_errored_secs*/
+int get_DSLLineStatsShowtime_SeverelyErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "showtime", "severely_errored_secs");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.LastShowtime.ErroredSecs!UBUS:dsl.line.0/stats//lastshowtime.errored_secs*/
+int get_DSLLineStatsLastShowtime_ErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "lastshowtime", "errored_secs");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.LastShowtime.SeverelyErroredSecs!UBUS:dsl.line.0/stats//lastshowtime.severely_errored_secs*/
+int get_DSLLineStatsLastShowtime_SeverelyErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "lastshowtime", "severely_errored_secs");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.CurrentDay.ErroredSecs!UBUS:dsl.line.0/stats//currentday.errored_secs*/
+int get_DSLLineStatsCurrentDay_ErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "currentday", "errored_secs");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.CurrentDay.SeverelyErroredSecs!UBUS:dsl.line.0/stats//currentday.severely_errored_secs*/
+int get_DSLLineStatsCurrentDay_SeverelyErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "currentday", "severely_errored_secs");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.QuarterHour.ErroredSecs!UBUS:dsl.line.0/stats//quarterhour.severely_errored_secs*/
+int get_DSLLineStatsQuarterHour_ErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "quarterhour", "errored_secs");
+ return 0;
+}
+
+/*#Device.DSL.Line.{i}.Stats.QuarterHour.SeverelyErroredSecs!UBUS:dsl.line.0/stats//quarterhour.severely_errored_secs*/
+int get_DSLLineStatsQuarterHour_SeverelyErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.line", ((struct dsl_line_args*)data)->id, "stats", "quarterhour", "severely_errored_secs");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Enable!UBUS:dsl.channel.0/status//status*/
+int get_DSLChannel_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *status = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "status");
+ *value = (strcmp(status, "up") == 0) ? "1" : "0";
+ return 0;
+}
+
+int set_DSLChannel_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Status!UBUS:dsl.channel.0/status//status*/
+int get_DSLChannel_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *status = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "status");
+ *value = (strcmp(status, "up") == 0) ? "Up" : "Down";
+ return 0;
+}
+
+int get_DSLChannel_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct dsl_channel_args *)data)->channel_sec, "dsl_channel_alias", value);
+ return 0;
+}
+
+int set_DSLChannel_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section(((struct dsl_channel_args *)data)->channel_sec, "dsl_channel_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_DSLChannel_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ((struct dsl_channel_args*)data)->id;
+ return 0;
+}
+
+int get_DSLChannel_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char linker[8];
+ sprintf(linker, "line_%s", ((struct dsl_line_args *)data)->id);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cDSL%cLine%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value); // MEM WILL BE FREED IN DMMEMCLEAN
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+static char *get_dsl_link_encapsulation_standard(char *str)
+{
+ char *dsl_link_encapsulation_standard;
+
+ if(strcmp(str, "adsl2_atm") == 0)
+ dsl_link_encapsulation_standard = "G.992.3_Annex_K_ATM";
+ else if(strcmp(str, "adsl2_ptm") == 0)
+ dsl_link_encapsulation_standard = "G.992.3_Annex_K_PTM";
+ else if(strcmp(str, "vdsl2_atm") == 0)
+ dsl_link_encapsulation_standard = "G.993.2_Annex_K_ATM";
+ else if(strcmp(str, "vdsl2_ptm") == 0)
+ dsl_link_encapsulation_standard = "G.993.2_Annex_K_PTM";
+ else if(strcmp(str, "auto") == 0)
+ dsl_link_encapsulation_standard = "G.994.1";
+
+ return dsl_link_encapsulation_standard;
+}
+
+/*#Device.DSL.Channel.{i}.LinkEncapsulationSupported!UBUS:dsl.channel.0/status//link_encapsulation_supported*/
+int get_DSLChannel_LinkEncapsulationSupported(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *link_encapsulation_supported,*pch, *spch, *tmp, *tmpPtr, *str = "";
+
+ *value = "";
+ link_encapsulation_supported = get_dsl_value_array_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "link_encapsulation_supported");
+ if(link_encapsulation_supported[0] == '\0')
+ return 0;
+ for (pch = strtok_r(link_encapsulation_supported, ",", &spch); pch != NULL; pch = strtok_r(NULL, ",", &spch))
+ {
+ tmp = get_dsl_link_encapsulation_standard(pch);
+ if(*str == '\0')
+ dmasprintf(&str, "%s", tmp);
+ else {
+ tmpPtr = str;
+ dmasprintf(&str, "%s,%s", tmpPtr, tmp);
+ }
+ }
+ *value = str;
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.LinkEncapsulationUsed!UBUS:dsl.channel.0/status//link_encapsulation_used*/
+int get_DSLChannel_LinkEncapsulationUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *link_encapsulation_used = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "link_encapsulation_used");
+ *value = get_dsl_link_encapsulation_standard(link_encapsulation_used);
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.LPATH!UBUS:dsl.channel.0/status//lpath*/
+int get_DSLChannel_LPATH(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "lpath");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.INTLVDEPTH!UBUS:dsl.channel.0/status//intlvdepth*/
+int get_DSLChannel_INTLVDEPTH(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "intlvdepth");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.INTLVBLOCK!UBUS:dsl.channel.0/status//intlvblock*/
+int get_DSLChannel_INTLVBLOCK(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "intlvblock");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.ActualInterleavingDelay!UBUS:dsl.channel.0/status//actual_interleaving_delay*/
+int get_DSLChannel_ActualInterleavingDelay(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "actual_interleaving_delay");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.ACTINP!UBUS:dsl.channel.0/status//actinp*/
+int get_DSLChannel_ACTINP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "actinp");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.INPREPORT!UBUS:dsl.channel.0/status//inpreport*/
+int get_DSLChannel_INPREPORT(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "inpreport");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.NFEC!UBUS:dsl.channel.0/status//nfec*/
+int get_DSLChannel_NFEC(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "nfec");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.RFEC!UBUS:dsl.channel.0/status//rfec*/
+int get_DSLChannel_RFEC(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "rfec");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.LSYMB!UBUS:dsl.channel.0/status//lsymb*/
+int get_DSLChannel_LSYMB(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "lsymb");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.UpstreamCurrRate!UBUS:dsl.channel.0/status//curr_rate.us*/
+int get_DSLChannel_UpstreamCurrRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "curr_rate", "us");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.DownstreamCurrRate!UBUS:dsl.channel.0/status//curr_rate.ds*/
+int get_DSLChannel_DownstreamCurrRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "curr_rate", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.ACTNDR!UBUS:dsl.channel.0/status//actndr.ds*/
+int get_DSLChannel_ACTNDR(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "actndr", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.ACTINPREIN!UBUS:dsl.channel.0/status//actinprein.ds*/
+int get_DSLChannel_ACTINPREIN(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument_and_with_two_key("dsl.channel", ((struct dsl_channel_args*)data)->id, "status", "actinprein", "ds");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.TotalStart!UBUS:dsl.channel.0/stats//total_start*/
+int get_DSLChannelStats_TotalStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "total_start");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.ShowtimeStart(!UBUS:dsl.channel.0/stats//showtime_start*/
+int get_DSLChannelStats_ShowtimeStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "showtime_start");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.LastShowtimeStart!UBUS:dsl.channel.0/stats//last_showtime_start*/
+int get_DSLChannelStats_LastShowtimeStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "last_showtime_start");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.CurrentDayStart!UBUS:dsl.channel.0/stats//current_day_start*/
+int get_DSLChannelStats_CurrentDayStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "current_day_start");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.QuarterHourStart!UBUS:dsl.channel.0/stats//quarter_hour_start*/
+int get_DSLChannelStats_QuarterHourStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_without_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "quarter_hour_start");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Total.XTURFECErrors!UBUS:dsl.channel.0/stats//total.xtur_fec_errors*/
+int get_DSLChannelStatsTotal_XTURFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "total", "xtur_fec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Total.XTUCFECErrors!UBUS:dsl.channel.0/stats//total.xtur_fec_errors*/
+int get_DSLChannelStatsTotal_XTUCFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "total", "xtuc_fec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Total.XTURHECErrors!UBUS:dsl.channel.0/stats//total.xtur_fec_errors*/
+int get_DSLChannelStatsTotal_XTURHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "total", "xtur_hec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Total.XTUCHECErrors!UBUS:dsl.channel.0/stats//total.xtur_fec_errors*/
+int get_DSLChannelStatsTotal_XTUCHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "total", "xtuc_hec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Total.XTURCRCErrors!UBUS:dsl.channel.0/stats//total.xtur_fec_errors*/
+int get_DSLChannelStatsTotal_XTURCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "total", "xtur_crc_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Total.XTUCCRCErrors!UBUS:dsl.channel.0/stats//total.xtur_fec_errors*/
+int get_DSLChannelStatsTotal_XTUCCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "total", "xtuc_crc_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Showtime.XTURFECErrors!UBUS:dsl.channel.0/stats//showtime.xtur_fec_errors*/
+int get_DSLChannelStatsShowtime_XTURFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "showtime", "xtur_fec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Showtime.XTUCFECErrors!UBUS:dsl.channel.0/stats//showtime.xtuc_fec_errors*/
+int get_DSLChannelStatsShowtime_XTUCFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "showtime", "xtuc_fec_errors");
+ return 0;}
+
+/*#Device.DSL.Channel.{i}.Stats.Showtime.XTURHECErrors!UBUS:dsl.channel.0/stats//showtime.xtur_hec_errors*/
+int get_DSLChannelStatsShowtime_XTURHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "showtime", "xtur_hec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Showtime.XTUCHECErrors!UBUS:dsl.channel.0/stats//showtime.xtuc_hec_errors*/
+int get_DSLChannelStatsShowtime_XTUCHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "showtime", "xtuc_hec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Showtime.XTURCRCErrors!UBUS:dsl.channel.0/stats//showtime.xtur_crc_errors*/
+int get_DSLChannelStatsShowtime_XTURCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "showtime", "xtur_crc_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.Showtime.XTUCCRCErrors!UBUS:dsl.channel.0/stats//showtime.xtuc_crc_errors*/
+int get_DSLChannelStatsShowtime_XTUCCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "showtime", "xtuc_crc_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.LastShowtime.XTURFECErrors!UBUS:dsl.channel.0/stats//lastshowtime.xtur_fec_errors*/
+int get_DSLChannelStatsLastShowtime_XTURFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "lastshowtime", "xtur_fec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.LastShowtime.XTUCFECErrors!UBUS:dsl.channel.0/stats//lastshowtime.xtuc_fec_errors*/
+int get_DSLChannelStatsLastShowtime_XTUCFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "lastshowtime", "xtuc_fec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.LastShowtime.XTURHECErrors!UBUS:dsl.channel.0/stats//lastshowtime.xtur_hec_errors*/
+int get_DSLChannelStatsLastShowtime_XTURHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "lastshowtime", "xtur_hec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.LastShowtime.XTUCHECErrors!UBUS:dsl.channel.0/stats//lastshowtime.xtuc_hec_errors*/
+int get_DSLChannelStatsLastShowtime_XTUCHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "lastshowtime", "xtuc_hec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.LastShowtime.XTURCRCErrors!UBUS:dsl.channel.0/stats//lastshowtime.xtur_crc_errors*/
+int get_DSLChannelStatsLastShowtime_XTURCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "lastshowtime", "xtur_crc_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.LastShowtime.XTUCCRCErrors!UBUS:dsl.channel.0/stats//lastshowtime.xtuc_crc_errors*/
+int get_DSLChannelStatsLastShowtime_XTUCCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "lastshowtime", "xtuc_crc_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.CurrentDay.XTURFECErrors!UBUS:dsl.channel.0/stats//currentday.xtur_fec_errors*/
+int get_DSLChannelStatsCurrentDay_XTURFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "currentday", "xtur_fec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.CurrentDay.XTUCFECErrors!UBUS:dsl.channel.0/stats//currentday.xtuc_fec_errors*/
+int get_DSLChannelStatsCurrentDay_XTUCFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "currentday", "xtuc_fec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.CurrentDay.XTURHECErrors!UBUS:dsl.channel.0/stats//currentday.xtur_hec_errors*/
+int get_DSLChannelStatsCurrentDay_XTURHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "currentday", "xtur_hec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.CurrentDay.XTUCHECErrors!UBUS:dsl.channel.0/stats//currentday.xtuc_hec_errors*/
+int get_DSLChannelStatsCurrentDay_XTUCHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "currentday", "xtuc_hec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.CurrentDay.XTURCRCErrors!UBUS:dsl.channel.0/stats//currentday.xtur_crc_errors*/
+int get_DSLChannelStatsCurrentDay_XTURCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "currentday", "xtur_crc_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.CurrentDay.XTUCCRCErrors!UBUS:dsl.channel.0/stats//currentday.xtuc_crc_errors*/
+int get_DSLChannelStatsCurrentDay_XTUCCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "currentday", "xtuc_crc_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.QuarterHour.XTURFECErrors!UBUS:dsl.channel.0/stats//quarterhour.xtur_fec_errors*/
+int get_DSLChannelStatsQuarterHour_XTURFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "quarterhour", "xtur_fec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.QuarterHour.XTUCFECErrors!UBUS:dsl.channel.0/stats//quarterhour.xtuc_fec_errors*/
+int get_DSLChannelStatsQuarterHour_XTUCFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "quarterhour", "xtuc_fec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.QuarterHour.XTURHECErrors!UBUS:dsl.channel.0/stats//quarterhour.xtur_hec_errors*/
+int get_DSLChannelStatsQuarterHour_XTURHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "quarterhour", "xtur_hec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.QuarterHour.XTUCHECErrors!UBUS:dsl.channel.0/stats//quarterhour.xtuc_hec_errors*/
+int get_DSLChannelStatsQuarterHour_XTUCHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "quarterhour", "xtuc_hec_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.QuarterHour.XTURCRCErrors!UBUS:dsl.channel.0/stats//quarterhour.xtur_crc_errors*/
+int get_DSLChannelStatsQuarterHour_XTURCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "quarterhour", "xtur_crc_errors");
+ return 0;
+}
+
+/*#Device.DSL.Channel.{i}.Stats.QuarterHour.XTUCCRCErrors!UBUS:dsl.channel.0/stats//quarterhour.xtuc_crc_errors*/
+int get_DSLChannelStatsQuarterHour_XTUCCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_dsl_value_with_argument("dsl.channel", ((struct dsl_channel_args*)data)->id, "stats", "quarterhour", "xtuc_crc_errors");
+ return 0;
+}
diff --git a/dmtree/tr181/dsl.h b/dmtree/tr181/dsl.h
new file mode 100644
index 00000000..a50c6f23
--- /dev/null
+++ b/dmtree/tr181/dsl.h
@@ -0,0 +1,179 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: AMIN Ben Ramdhane
+*/
+
+#ifndef __DSL_H
+#define __DSL_H
+
+struct dsl_line_args
+{
+ struct uci_section *line_sec;
+ char *id;
+};
+
+struct dsl_channel_args
+{
+ struct uci_section *channel_sec;
+ char *id;
+};
+
+extern DMOBJ tDSLObj[];
+extern DMLEAF tDSLParams[];
+extern DMOBJ tDSLLineObj[];
+extern DMLEAF tDSLLineParams[];
+extern DMOBJ tDSLLineStatsObj[];
+extern DMLEAF tDSLLineStatsParams[];
+extern DMLEAF tDSLLineStatsTotalParams[];
+extern DMLEAF tDSLLineStatsShowtimeParams[];
+extern DMLEAF tDSLLineStatsLastShowtimeParams[];
+extern DMLEAF tDSLLineStatsCurrentDayParams[];
+extern DMLEAF tDSLLineStatsQuarterHourParams[];
+extern DMOBJ tDSLChannelObj[];
+extern DMLEAF tDSLChannelParams[];
+extern DMOBJ tDSLChannelStatsObj[];
+extern DMLEAF tDSLChannelStatsParams[];
+extern DMLEAF tDSLChannelStatsTotalParams[];
+extern DMLEAF tDSLChannelStatsShowtimeParams[];
+extern DMLEAF tDSLChannelStatsLastShowtimeParams[];
+extern DMLEAF tDSLChannelStatsCurrentDayParams[];
+extern DMLEAF tDSLChannelStatsQuarterHourParams[];
+
+int browseDSLLineInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseDSLChannelInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int get_dsl_line_linker(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+int get_dsl_channel_linker(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+
+int get_DSL_LineNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSL_ChannelNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DSLLine_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DSLLine_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DSLLine_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DSLLine_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DSLLine_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DSLLine_Upstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_FirmwareVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_LinkStatus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_StandardsSupported(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_XTSE(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_StandardUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_XTSUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_LineEncoding(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_AllowedProfiles(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_CurrentProfile(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_PowerManagementState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_SuccessFailureCause(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_UPBOKLERPb(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_RXTHRSHds(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_ACTRAMODEds(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_ACTRAMODEus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_SNRMROCus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_LastStateTransmittedDownstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_LastStateTransmittedUpstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_US0MASK(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_TRELLISds(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_TRELLISus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_ACTSNRMODEds(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_ACTSNRMODEus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_LineNumber(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_UpstreamMaxBitRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_DownstreamMaxBitRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_UpstreamNoiseMargin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_DownstreamNoiseMargin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_SNRMpbus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_SNRMpbds(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_UpstreamAttenuation(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_DownstreamAttenuation(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_UpstreamPower(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_DownstreamPower(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_XTURVendor(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_XTURCountry(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_XTURANSIStd(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_XTURANSIRev(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_XTUCVendor(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_XTUCCountry(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_XTUCANSIStd(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLine_XTUCANSIRev(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStats_TotalStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStats_ShowtimeStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStats_LastShowtimeStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStats_CurrentDayStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStats_QuarterHourStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStatsTotal_ErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStatsTotal_SeverelyErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStatsShowtime_ErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStatsShowtime_SeverelyErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStatsLastShowtime_ErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStatsLastShowtime_SeverelyErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStatsCurrentDay_ErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStatsCurrentDay_SeverelyErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStatsQuarterHour_ErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLLineStatsQuarterHour_SeverelyErroredSecs(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DSLChannel_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DSLChannel_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_DSLChannel_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_DSLChannel_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_LinkEncapsulationSupported(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_LinkEncapsulationUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_LPATH(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_INTLVDEPTH(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_INTLVBLOCK(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_ActualInterleavingDelay(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_ACTINP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_INPREPORT(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_NFEC(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_RFEC(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_LSYMB(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_UpstreamCurrRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_DownstreamCurrRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_ACTNDR(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannel_ACTINPREIN(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStats_TotalStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStats_ShowtimeStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStats_LastShowtimeStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStats_CurrentDayStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStats_QuarterHourStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsTotal_XTURFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsTotal_XTUCFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsTotal_XTURHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsTotal_XTUCHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsTotal_XTURCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsTotal_XTUCCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsShowtime_XTURFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsShowtime_XTUCFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsShowtime_XTURHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsShowtime_XTUCHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsShowtime_XTURCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsShowtime_XTUCCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsLastShowtime_XTURFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsLastShowtime_XTUCFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsLastShowtime_XTURHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsLastShowtime_XTUCHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsLastShowtime_XTURCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsLastShowtime_XTUCCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsCurrentDay_XTURFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsCurrentDay_XTUCFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsCurrentDay_XTURHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsCurrentDay_XTUCHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsCurrentDay_XTURCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsCurrentDay_XTUCCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsQuarterHour_XTURFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsQuarterHour_XTUCFECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsQuarterHour_XTURHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsQuarterHour_XTUCHECErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsQuarterHour_XTURCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_DSLChannelStatsQuarterHour_XTUCCRCErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+#endif //__DSL_H
diff --git a/dmtree/tr181/ethernet.c b/dmtree/tr181/ethernet.c
new file mode 100644
index 00000000..51fdbf1f
--- /dev/null
+++ b/dmtree/tr181/ethernet.c
@@ -0,0 +1,1509 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB
+ * Author: Anis Ellouze
+ * Author: Amin Ben Ramdhane
+ *
+ */
+
+#include
+#include
+#include
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcwmp.h"
+#include "dmcommon.h"
+#include "ethernet.h"
+#include "dmjson.h"
+#include "dmentry.h"
+
+char *wan_ifname = NULL;
+
+/* *** Device.Ethernet. *** */
+DMOBJ tEthernetObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Interface", &DMREAD, NULL, NULL, NULL, browseEthernetInterfaceInst, NULL, NULL, tEthernetInterfaceObj, tEthernetInterfaceParams, get_linker_interface, BBFDM_BOTH},
+{"Link", &DMWRITE, addObjEthernetLink, delObjEthernetLink, NULL, browseEthernetLinkInst, NULL, NULL, tEthernetLinkObj, tEthernetLinkParams, get_linker_link, BBFDM_BOTH},
+{"VLANTermination", &DMWRITE, addObjEthernetVLANTermination, delObjEthernetVLANTermination, NULL, browseEthernetVLANTerminationInst, NULL, NULL, tEthernetVLANTerminationObj, tEthernetVLANTerminationParams, get_linker_vlan_term, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tEthernetParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"InterfaceNumberOfEntries", &DMREAD, DMT_UNINT, get_Ethernet_InterfaceNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"LinkNumberOfEntries", &DMREAD, DMT_UNINT, get_Ethernet_LinkNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"VLANTerminationNumberOfEntries", &DMREAD, DMT_UNINT, get_Ethernet_VLANTerminationNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Ethernet.Interface.{i}. *** */
+DMOBJ tEthernetInterfaceObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Stats", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tEthernetInterfaceStatsParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tEthernetInterfaceParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_EthernetInterface_Enable, set_EthernetInterface_Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_EthernetInterface_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_EthernetInterface_Alias, set_EthernetInterface_Alias, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_EthernetInterface_Name, NULL, NULL, NULL, BBFDM_BOTH},
+{"LastChange", &DMREAD, DMT_UNINT, get_EthernetInterface_LastChange, NULL, NULL, NULL, BBFDM_BOTH},
+{"LowerLayers", &DMWRITE, DMT_STRING, get_EthernetInterface_LowerLayers, set_EthernetInterface_LowerLayers, NULL, NULL, BBFDM_BOTH},
+{"Upstream", &DMREAD, DMT_BOOL, get_EthernetInterface_Upstream, NULL, NULL, NULL, BBFDM_BOTH},
+{"MACAddress", &DMREAD, DMT_STRING, get_EthernetInterface_MACAddress, NULL, NULL, NULL, BBFDM_BOTH},
+{"MaxBitRate", &DMWRITE, DMT_INT, get_EthernetInterface_MaxBitRate, set_EthernetInterface_MaxBitRate, NULL, NULL, BBFDM_BOTH},
+{"CurrentBitRate", &DMREAD, DMT_UNINT, get_EthernetInterface_CurrentBitRate, NULL, NULL, NULL, BBFDM_BOTH},
+{"DuplexMode", &DMWRITE, DMT_STRING, get_EthernetInterface_DuplexMode, set_EthernetInterface_DuplexMode, NULL, NULL, BBFDM_BOTH},
+{"EEECapability", &DMREAD, DMT_BOOL, get_EthernetInterface_EEECapability, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Ethernet.Interface.{i}.Stats. *** */
+DMLEAF tEthernetInterfaceStatsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"BytesSent", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_BytesSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"BytesReceived", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_BytesReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsSent", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_PacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsReceived", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_PacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"ErrorsSent", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_ErrorsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"ErrorsReceived", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_ErrorsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnicastPacketsSent", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_UnicastPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnicastPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_UnicastPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"DiscardPacketsSent", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_DiscardPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"DiscardPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_DiscardPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"MulticastPacketsSent", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_MulticastPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"MulticastPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_MulticastPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"BroadcastPacketsSent", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_BroadcastPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"BroadcastPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_BroadcastPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnknownProtoPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetInterfaceStats_UnknownProtoPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Ethernet.Link.{i}. *** */
+DMOBJ tEthernetLinkObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Stats", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tEthernetLinkStatsParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tEthernetLinkParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_EthernetLink_Enable, set_EthernetLink_Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_EthernetLink_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_EthernetLink_Alias, set_EthernetLink_Alias, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_EthernetLink_Name, NULL, NULL, NULL, BBFDM_BOTH},
+{"LastChange", &DMREAD, DMT_UNINT, get_EthernetLink_LastChange, NULL, NULL, NULL, BBFDM_BOTH},
+{"LowerLayers", &DMWRITE, DMT_STRING, get_EthernetLink_LowerLayers, set_EthernetLink_LowerLayers, NULL, NULL, BBFDM_BOTH},
+{"MACAddress", &DMREAD, DMT_STRING, get_EthernetLink_MACAddress, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Ethernet.Link.{i}.Stats. *** */
+DMLEAF tEthernetLinkStatsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"BytesSent", &DMREAD, DMT_UNINT, get_EthernetLinkStats_BytesSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"BytesReceived", &DMREAD, DMT_UNINT, get_EthernetLinkStats_BytesReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsSent", &DMREAD, DMT_UNINT, get_EthernetLinkStats_PacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsReceived", &DMREAD, DMT_UNINT, get_EthernetLinkStats_PacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"ErrorsSent", &DMREAD, DMT_UNINT, get_EthernetLinkStats_ErrorsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"ErrorsReceived", &DMREAD, DMT_UNINT, get_EthernetLinkStats_ErrorsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnicastPacketsSent", &DMREAD, DMT_UNINT, get_EthernetLinkStats_UnicastPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnicastPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetLinkStats_UnicastPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"DiscardPacketsSent", &DMREAD, DMT_UNINT, get_EthernetLinkStats_DiscardPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"DiscardPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetLinkStats_DiscardPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"MulticastPacketsSent", &DMREAD, DMT_UNINT, get_EthernetLinkStats_MulticastPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"MulticastPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetLinkStats_MulticastPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"BroadcastPacketsSent", &DMREAD, DMT_UNINT, get_EthernetLinkStats_BroadcastPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"BroadcastPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetLinkStats_BroadcastPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnknownProtoPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetLinkStats_UnknownProtoPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Ethernet.VLANTermination.{i}. *** */
+DMOBJ tEthernetVLANTerminationObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Stats", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tEthernetVLANTerminationStatsParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tEthernetVLANTerminationParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_EthernetVLANTermination_Enable, set_EthernetVLANTermination_Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_EthernetVLANTermination_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_EthernetVLANTermination_Alias, set_EthernetVLANTermination_Alias, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_EthernetVLANTermination_Name, NULL, NULL, NULL, BBFDM_BOTH},
+{"LastChange", &DMREAD, DMT_UNINT, get_EthernetVLANTermination_LastChange, NULL, NULL, NULL, BBFDM_BOTH},
+{"LowerLayers", &DMWRITE, DMT_STRING, get_EthernetVLANTermination_LowerLayers, set_EthernetVLANTermination_LowerLayers, NULL, NULL, BBFDM_BOTH},
+{"VLANID", &DMWRITE, DMT_UNINT, get_EthernetVLANTermination_VLANID, set_EthernetVLANTermination_VLANID, NULL, NULL, BBFDM_BOTH},
+{"TPID", &DMWRITE, DMT_UNINT, get_EthernetVLANTermination_TPID, set_EthernetVLANTermination_TPID, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Ethernet.VLANTermination.{i}.Stats. *** */
+DMLEAF tEthernetVLANTerminationStatsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"BytesSent", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_BytesSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"BytesReceived", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_BytesReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsSent", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_PacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsReceived", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_PacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"ErrorsSent", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_ErrorsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"ErrorsReceived", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_ErrorsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnicastPacketsSent", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_UnicastPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnicastPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_UnicastPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"DiscardPacketsSent", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_DiscardPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"DiscardPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_DiscardPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"MulticastPacketsSent", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_MulticastPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"MulticastPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_MulticastPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"BroadcastPacketsSent", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_BroadcastPacketsSent, NULL, NULL, NULL, BBFDM_BOTH},
+{"BroadcastPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_BroadcastPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnknownProtoPacketsReceived", &DMREAD, DMT_UNINT, get_EthernetVLANTerminationStats_UnknownProtoPacketsReceived, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*************************************************************
+ * INIT
+/*************************************************************/
+inline int init_eth_port(struct eth_port_args *args, struct uci_section *s, char *ifname)
+{
+ args->eth_port_sec = s;
+ args->ifname = ifname;
+ return 0;
+}
+
+/*************************************************************
+ * COMMON Functions
+/*************************************************************/
+static int is_mac_exist(char *macaddr)
+{
+ struct uci_section *s = NULL;
+ char *mac;
+
+ uci_path_foreach_sections(icwmpd, DMMAP, "link", s) {
+ dmuci_get_value_by_section_string(s, "mac", &mac);
+ if (strcmp(mac, macaddr) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+static void create_link(char *ifname)
+{
+ char *macaddr, *v, *device;
+ struct uci_section *dmmap = NULL;
+
+ macaddr = get_macaddr(ifname);
+ if (macaddr[0] == '\0')
+ return;
+
+ device = get_device(ifname);
+ if (device[0] == '\0')
+ return;
+
+ /* Interfaces might share the same mac address */
+ if (is_mac_exist(macaddr))
+ return;
+
+ dmuci_add_section_icwmpd(DMMAP, "link", &dmmap, &v);
+ dmuci_set_value_by_section(dmmap, "mac", macaddr);
+ dmuci_set_value_by_section(dmmap, "device", device);
+ dmuci_set_value_by_section(dmmap, "section_name", ifname);
+}
+
+static int dmmap_synchronizeEthernetLink(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ char *type, *ifname;
+
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if (strcmp(type, "alias") == 0 || strcmp(section_name(s), "loopback") == 0)
+ continue;
+
+ dmuci_get_value_by_section_string(s, "ifname", &ifname);
+ if (*ifname == '\0' || *ifname == '@')
+ continue;
+
+ create_link(section_name(s));
+ }
+ return 0;
+}
+
+/*************************************************************
+ * ENTRY METHOD
+/*************************************************************/
+/*#Device.Ethernet.Interface.{i}.!UCI:ports/ethport/dmmap_ports*/
+int browseEthernetInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *int_num = NULL, *int_num_last = NULL, *ifname;
+ struct eth_port_args curr_eth_port_args = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap("ports", "ethport", "dmmap_ports", &dup_list);
+ dmuci_get_option_value_string("ports", "WAN", "ifname", &wan_ifname);
+ list_for_each_entry(p, &dup_list, list) {
+ dmuci_get_value_by_section_string(p->config_section, "ifname", &ifname);
+ if (strcmp(ifname, wan_ifname) == 0) {
+ if(strchr(ifname, '.')== NULL)
+ dmasprintf(&ifname, "%s.1", ifname);
+ }
+ init_eth_port(&curr_eth_port_args, p->config_section, ifname);
+ int_num = handle_update_instance(1, dmctx, &int_num_last, update_instance_alias, 3, p->dmmap_section, "eth_port_instance", "eth_port_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_eth_port_args, int_num) == DM_STOP)
+ break;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
+
+int browseEthernetLinkInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct dm_args args = {0};
+ struct uci_section *s = NULL;
+ char *id_last = NULL, *id = NULL;
+
+ dmmap_synchronizeEthernetLink(dmctx, NULL, NULL, NULL);
+ uci_path_foreach_sections(icwmpd, DMMAP, "link", s) {
+ args.section = s;
+ id = handle_update_instance(1, dmctx, &id_last, update_instance_alias_icwmpd, 3, s, "link_instance", "link_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&args, id) == DM_STOP) {
+ break;
+ }
+ }
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.!UCI:network/device/dmmap_network*/
+int browseEthernetVLANTerminationInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *vlan_term = NULL, *vlan_term_last = NULL, *type= NULL, *vlan_method= NULL;
+ struct dm_args curr_vlan_term_args = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap("network", "device", "dmmap_network", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ dmuci_get_value_by_section_string(p->config_section, "type", &type);
+ dmuci_get_option_value_string("cwmp", "cpe", "vlan_method", &vlan_method);
+ if ((strcmp(vlan_method, "2") != 0 && strcmp(vlan_method, "1") != 0) || (strcmp(vlan_method, "1") == 0 && strcmp(type, "untagged") == 0) )
+ continue;
+ curr_vlan_term_args.section = p->config_section;
+ if(strcmp(vlan_method, "2") == 0)
+ vlan_term = handle_update_instance(1, dmctx, &vlan_term_last, update_instance_alias, 3, p->dmmap_section, "all_vlan_term_instance", "all_vlan_term_alias");
+ else
+ vlan_term = handle_update_instance(1, dmctx, &vlan_term_last, update_instance_alias, 3, p->dmmap_section, "only_tagged_vlan_term_instance", "vlan_term_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_vlan_term_args, vlan_term) == DM_STOP)
+ break;
+ }
+
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
+
+/*************************************************************
+* LINKER
+**************************************************************/
+int get_linker_interface(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker)
+{
+ if (data && ((struct eth_port_args *)data)->ifname) {
+ *linker = ((struct eth_port_args *)data)->ifname;
+ return 0;
+ } else {
+ *linker = "";
+ return 0;
+ }
+}
+
+int get_linker_link(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker)
+{
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "mac", linker);
+ return 0;
+}
+
+int get_linker_vlan_term(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker)
+{
+ if(((struct dm_args *)data)->section) {
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", linker);
+ return 0;
+ } else {
+ *linker = "";
+ return 0;
+ }
+}
+
+/*************************************************************
+ * ADD & DEL OBJ
+/*************************************************************/
+int addObjEthernetLink(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ char *inst, *v;
+ struct uci_section *dmmap_network= NULL;
+
+ inst = get_last_instance_icwmpd(DMMAP, "link", "link_instance");
+
+ dmuci_add_section_icwmpd(DMMAP, "link", &dmmap_network, &v);
+ *instance = update_instance_icwmpd(dmmap_network, inst, "link_instance");
+ return 0;
+}
+
+int delObjEthernetLink(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ switch (del_action) {
+ case DEL_INST:
+ dmuci_delete_by_section(((struct dm_args *)data)->section, NULL, NULL);
+ break;
+ case DEL_ALL:
+ DMUCI_DEL_SECTION(icwmpd, DMMAP, "link", NULL, NULL);
+ break;
+ }
+
+ return 0;
+}
+
+int addObjEthernetVLANTermination(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ char *inst, *v, *eth_wan, *vid, *name, *vlan_name, *vlan_method = NULL;
+ struct uci_section *dmmap_network= NULL;
+
+ check_create_dmmap_package("dmmap_network");
+ dmuci_get_option_value_string("cwmp", "cpe", "vlan_method", &vlan_method);
+ if(strcmp(vlan_method, "2") == 0)
+ inst = get_vlan_last_instance_icwmpd("dmmap_network", "device", "all_vlan_term_instance", vlan_method);
+ else
+ inst = get_vlan_last_instance_icwmpd("dmmap_network", "device", "only_tagged_vlan_term_instance", vlan_method);
+
+ dmuci_get_option_value_string("ports", "WAN", "ifname", ð_wan);
+ dmasprintf(&vid, "%d", inst?atoi(inst)+4:4);
+ dmasprintf(&vlan_name, "vlan_%s", vid);
+ dmuci_set_value("network", vlan_name, "", "device");
+ dmuci_set_value("network", vlan_name, "ifname", eth_wan);
+ dmuci_set_value("network", vlan_name, "type", "8021q");
+ dmuci_set_value("network", vlan_name, "vid", vid);
+ dmasprintf(&name, "%s.%s", eth_wan, vid);
+ dmuci_set_value("network", vlan_name, "name", name);
+
+ dmuci_add_section_icwmpd("dmmap_network", "device", &dmmap_network, &v);
+ dmuci_set_value_by_section(dmmap_network, "section_name", vlan_name);
+ if(strcmp(vlan_method, "2") == 0)
+ *instance = update_instance_icwmpd(dmmap_network, inst, "all_vlan_term_instance");
+ else
+ *instance = update_instance_icwmpd(dmmap_network, inst, "only_tagged_vlan_term_instance");
+
+ return 0;
+}
+
+int delObjEthernetVLANTermination(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ int found = 0;
+ struct uci_section *s = NULL, *ss = NULL, *dmmap_section = NULL;
+ char *vlan_method = NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ dmuci_get_option_value_string("cwmp", "cpe", "vlan_method", &vlan_method);
+ if(is_section_unnamed(section_name(((struct dm_args *)data)->section))) {
+ LIST_HEAD(dup_list);
+ if(strcmp(vlan_method, "2") == 0) {
+ delete_sections_save_next_sections("dmmap_network", "device", "all_vlan_term_instance", section_name((struct uci_section *)data), atoi(instance), &dup_list);
+ update_dmmap_sections(&dup_list, "all_vlan_term_instance", "dmmap_network", "device");
+ }
+ else {
+ delete_sections_save_next_sections("dmmap_network", "device", "only_tagged_vlan_term_instance", section_name((struct uci_section *)data), atoi(instance), &dup_list);
+ update_dmmap_sections(&dup_list, "only_tagged_vlan_term_instance", "dmmap_network", "device");
+ }
+ dmuci_delete_by_section_unnamed(((struct dm_args *)data)->section, NULL, NULL);
+ } else {
+ get_dmmap_section_of_config_section("dmmap_dropbear", "dropbear", section_name(((struct dm_args *)data)->section), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section_unnamed_icwmpd(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(((struct dm_args *)data)->section, NULL, NULL);
+ }
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("network", "device", s) {
+ if (found != 0){
+ get_dmmap_section_of_config_section("dmmap_network", "device", section_name(s), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL){
+ get_dmmap_section_of_config_section("dmmap_network", "device", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ break;
+ }
+ return 0;
+}
+
+/*************************************************************
+ * GET & SET PARAM
+/*************************************************************/
+/*#Device.Ethernet.InterfaceNumberOfEntries!UCI:ports/ethport/*/
+int get_Ethernet_InterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_foreach_sections("ports", "ethport", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+int get_Ethernet_LinkNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ dmmap_synchronizeEthernetLink(ctx, NULL, NULL, NULL);
+ uci_path_foreach_sections(icwmpd, DMMAP, "link", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTerminationNumberOfEntries!UCI:network/device/*/
+int get_Ethernet_VLANTerminationNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ char *type, *vlan_method;
+ int cnt = 0;
+
+ uci_foreach_sections("network", "device", s)
+ {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ dmuci_get_option_value_string("cwmp", "cpe", "vlan_method", &vlan_method);
+ if ((strcmp(vlan_method, "2") != 0 && strcmp(vlan_method, "1") != 0) || (strcmp(vlan_method, "1") == 0 && strcmp(type, "untagged") == 0))
+ continue;
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Enable!UBUS:network.device/status/name,@Name/carrier*/
+int get_EthernetInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ char *ifname;
+
+ if (strstr(((struct eth_port_args *)data)->ifname, wan_ifname)) {
+ ifname = dmstrdup(wan_ifname);
+ } else
+ ifname = dmstrdup(((struct eth_port_args *)data)->ifname);
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 1, "carrier");
+ dmfree(ifname);
+ return 0;
+}
+
+int set_EthernetInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ char *ifname;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (strstr(((struct eth_port_args *)data)->ifname, wan_ifname))
+ ifname = dmstrdup(wan_ifname);
+ else
+ ifname = dmstrdup(((struct eth_port_args *)data)->ifname);
+
+ DMCMD("ethctl", 3, ifname, "phy-power", b ? "up" : "down");
+ dmfree(ifname);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Status!UBUS:network.device/status/name,@Name/carrier*/
+int get_EthernetInterface_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ bool b;
+
+ get_EthernetInterface_Enable(refparam, ctx, data, instance, value);
+ string_to_bool(*value, &b);
+ *value = b ? "Up" : "Down";
+ return 0;
+}
+
+int get_EthernetInterface_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_ports", "ethport", section_name(((struct eth_port_args *)data)->eth_port_sec), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "eth_port_alias", value);
+ if(*value == NULL || strlen(*value)<1)
+ dmuci_get_value_by_section_string(((struct eth_port_args *)data)->eth_port_sec, "name", value);
+ return 0;
+}
+
+int set_EthernetInterface_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ get_dmmap_section_of_config_section("dmmap_ports", "ethport", section_name(((struct eth_port_args *)data)->eth_port_sec), &dmmap_section);
+ dmuci_set_value_by_section(dmmap_section, "eth_port_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Name!UCI:ports/ethport,@i-1/name*/
+int get_EthernetInterface_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct eth_port_args *)data)->eth_port_sec, "name", value);
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.LastChange!UBUS:network.interface/status/interface,@Name/uptime*/
+int get_EthernetInterface_LastChange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ struct uci_section *s = NULL;
+ char *ifname;
+
+ *value ="0";
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "ifname", &ifname);
+ if (strstr(ifname, ((struct eth_port_args *)data)->ifname)) {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(s), String}}, 1, &res);
+ DM_ASSERT(res, *value = "0");
+ *value = dmjson_get_value(res, 1, "uptime");
+ if((*value)[0] == '\0')
+ *value = "0";
+ break;
+ }
+ }
+ return 0;
+}
+
+int get_EthernetInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "";
+ return 0;
+}
+
+int set_EthernetInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_EthernetInterface_Upstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ dmuci_get_option_value_string("network", "lan", "ifname", &ifname);
+ if (strstr(ifname, ((struct eth_port_args *)data)->ifname))
+ *value = "1";
+ else
+ *value = "0";
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.MACAddress!UBUS:network.device/status/name,@Name/macaddr*/
+int get_EthernetInterface_MACAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 1, "macaddr");
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.MaxBitRate!UCI:ports/ethport,@i-1/speed*/
+int get_EthernetInterface_MaxBitRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *pch, *spch, *speed;
+
+ dmuci_get_value_by_section_string(((struct eth_port_args *)data)->eth_port_sec, "speed", &speed);
+ if (speed[0] == '\0' || strcmp(speed, "disabled") == 0 )
+ *value = "0";
+ else {
+ if (strcmp(speed, "auto") == 0)
+ *value = "-1";
+ else {
+ pch = strtok_r(speed, "FHfh", &spch);
+ *value = dmstrdup(pch);
+ }
+ }
+ return 0;
+}
+
+int set_EthernetInterface_MaxBitRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *duplex, *val = "", *p = "";
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcasecmp(value, "0") == 0 ) {
+ dmuci_set_value_by_section(((struct eth_port_args *)data)->eth_port_sec, "speed", "disabled");
+ } else if (strcmp(value, "-1") == 0) {
+ dmuci_set_value_by_section(((struct eth_port_args *)data)->eth_port_sec, "speed", "auto");
+ } else {
+ dmuci_get_value_by_section_string(((struct eth_port_args *)data)->eth_port_sec, "speed", &duplex);
+ if (strcmp(duplex, "auto") == 0 || strcmp(duplex, "disabled") == 0)
+ p = "FDAUTO";
+ else {
+ p = strchr(duplex, 'F') ? strchr(duplex, 'F') : strchr(duplex, 'H');
+ }
+ if (p) dmastrcat(&val, value, p);
+ dmuci_set_value_by_section(((struct eth_port_args *)data)->eth_port_sec, "speed", val);
+ dmfree(val);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.CurrentBitRate!UBUS:network.device/status/name,@Name/speed*/
+int get_EthernetInterface_CurrentBitRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ char *speed, *pch;
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "0");
+ speed = dmjson_get_value(res, 1, "speed");
+ if(speed[0] != '\0') {
+ pch = strtok(speed, "FHfh");
+ *value = dmstrdup(pch);
+ } else
+ *value = "0";
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.DuplexMode!UCI:ports/status/ethport,@i-1/speed*/
+int get_EthernetInterface_DuplexMode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct eth_port_args *)data)->eth_port_sec, "speed", value);
+ if (*value[0] == '\0') {
+ *value = "";
+ } else if (strcmp(*value, "auto") == 0) {
+ *value = "Auto";
+ } else {
+ if (strchr(*value, 'F'))
+ *value = "Full";
+ else if (strchr(*value, 'H'))
+ *value = "Half";
+ else
+ *value = "";
+ }
+ return 0;
+}
+
+int set_EthernetInterface_DuplexMode(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *m, *spch, *rate, *val = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcasecmp(value, "auto") == 0) {
+ dmuci_set_value_by_section(((struct eth_port_args *)data)->eth_port_sec, "speed", "auto");
+ return 0;
+ }
+ dmuci_get_value_by_section_string(((struct eth_port_args *)data)->eth_port_sec, "speed", &m);
+ m = dmstrdup(m);
+ rate = m;
+ if (strcmp(rate, "auto") == 0)
+ rate = "100";
+ else {
+ strtok_r(rate, "FHfh", &spch);
+ }
+ if (strcasecmp(value, "full") == 0)
+ dmastrcat(&val, rate, "FD");
+ else if (strcasecmp(value, "half") == 0)
+ dmastrcat(&val, rate, "HD");
+ else {
+ dmfree(m);
+ return 0;
+ }
+ dmuci_set_value_by_section(((struct eth_port_args *)data)->eth_port_sec, "speed", val);
+ dmfree(m);
+ dmfree(val);
+ return 0;
+ }
+ return 0;
+}
+
+int get_EthernetInterface_EEECapability(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ return 0;
+}
+
+inline int get_ubus_ethernet_interface_stats(json_object *res, char **value, char *stat_mod, void *data)
+{
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "0");
+ *value = dmjson_get_value(res, 2, "statistics", stat_mod);
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Stats.BytesSent!UBUS:network.device/status/name,@Name/statistics.tx_bytes*/
+int get_EthernetInterfaceStats_BytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_interface_stats(res, value, "tx_bytes", data);
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Stats.BytesReceived!UBUS:network.device/status/name,@Name/statistics.rx_bytes*/
+int get_EthernetInterfaceStats_BytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 2, "statistics", "rx_bytes");
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Stats.PacketsSent!UBUS:network.device/status/name,@Name/statistics.tx_packets*/
+int get_EthernetInterfaceStats_PacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 2, "statistics", "tx_packets");
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Stats.PacketsReceived!UBUS:network.device/status/name,@Name/statistics.rx_packets*/
+int get_EthernetInterfaceStats_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 2, "statistics", "rx_packets");
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Stats.ErrorsSent!UBUS:network.device/status/name,@Name/statistics.tx_errors*/
+int get_EthernetInterfaceStats_ErrorsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 2, "statistics", "tx_errors");
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Stats.ErrorsReceived!UBUS:network.device/status/name,@Name/statistics.rx_errors*/
+int get_EthernetInterfaceStats_ErrorsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 2, "statistics", "rx_errors");
+ return 0;
+}
+
+int get_EthernetInterfaceStats_UnicastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(((struct eth_port_args *)data)->ifname, "TX", "unicast"));
+ return 0;
+}
+
+int get_EthernetInterfaceStats_UnicastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(((struct eth_port_args *)data)->ifname, "RX", "unicast"));
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Stats.DiscardPacketsSent!UBUS:network.device/status/name,@Name/statistics.tx_dropped*/
+int get_EthernetInterfaceStats_DiscardPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 2, "statistics", "tx_dropped");
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Stats.DiscardPacketsReceived!UBUS:network.device/status/name,@Name/statistics.rx_dropped*/
+int get_EthernetInterfaceStats_DiscardPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 2, "statistics", "rx_dropped");
+ return 0;
+}
+
+int get_EthernetInterfaceStats_MulticastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(((struct eth_port_args *)data)->ifname, "TX", "multicast"));
+ return 0;
+}
+
+int get_EthernetInterfaceStats_MulticastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(((struct eth_port_args *)data)->ifname, "RX", "multicast"));
+ return 0;
+}
+
+int get_EthernetInterfaceStats_BroadcastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(((struct eth_port_args *)data)->ifname, "TX", "broadcast"));
+ return 0;
+}
+
+int get_EthernetInterfaceStats_BroadcastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(((struct eth_port_args *)data)->ifname, "RX", "broadcast"));
+ return 0;
+}
+
+/*#Device.Ethernet.Interface.{i}.Stats.UnknownProtoPacketsReceived!UBUS:network.device/status/name,@Name/statistics.rx_over_errors*/
+int get_EthernetInterfaceStats_UnknownProtoPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ((struct eth_port_args *)data)->ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 2, "statistics", "rx_over_errors");
+ return 0;
+}
+
+int get_EthernetLink_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "true";
+ return 0;
+}
+
+int set_EthernetLink_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_EthernetLink_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Up";
+ return 0;
+}
+
+int get_EthernetLink_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "link_alias", value);
+ return 0;
+}
+
+int set_EthernetLink_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section(((struct dm_args *)data)->section, "link_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_EthernetLink_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = dmstrdup(section_name(((struct dm_args *)data)->section));
+ return 0;
+}
+
+int get_EthernetLink_LastChange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ char *interface;
+
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "section_name", &interface);
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res);
+ DM_ASSERT(res, *value = "0");
+ *value = dmjson_get_value(res, 1, "uptime");
+ if((*value)[0] == '\0')
+ *value = "0";
+ return 0;
+}
+
+int get_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ char *link_mac, *type, *ifname, *mac, *br_inst, *mg, *wanifname, *wanlinker, linker[64] = "";
+ struct uci_section *dmmap_section, *port;
+
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "mac", &link_mac);
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if (strcmp(type, "alias") == 0 || strcmp(section_name(s), "loopback") == 0)
+ continue;
+
+ dmuci_get_value_by_section_string(s, "ifname", &ifname);
+ if (*ifname == '\0' || *ifname == '@')
+ continue;
+
+ mac = get_macaddr(section_name(s));
+ if (mac[0] == '\0' || strcasecmp(mac, link_mac) != 0)
+ continue;
+
+ if (strcmp(type, "bridge") == 0) {
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(s), &dmmap_section);
+ if (dmmap_section != NULL) {
+ dmuci_get_value_by_section_string(dmmap_section, "bridge_instance", &br_inst);
+ uci_path_foreach_option_eq(icwmpd, "dmmap_bridge_port", "bridge_port", "bridge_key", br_inst, port) {
+ dmuci_get_value_by_section_string(port, "mg_port", &mg);
+ if (strcmp(mg, "true") == 0)
+ sprintf(linker, "%s+", section_name(port));
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
+ if (*value == NULL)
+ *value = "";
+ }
+ }
+ }
+ else {
+ dmuci_get_option_value_string("ports", "WAN", "ifname", &wanifname);
+ /* for upstream interface, set the lowerlayer to wan port of Ethernet.Interface */
+ if(strstr(ifname, wanifname)) {
+ dmasprintf(&wanlinker, "%s.1", wanifname);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), wanlinker, value);
+ dmfree(wanlinker);
+ if (*value == NULL)
+ *value = "";
+ }
+ }
+ }
+ return 0;
+}
+
+int set_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_EthernetLink_MACAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "mac", value);
+ return 0;
+}
+
+inline int get_ubus_ethernet_link_stats(json_object *res, char **value, char *stat_mod, void *data)
+{
+ char *device;
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "device", &device);
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", device, String}}, 1, &res);
+ DM_ASSERT(res, *value = "0");
+ *value = dmjson_get_value(res, 2, "statistics", stat_mod);
+ return 0;
+}
+
+int get_EthernetLinkStats_BytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_link_stats(res, value, "tx_bytes", data);
+ return 0;
+}
+
+int get_EthernetLinkStats_BytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_link_stats(res, value, "rx_bytes", data);
+ return 0;
+}
+
+int get_EthernetLinkStats_PacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_link_stats(res, value, "tx_packets", data);
+ return 0;
+}
+
+int get_EthernetLinkStats_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_link_stats(res, value, "rx_packets", data);
+ return 0;
+}
+
+int get_EthernetLinkStats_ErrorsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_link_stats(res, value, "tx_errors", data);
+ return 0;
+}
+
+int get_EthernetLinkStats_ErrorsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_link_stats(res, value, "rx_errors", data);
+ return 0;
+}
+
+int get_EthernetLinkStats_UnicastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *device;
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "device", &device);
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "TX", "unicast"));
+ return 0;
+}
+
+int get_EthernetLinkStats_UnicastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *device;
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "device", &device);
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "RX", "unicast"));
+ return 0;
+}
+
+int get_EthernetLinkStats_DiscardPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_link_stats(res, value, "tx_dropped", data);
+ return 0;
+}
+
+int get_EthernetLinkStats_DiscardPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_link_stats(res, value, "rx_dropped", data);
+ return 0;
+}
+
+int get_EthernetLinkStats_MulticastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *device;
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "device", &device);
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "TX", "multicast"));
+ return 0;
+}
+
+int get_EthernetLinkStats_MulticastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *device;
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "device", &device);
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "RX", "multicast"));
+ return 0;
+}
+
+int get_EthernetLinkStats_BroadcastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *device;
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "device", &device);
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "TX", "broadcast"));
+ return 0;
+}
+
+int get_EthernetLinkStats_BroadcastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *device;
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "device", &device);
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "RX", "broadcast"));
+ return 0;
+}
+
+int get_EthernetLinkStats_UnknownProtoPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_link_stats(res, value, "rx_over_errors", data);
+ return 0;
+}
+
+int get_EthernetVLANTermination_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "true";
+ return 0;
+}
+
+int set_EthernetVLANTermination_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_EthernetVLANTermination_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Up";
+ return 0;
+}
+
+int get_EthernetVLANTermination_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+ char *vlan_method= NULL;
+
+ get_dmmap_section_of_config_section("dmmap_network", "device", section_name(((struct dm_args *)data)->section), &dmmap_section);
+ dmuci_get_option_value_string("cwmp", "cpe", "vlan_method", &vlan_method);
+ if(strcmp(vlan_method, "2") == 0)
+ dmuci_get_value_by_section_string(dmmap_section, "all_vlan_term_alias", value);
+ else
+ dmuci_get_value_by_section_string(dmmap_section, "vlan_term_alias", value);
+
+ return 0;
+}
+
+int set_EthernetVLANTermination_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section;
+ char *vlan_method= NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ get_dmmap_section_of_config_section("dmmap_network", "device", section_name(((struct dm_args *)data)->section), &dmmap_section);
+ dmuci_get_option_value_string("cwmp", "cpe", "vlan_method", &vlan_method);
+ if(strcmp(vlan_method, "2") == 0)
+ dmuci_set_value_by_section(dmmap_section, "all_vlan_term_alias", value);
+ else
+ dmuci_set_value_by_section(dmmap_section, "vlan_term_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_EthernetVLANTermination_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = dmstrdup(section_name(((struct dm_args *)data)->section));
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.LastChange!UBUS:network.interface/status/interface,@Name/uptime*/
+int get_EthernetVLANTermination_LastChange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ struct uci_section *s = NULL;
+ char *ifname, *devifname;
+
+ *value ="0";
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", &devifname);
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "ifname", &ifname);
+ if (strstr(ifname, devifname)) {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(s), String}}, 1, &res);
+ DM_ASSERT(res, *value = "0");
+ *value = dmjson_get_value(res, 1, "uptime");
+ if((*value)[0] == '\0')
+ *value = "0";
+ break;
+ }
+ }
+ return 0;
+}
+
+int get_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *pch, *spch, *devifname, *ifname, *mac;
+ struct uci_section *section;
+
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", &devifname);
+ uci_foreach_sections("network", "interface", section) {
+ dmuci_get_value_by_section_string(section, "ifname", &ifname);
+ for (pch = strtok_r(ifname, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) {
+ if(strcmp(pch, devifname) == 0) {
+ mac = get_macaddr(section_name(section));
+ if (mac[0] != '\0') {
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), mac, value);
+ if (*value == NULL)
+ *value = "";
+ break;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int set_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *iface_list, *linker = NULL, *newvalue = NULL, *vlan_name = NULL;
+ struct uci_section *s;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (value[strlen(value)-1]!='.') {
+ dmasprintf(&newvalue, "%s.", value);
+ adm_entry_get_linker_value(ctx, newvalue, &linker);
+ } else
+ adm_entry_get_linker_value(ctx, value, &linker);
+
+ if (linker == NULL || *linker == '\0')
+ return -1;
+
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", &vlan_name);
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "ifname", &iface_list);
+ if(strcmp(section_name(s), linker) != 0 && is_elt_exit_in_str_list(iface_list, vlan_name)) {
+ remove_elt_from_str_list(&iface_list, vlan_name);
+ dmuci_set_value_by_section(s, "ifname", iface_list);
+ } else if (strcmp(section_name(s), linker) == 0 && !is_elt_exit_in_str_list(iface_list, vlan_name)) {
+ add_elt_to_str_list(&iface_list, vlan_name);
+ dmuci_set_value_by_section(s, "ifname", iface_list);
+ }
+ }
+ }
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.LastChange!UCI:network/device,@i-1/vid*/
+int get_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "vid", value);
+ return 0;
+}
+
+int set_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *ifname, *name, *vid, *curr_ifname;
+ struct uci_section *s;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET: {
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
+ dmasprintf(&name, "%s.%s", ifname, value);
+ dmuci_set_value_by_section(((struct dm_args *)data)->section, "name", name);
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "vid", &vid);
+ dmuci_set_value_by_section(((struct dm_args *)data)->section, "vid", value);
+ dmasprintf(&curr_ifname, "%s.%s", ifname, vid);
+ uci_foreach_option_eq("network", "interface", "ifname", curr_ifname, s) {
+ dmuci_set_value_by_section(s, "ifname", name);
+ }
+ dmfree(name);
+ dmfree(curr_ifname);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.TPID!UCI:network/device,@i-1/type*/
+int get_EthernetVLANTermination_TPID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *type;
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "type", &type);
+ if (strcmp(type, "8021q") == 0 || strcmp(type, "untagged") == 0)
+ *value = "33024";
+ else if (strcmp(type, "8021ad") == 0)
+ *value = "34984";
+ else
+ return -1;
+ return 0;
+}
+
+int set_EthernetVLANTermination_TPID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value, "33024") == 0)
+ dmuci_set_value_by_section(((struct dm_args *)data)->section, "type", "8021q");
+ else if (strcmp(value, "34984") == 0)
+ dmuci_set_value_by_section(((struct dm_args *)data)->section, "type", "8021ad");
+ else
+ return -1;
+ return 0;
+ }
+ return 0;
+}
+
+inline int get_ubus_ethernet_vlan_termination_stats(json_object *res, char **value, char *stat_mod, void *data)
+{
+ char *ifname;
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", ifname, String}}, 1, &res);
+ DM_ASSERT(res, *value = "0");
+ *value = dmjson_get_value(res, 2, "statistics", stat_mod);
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.Stats.BytesSent!UBUS:network.device/status/name,@Name/statistics.tx_bytes*/
+int get_EthernetVLANTerminationStats_BytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_vlan_termination_stats(res, value, "tx_bytes", data);
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.Stats.BytesReceived!UBUS:network.device/status/name,@Name/statistics.rx_bytes*/
+int get_EthernetVLANTerminationStats_BytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_vlan_termination_stats(res, value, "rx_bytes", data);
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.Stats.PacketsSent!UBUS:network.device/status/name,@Name/statistics.tx_packets*/
+int get_EthernetVLANTerminationStats_PacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_vlan_termination_stats(res, value, "tx_packets", data);
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.Stats.PacketsReceived!UBUS:network.device/status/name,@Name/statistics.rx_packets*/
+int get_EthernetVLANTerminationStats_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_vlan_termination_stats(res, value, "rx_packets", data);
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.Stats.ErrorsSent!UBUS:network.device/status/name,@Name/statistics.tx_errors*/
+int get_EthernetVLANTerminationStats_ErrorsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_vlan_termination_stats(res, value, "tx_errors", data);
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.Stats.ErrorsReceived!UBUS:network.device/status/name,@Name/statistics.rx_errors*/
+int get_EthernetVLANTerminationStats_ErrorsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_vlan_termination_stats(res, value, "rx_errors", data);
+ return 0;
+}
+
+int get_EthernetVLANTerminationStats_UnicastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
+ if(!strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "TX", "unicast"));
+ return 0;
+}
+
+int get_EthernetVLANTerminationStats_UnicastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
+ if(!strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "RX", "unicast"));
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.Stats.DiscardPacketsSent!UBUS:network.device/status/name,@Name/statistics.tx_dropped*/
+int get_EthernetVLANTerminationStats_DiscardPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_vlan_termination_stats(res, value, "tx_dropped", data);
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.Stats.DiscardPacketsReceived!UBUS:network.device/status/name,@Name/statistics.rx_dropped*/
+int get_EthernetVLANTerminationStats_DiscardPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_vlan_termination_stats(res, value, "rx_dropped", data);
+ return 0;
+}
+
+int get_EthernetVLANTerminationStats_MulticastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
+ if(!strstr(ifname, "atm") && !strstr(ifname, "ptm")) {
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "TX", "multicast"));
+ }
+ return 0;
+}
+
+int get_EthernetVLANTerminationStats_MulticastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
+ if(!strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "RX", "multicast"));
+ return 0;
+}
+
+int get_EthernetVLANTerminationStats_BroadcastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
+ if(!strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "TX", "broadcast"));
+ return 0;
+}
+
+int get_EthernetVLANTerminationStats_BroadcastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ifname;
+ *value = "0";
+ dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
+ if(!strstr(ifname, "atm") && !strstr(ifname, "ptm"))
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(ifname, "RX", "broadcast"));
+ return 0;
+}
+
+/*#Device.Ethernet.VLANTermination.{i}.Stats.UnknownProtoPacketsReceived!UBUS:network.device/status/name,@Name/statistics.rx_over_errors*/
+int get_EthernetVLANTerminationStats_UnknownProtoPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ get_ubus_ethernet_vlan_termination_stats(res, value, "rx_over_errors", data);
+ return 0;
+}
diff --git a/dmtree/tr181/ethernet.h b/dmtree/tr181/ethernet.h
new file mode 100644
index 00000000..ed00af18
--- /dev/null
+++ b/dmtree/tr181/ethernet.h
@@ -0,0 +1,139 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB
+ * Author: Anis Ellouze
+ * Author: Amin Ben Ramdhane
+ *
+ */
+
+#ifndef __ETHERNET_H
+#define __ETHERNET_H
+
+struct eth_port_args
+{
+ struct uci_section *eth_port_sec;
+ char *ifname;
+};
+
+extern DMOBJ tEthernetObj[];
+extern DMLEAF tEthernetParams[];
+extern DMOBJ tEthernetInterfaceObj[];
+extern DMLEAF tEthernetInterfaceParams[];
+extern DMLEAF tEthernetInterfaceStatsParams[];
+extern DMOBJ tEthernetLinkObj[];
+extern DMLEAF tEthernetLinkParams[];
+extern DMLEAF tEthernetLinkStatsParams[];
+extern DMOBJ tEthernetVLANTerminationObj[];
+extern DMLEAF tEthernetVLANTerminationParams[];
+extern DMLEAF tEthernetVLANTerminationStatsParams[];
+
+int browseEthernetInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseEthernetLinkInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseEthernetVLANTerminationInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int addObjEthernetLink(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjEthernetLink(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int addObjEthernetVLANTermination(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjEthernetVLANTermination(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+
+int get_linker_interface(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+int get_linker_link(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+int get_linker_vlan_term(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+
+int get_Ethernet_InterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_Ethernet_LinkNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_Ethernet_VLANTerminationNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_EthernetInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetInterface_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterface_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetInterface_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetInterface_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterface_LastChange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetInterface_Upstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterface_MACAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterface_MaxBitRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetInterface_MaxBitRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetInterface_CurrentBitRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterface_DuplexMode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetInterface_DuplexMode(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetInterface_EEECapability(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_BytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_BytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_PacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_ErrorsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_ErrorsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_UnicastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_UnicastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_DiscardPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_DiscardPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_MulticastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_MulticastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_BroadcastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_BroadcastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetInterfaceStats_UnknownProtoPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_EthernetLink_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetLink_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetLink_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLink_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetLink_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetLink_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLink_LastChange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetLink_MACAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_BytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_BytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_PacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_ErrorsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_ErrorsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_UnicastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_UnicastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_DiscardPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_DiscardPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_MulticastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_MulticastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_BroadcastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_BroadcastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetLinkStats_UnknownProtoPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_EthernetVLANTermination_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetVLANTermination_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetVLANTermination_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTermination_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetVLANTermination_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetVLANTermination_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTermination_LastChange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetVLANTermination_TPID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_EthernetVLANTermination_TPID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_EthernetVLANTerminationStats_BytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_BytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_PacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_ErrorsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_ErrorsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_UnicastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_UnicastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_DiscardPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_DiscardPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_MulticastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_MulticastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_BroadcastPacketsSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_BroadcastPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_EthernetVLANTerminationStats_UnknownProtoPacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+#endif //__ETHERNET_H
diff --git a/dmtree/tr181/firewall.c b/dmtree/tr181/firewall.c
new file mode 100644
index 00000000..a7de6a97
--- /dev/null
+++ b/dmtree/tr181/firewall.c
@@ -0,0 +1,1329 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB
+ *
+ * Author: Omar Kallel
+ */
+
+#include "dmcwmp.h"
+#include "firewall.h"
+#include "dmcommon.h"
+#include "dmentry.h"
+
+/* *** Device.Firewall. *** */
+DMOBJ tFirewallObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Level", &DMREAD, NULL, NULL, NULL, browseLevelInst, NULL, NULL, NULL, tFirewallLevelParams, NULL, BBFDM_BOTH},
+{"Chain", &DMREAD, NULL, NULL, NULL, browseChainInst, NULL, NULL, tFirewallChainObj, tFirewallChainParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tFirewallParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_firewall_enable, set_firewall_enable, NULL, NULL, BBFDM_BOTH},
+{"Config", &DMWRITE, DMT_STRING, get_firewall_config, set_firewall_config, NULL, NULL, BBFDM_BOTH},
+{"AdvancedLevel", &DMWRITE, DMT_STRING, get_firewall_advanced_level, set_firewall_advanced_level, NULL, NULL, BBFDM_BOTH},
+{"LevelNumberOfEntries", &DMREAD, DMT_UNINT, get_firewall_level_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"ChainNumberOfEntries", &DMREAD, DMT_UNINT, get_firewall_chain_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Firewall.Level.{i}. *** */
+DMLEAF tFirewallLevelParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Name", &DMWRITE, DMT_STRING, get_level_name, set_level_name, NULL, NULL, BBFDM_BOTH},
+{"Description", &DMWRITE, DMT_STRING, get_level_description, set_level_description, NULL, NULL, BBFDM_BOTH},
+{"Chain", &DMREAD, DMT_STRING, get_level_chain, NULL, NULL, NULL, BBFDM_BOTH},
+{"PortMappingEnabled", &DMWRITE, DMT_BOOL, get_level_port_mapping_enabled, set_level_port_mapping_enabled, NULL, NULL, BBFDM_BOTH},
+{"DefaultLogPolicy", &DMWRITE, DMT_BOOL, get_level_default_log_policy, set_level_default_log_policy, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Firewall.Chain.{i}. *** */
+DMOBJ tFirewallChainObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Rule", &DMWRITE, add_firewall_rule, delete_firewall_rule, NULL, browseRuleInst, NULL, NULL, tFirewallChainRuleObj, tFirewallChainRuleParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tFirewallChainParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_chain_enable, set_chain_enable, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMWRITE, DMT_STRING, get_chain_name, set_chain_name, NULL, NULL, BBFDM_BOTH},
+{"Creator", &DMREAD, DMT_STRING, get_chain_creator, NULL, NULL, NULL, BBFDM_BOTH},
+{"RuleNumberOfEntries", &DMREAD, DMT_UNINT, get_chain_rule_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Firewall.Chain.{i}.Rule.{i}. *** */
+DMOBJ tFirewallChainRuleObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{CUSTOM_PREFIX"TimeSpan", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tTimeSpanParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tFirewallChainRuleParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_rule_enable, set_rule_enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_rule_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Order", &DMWRITE, DMT_UNINT, get_rule_order, set_rule_order, NULL, NULL, BBFDM_BOTH},
+{"Description", &DMWRITE, DMT_STRING, get_rule_description, set_rule_description, NULL, NULL, BBFDM_BOTH},
+{"Target", &DMWRITE, DMT_STRING, get_rule_target, set_rule_target, NULL, NULL, BBFDM_BOTH},
+{"TargetChain", &DMWRITE, DMT_STRING, get_rule_target_chain, set_rule_target_chain, NULL, NULL, BBFDM_BOTH},
+{"SourceInterface", &DMWRITE, DMT_STRING, get_rule_source_interface, set_rule_source_interface, NULL, NULL, BBFDM_BOTH},
+{"DestInterface", &DMWRITE, DMT_STRING, get_rule_dest_interface, set_rule_dest_interface, NULL, NULL, BBFDM_BOTH},
+{"IPVersion", &DMWRITE, DMT_INT, get_rule_i_p_version, set_rule_i_p_version, NULL, NULL, BBFDM_BOTH},
+{"DestIp", &DMWRITE, DMT_STRING, get_rule_dest_ip, set_rule_dest_ip, NULL, NULL, BBFDM_BOTH},
+{"DestMask", &DMWRITE, DMT_STRING, get_rule_dest_mask, set_rule_dest_mask, NULL, NULL, BBFDM_BOTH},
+{"SourceIp", &DMWRITE, DMT_STRING, get_rule_source_ip, set_rule_source_ip, NULL, NULL, BBFDM_BOTH},
+{"SourceMask", &DMWRITE, DMT_STRING, get_rule_source_mask, set_rule_source_mask, NULL, NULL, BBFDM_BOTH},
+{"Protocol", &DMWRITE, DMT_INT, get_rule_protocol, set_rule_protocol, NULL, NULL, BBFDM_BOTH},
+{"DestPort", &DMWRITE, DMT_INT, get_rule_dest_port, set_rule_dest_port, NULL, NULL, BBFDM_BOTH},
+{"DestPortRangeMax", &DMWRITE, DMT_INT, get_rule_dest_port_range_max, set_rule_dest_port_range_max, NULL, NULL, BBFDM_BOTH},
+{"SourcePort", &DMWRITE, DMT_INT, get_rule_source_port, set_rule_source_port, NULL, NULL, BBFDM_BOTH},
+{"SourcePortRangeMax", &DMWRITE, DMT_INT, get_rule_source_port_range_max, set_rule_source_port_range_max, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"IcmpType", &DMWRITE, DMT_STRING, get_rule_icmp_type, set_rule_icmp_type, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"SourceMac", &DMWRITE, DMT_STRING, get_rule_source_mac, set_rule_source_mac, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tTimeSpanParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"SupportedDays", &DMWRITE, DMT_STRING, get_time_span_supported_days, set_time_span_supported_days, NULL, NULL, BBFDM_BOTH},
+{"Days", &DMWRITE, DMT_STRING, get_time_span_days, set_time_span_days, NULL, NULL, BBFDM_BOTH},
+{"StartTime", &DMWRITE, DMT_STRING, get_time_span_start_time, set_time_span_start_time, NULL, NULL, BBFDM_BOTH},
+{"StopTime", &DMWRITE, DMT_STRING, get_time_span_stop_time, set_time_span_stop_time, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/***************************** Browse Functions ***********************************/
+int browseLevelInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s;
+ char *v, *instance, *instnbr = NULL;
+
+ check_create_dmmap_package("dmmap_firewall");
+ s = is_dmmap_section_exist("dmmap_firewall", "level");
+ if(!s)
+ dmuci_add_section_icwmpd("dmmap_firewall", "level", &s, &v);
+ instance = handle_update_instance(1, dmctx, &instnbr, update_instance_alias, 3, s, "firewall_level_instance", "firewall_level_alias");
+
+ DM_LINK_INST_OBJ(dmctx, parent_node, s, "1");
+ return 0;
+}
+
+int browseChainInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s;
+ char *v, *instance, *instnbr = NULL;
+
+ check_create_dmmap_package("dmmap_firewall");
+ s = is_dmmap_section_exist("dmmap_firewall", "chain");
+ if(!s)
+ dmuci_add_section_icwmpd("dmmap_firewall", "chain", &s, &v);
+ instance = handle_update_instance(1, dmctx, &instnbr, update_instance_alias, 3, s, "firewall_chain_instance", "firewall_chain_alias");
+
+ DM_LINK_INST_OBJ(dmctx, parent_node, s, "1");
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.!UCI:firewall/rule/dmmap_firewall*/
+int browseRuleInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *instance, *instnbr = NULL;
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap("firewall", "rule", "dmmap_firewall", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ instance = handle_update_instance(1, dmctx, &instnbr, update_instance_alias, 3, p->dmmap_section, "firewall_chain_rule_instance", "firewall_chain_rule_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, instance) == DM_STOP)
+ return 0;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
+
+int add_firewall_rule(char *refparam, struct dmctx *ctx, void *data, char **instance){
+ struct uci_section *s, *dmmap_firewall_rule;
+ char *last_inst= NULL, *sect_name= NULL, *rule_name, *v;
+ char ib[8];
+ last_inst= get_last_instance_icwmpd("dmmap_firewall", "rule", "firewall_chain_rule_instance");
+ if (last_inst)
+ sprintf(ib, "%s", last_inst);
+ else
+ sprintf(ib, "%s", "1");
+ dmasprintf(&rule_name, "Firewall rule %d", atoi(ib)+1);
+
+ dmuci_add_section("firewall", "rule", &s, §_name);
+ dmuci_set_value_by_section(s, "name", rule_name);
+ dmuci_set_value_by_section(s, "dest", "lan");
+ dmuci_set_value_by_section(s, "src", "wan");
+ dmuci_set_value_by_section(s, "target", "ACCEPT");
+
+ dmuci_add_section_icwmpd("dmmap_firewall", "rule", &dmmap_firewall_rule, &v);
+ dmuci_set_value_by_section(dmmap_firewall_rule, "section_name", sect_name);
+ *instance = update_instance_icwmpd(dmmap_firewall_rule, last_inst, "firewall_chain_rule_instance");
+ return 0;
+}
+
+int delete_firewall_rule(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action){
+ struct uci_section *s = NULL;
+ struct uci_section *ss = NULL;
+ struct uci_section *dmmap_section;
+ int found = 0;
+
+ switch (del_action) {
+ case DEL_INST:
+ if(is_section_unnamed(section_name((struct uci_section *)data))){
+ LIST_HEAD(dup_list);
+ delete_sections_save_next_sections("dmmap_firewall", "rule", "firewall_chain_rule_instance", section_name((struct uci_section *)data), atoi(instance), &dup_list);
+ update_dmmap_sections(&dup_list, "firewall_chain_rule_instance", "dmmap_firewall", "rule");
+ dmuci_delete_by_section_unnamed((struct uci_section *)data, NULL, NULL);
+ } else {
+ get_dmmap_section_of_config_section("dmmap_firewall", "rule", section_name((struct uci_section *)data), &dmmap_section);
+ dmuci_delete_by_section_unnamed_icwmpd(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section((struct uci_section *)data, NULL, NULL);
+ }
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("firewall", "rule", s) {
+ if (found != 0){
+ get_dmmap_section_of_config_section("dmmap_firewall", "rule", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL){
+ get_dmmap_section_of_config_section("dmmap_firewall", "rule", section_name(ss), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ }
+ return 0;
+}
+
+/***************************************** Set/Get Parameter functions ***********************/
+int get_firewall_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *path = "/etc/rc.d/*firewall";
+ if (check_file(path))
+ *value = "1";
+ else
+ *value = "0";
+ return 0;
+}
+
+int get_firewall_config(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Advanced";
+ return 0;
+}
+
+int get_firewall_advanced_level(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Device.Firewall.Level.1.";
+ return 0;
+}
+
+int get_firewall_level_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value="1";
+ return 0;
+}
+
+int get_firewall_chain_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value="1";
+ return 0;
+}
+
+int get_level_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section* levels=(struct uci_section *)data;
+ dmuci_get_value_by_section_string(levels, "name", value);
+ return 0;
+}
+
+int get_level_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section* levels=(struct uci_section *)data;
+ dmuci_get_value_by_section_string(levels, "description", value);
+ return 0;
+}
+
+int get_level_chain(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Device.Firewall.Chain.1.";
+ return 0;
+}
+
+int get_level_port_mapping_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ char *v;
+
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_get_value_by_section_string(s, "masq", &v);
+ if (*v == '1') {
+ *value = "1";
+ return 0;
+ }
+ }
+ *value = "0";
+ return 0;
+}
+
+int get_level_default_log_policy(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ char *v;
+
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_get_value_by_section_string(s, "log", &v);
+ if (*v == '1') {
+ *value = "1";
+ return 0;
+ }
+ }
+ *value = "0";
+ return 0;
+}
+
+int get_chain_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int get_chain_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section* chains=(struct uci_section *)data;
+ dmuci_get_value_by_section_string(chains, "name", value);
+ return 0;
+}
+
+int get_chain_creator(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Defaults";
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.RuleNumberOfEntries!UCI:firewall/rule/*/
+int get_chain_rule_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_foreach_sections("firewall", "rule", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Enable!UCI:firewall/rule,@i-1/enabled*/
+int get_rule_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enabled", &v);
+ *value = (*v == 'n' || *v == '0' ) ? "0" : "1";
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Status!UCI:firewall/rule,@i-1/enabled*/
+int get_rule_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enabled", &v);
+ *value = (*v == 'n' || *v == '0') ? "Disabled" : "Enabled";
+ return 0;
+}
+
+int get_rule_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dms;
+ get_dmmap_section_of_config_section("dmmap_firewall", "rule", section_name((struct uci_section *)data), &dms);
+ dmuci_get_value_by_section_string(dms, "firewall_chain_rule_instance", value);
+ return 0;
+}
+
+int get_rule_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dms;
+ get_dmmap_section_of_config_section("dmmap_firewall", "rule", section_name((struct uci_section *)data), &dms);
+ dmuci_get_value_by_section_string(dms, "description", value);
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Target!UCI:firewall/rule,@i-1/target*/
+int get_rule_target(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+ *value = "";
+ dmuci_get_value_by_section_string((struct uci_section *)data, "target", &v);
+ if (strcasecmp(v, "Accept") == 0) {
+ *value = "Accept";
+ }
+ else if (strcasecmp(v, "Reject") == 0) {
+ *value = "Reject";
+ }
+ else if (strcasecmp(v, "Drop") == 0){
+ *value = "Drop";
+ }
+ else if (strcasecmp(v, "MARK") == 0){
+ *value = "Return";
+ }
+ else {
+ *value = v;
+ }
+ return 0;
+}
+
+int get_rule_target_chain(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ //TODO
+ return 0;
+}
+
+int get_rule_source_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_list *v = NULL, *v1= NULL;
+ struct uci_element *e;
+ char *zone, *ifaceobj, buf[256] = "", *val;
+ struct uci_section *s = NULL;
+ char linker[64] = "", *vallink;
+
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src", &zone);
+ if(zone == NULL || strlen(zone)==0)
+ return 0;
+
+ if (strcmp(zone, "*") == 0) {
+ v = dmcalloc(1, sizeof(struct uci_list));
+ uci_list_init(v);
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_get_value_by_section_list(s, "network", &v1);
+ uci_add_list_to_list(v1, v);
+ }
+ } else {
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_get_value_by_section_string(s, "name", &val);
+ if (strcmp(val, zone) == 0) {
+ dmuci_get_value_by_section_list(s, "network", &v);
+ break;
+ }
+ }
+ }
+
+ if (v != NULL) {
+ uci_foreach_element(v, e) {
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), e->name, &vallink);
+ if (*vallink == '\0')
+ continue;
+ if (*buf != '\0')
+ strcat(buf, ",");
+ strcat(buf, vallink);
+ }
+ }
+ else {
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), zone, &vallink);
+ strcpy(buf, vallink);
+ }
+
+ *value = dmstrdup(buf);
+ return 0;
+}
+
+int get_rule_dest_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_list *v = NULL;
+ struct uci_element *e;
+ char *zone, *ifaceobj, buf[256] = "", *val;
+ struct uci_section *s = NULL;
+
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest", &zone);
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_get_value_by_section_string(s, "name", &val);
+ if (strcmp(val, zone) == 0) {
+ dmuci_get_value_by_section_list(s, "network", &v);
+ break;
+ }
+ }
+ if (v != NULL) {
+ uci_foreach_element(v, e) {
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), e->name, &ifaceobj);
+ if (*ifaceobj == '\0')
+ continue;
+ if (*buf != '\0')
+ strcat(buf, ",");
+ strcat(buf, ifaceobj);
+ }
+ }
+
+ *value = dmstrdup(buf);
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.IPVersion!UCI:firewall/rule,@i-1/family*/
+int get_rule_i_p_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ipversion;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "family", &ipversion);
+ if (strcasecmp(ipversion, "ipv4") == 0) {
+ *value = "4";
+ }
+ else if (strcasecmp(ipversion, "ipv6") == 0) {
+ *value = "6";
+ }
+ else {
+ *value = "-1";
+ }
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.DestIp!UCI:firewall/rule,@i-1/dest_ip*/
+int get_rule_dest_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char buf[64];
+ char *pch;
+ char *destip;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest_ip", &destip);
+ strcpy(buf, destip);
+ pch = strchr(buf, '/');
+ if (pch)
+ *pch = '\0';
+ *value = dmstrdup(buf);
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.DestMask!UCI:firewall/rule,@i-1/dest_ip*/
+int get_rule_dest_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *pch;
+ *value = "";
+
+ char *destip;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest_ip", &destip);
+ if (*destip == '\0')
+ return 0;
+
+ pch = strchr(destip, '/');
+ if (pch) {
+ *value = pch+1;
+ }
+ else {
+ *value = "";
+ }
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.SourceIp!UCI:firewall/rule,@i-1/src_ip*/
+int get_rule_source_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char buf[64];
+ char *pch;
+ char *srcip;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_ip", &srcip);
+ strcpy(buf, srcip);
+ pch = strchr(buf, '/');
+ if (pch)
+ *pch = '\0';
+ *value = dmstrdup(buf);
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.SourceMask!UCI:firewall/rule,@i-1/src_ip*/
+int get_rule_source_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *pch;
+ *value = "";
+
+ char *srcip;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_ip", &srcip);
+ if (*srcip == '\0')
+ return 0;
+
+ pch = strchr(srcip, '/');
+ if (pch) {
+ *value = pch+1;
+ }
+ else {
+ *value = "";
+ }
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Protocol!UCI:firewall/rule,@i-1/proto*/
+int get_rule_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ FILE *fp;
+ char buf[256];
+ char protocol[32];
+ char protocol_nbr[16];
+ struct uci_section *ss = (struct uci_section *)data;
+ char *v;
+
+ dmuci_get_value_by_section_string((struct uci_section *)data, "proto", &v);
+ *value = "-1";
+ if (*v == '\0' || *v == '0') {
+ return 0;
+ }
+ if (isdigit_str(v)) {
+ *value = v;
+ return 0;
+ }
+ fp = fopen("/etc/protocols", "r");
+ if (fp == NULL)
+ return 0;
+ while (fgets (buf , 256 , fp) != NULL) {
+ sscanf(buf, "%s %s", protocol, protocol_nbr);
+ if (strcmp(protocol, v) == 0) {
+ *value =dmstrdup(protocol_nbr);
+ fclose(fp);
+ return 0;
+ }
+ }
+ fclose(fp);
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.DestPort!UCI:firewall/rule,@i-1/dest_port*/
+int get_rule_dest_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+ char *v;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest_port", &v);
+ v = dmstrdup(v);
+ tmp = strchr(v, ':');
+ if (tmp == NULL)
+ tmp = strchr(v, '-');
+ if (tmp)
+ *tmp = '\0';
+ if (*v == '\0') {
+ *value = "-1";
+ return 0;
+ }
+ *value = v;
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.DestPortRangeMax!UCI:firewall/rule,@i-1/dest_port*/
+int get_rule_dest_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *rpch, *tmp;
+ char *v;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest_port", &v);
+ tmp = strchr(v, ':');
+ if (tmp == NULL)
+ tmp = strchr(v, '-');
+ *value = (tmp) ? tmp+1 : "-1";
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.SourcePort!UCI:firewall/rule,@i-1/src_port*/
+int get_rule_source_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *tmp;
+ char *v;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_port", &v);
+ v = dmstrdup(v);
+ tmp = strchr(v, ':');
+ if (tmp == NULL)
+ tmp = strchr(v, '-');
+ if (tmp)
+ *tmp = '\0';
+ if (*v == '\0') {
+ *value = "-1";
+ return 0;
+ }
+ *value = v;
+ return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.SourcePortRangeMax!UCI:firewall/rule,@i-1/src_port*/
+int get_rule_source_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *rpch, *tmp;
+ char *v;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_port", &v);
+ tmp = strchr(v, ':');
+ if (tmp == NULL)
+ tmp = strchr(v, '-');
+ *value = (tmp) ? tmp+1 : "-1";
+ return 0;
+}
+
+int get_rule_icmp_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_list *v= NULL;
+ struct uci_element *e;
+ char *ptr;
+
+ dmasprintf(value, "%s", "");
+ dmuci_get_value_by_section_list((struct uci_section *)data, "icmp_type", &v);
+ if (v != NULL) {
+ uci_foreach_element(v, e) {
+ ptr= dmstrdup(*value);
+ free(*value);
+
+ if(strlen(ptr)==0)
+ dmasprintf(value, "%s", e->name);
+ else{
+ dmasprintf(value, "%s %s", ptr, e->name);
+ free(ptr);
+ }
+ }
+ }
+ return 0;
+}
+
+int get_rule_source_mac(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v= NULL;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_mac", &v);
+ *value = (v) ? v : "";
+ return 0;
+}
+
+int get_time_span_supported_days(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value= "mon tue wed thu fri sat sun";
+ return 0;
+}
+
+int get_time_span_days(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "weekdays", &v);
+ *value = (v) ? v : "";
+ return 0;
+}
+
+int get_time_span_start_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "start_time", &v);
+ *value = (v) ? v : "";
+ return 0;
+}
+
+int get_time_span_stop_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "stop_time", &v);
+ *value = (v) ? v : "";
+ return 0;
+}
+
+int set_firewall_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b)
+ dmcmd("/etc/init.d/firewall", 1, "enable");
+ else
+ dmcmd("/etc/init.d/firewall", 1, "disable");
+ break;
+ }
+ return 0;
+}
+
+int set_firewall_config(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ if (strcasecmp(value, "Advanced") != 0)
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int set_firewall_advanced_level(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ if (strcasecmp(value, "Device.Firewall.Level.1.") != 0)
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int set_level_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section* level=(struct uci_section *)data;
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, level, "name", value);
+ break;
+ }
+ return 0;
+}
+
+int set_level_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section* level=(struct uci_section *)data;
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, level, "description", value);
+ break;
+ }
+ return 0;
+}
+
+int set_level_port_mapping_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct uci_section *s = NULL;
+ char *v, *v2;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b) {
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_get_value_by_section_string(s, "src", &v);
+ dmuci_get_value_by_section_string(s, "name", &v2);
+ if (strcasestr(v, "wan") || strcasestr(v2, "wan")) {
+ dmuci_set_value_by_section(s, "masq", "1");
+ return 0;
+ }
+ }
+ }
+ else {
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_set_value_by_section(s, "masq", "");
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+int set_level_default_log_policy(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b) {
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_set_value_by_section(s, "log", "1");
+ }
+ }
+ else {
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_set_value_by_section(s, "log", "");
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+int set_chain_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b) || !b)
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int set_chain_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section* chains=(struct uci_section *)data;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, chains, "name", value);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ dmuci_set_value_by_section((struct uci_section *)data, "enabled", (b) ? "" : "no");
+ break;
+ }
+ return 0;
+}
+
+int set_rule_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int set_rule_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dms;
+ get_dmmap_section_of_config_section("dmmap_firewall", "rule", section_name((struct uci_section *)data), &dms);
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, dms, "description", value);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_target(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ if (strcasecmp(value, "Accept") == 0) {
+ dmuci_set_value_by_section((struct uci_section *)data, "target", "ACCEPT");
+ }
+ else if (strcasecmp(value, "Reject") == 0) {
+ dmuci_set_value_by_section((struct uci_section *)data, "target", "REJECT");
+ }
+ else if (strcasecmp(value, "Drop") == 0) {
+ dmuci_set_value_by_section((struct uci_section *)data, "target", "DROP");
+ }
+ else if (strcasecmp(value, "Return") == 0) {
+ dmuci_set_value_by_section((struct uci_section *)data, "target", "MARK");
+ }
+ break;
+ }
+ return 0;
+}
+
+int set_rule_target_chain(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int set_rule_source_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *iface, *zone, *v = "", *val, *net;
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ adm_entry_get_linker_value(ctx, value, &iface);
+ if(iface == NULL || iface[0] == '\0')
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ adm_entry_get_linker_value(ctx, value, &iface);
+ if (iface && iface[0] != '\0') {
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_get_value_by_section_string(s, "network", &net);
+ if (dm_strword(net, iface)) {
+ dmuci_get_value_by_section_string(s, "name", &zone);
+ dmuci_set_value_by_section((struct uci_section *)data, "src", zone);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+int set_rule_dest_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *iface, *zone, *v = "", *net;
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ adm_entry_get_linker_value(ctx, value, &iface);
+ if (iface != NULL && iface[0] != '\0') {
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_get_value_by_section_string(s, "name", &net);
+ if (dm_strword(net, iface)) {
+ dmuci_get_value_by_section_string(s, "name", &zone);
+ dmuci_set_value_by_section((struct uci_section *)data, "dest", zone);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+int set_rule_i_p_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ if (strcmp(value, "4") == 0) {
+ dmuci_set_value_by_section((struct uci_section *)data, "family", "ipv4");
+ }
+ else if (strcmp(value, "6") == 0) {
+ dmuci_set_value_by_section((struct uci_section *)data, "family", "ipv6");
+ }
+ else if (strcmp(value, "-1") == 0) {
+ dmuci_set_value_by_section((struct uci_section *)data, "family", "");
+ }
+ break;
+ break;
+ }
+ return 0;
+}
+
+int set_rule_dest_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char buf[64], new[64];
+ char *pch, *destip;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest_ip", &destip);
+ strcpy(buf, destip);
+ pch = strchr(buf, '/');
+ if (pch) {
+ sprintf(new, "%s%s", value, pch);
+ }
+ else {
+ strcpy(new, value);
+ }
+ dmuci_set_value_by_section((struct uci_section *)data, "dest_ip", new);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_dest_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char buf[64], new[64];
+ char *pch, *destip;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest_ip", &destip);
+ strcpy(buf, destip);
+ pch = strchr(buf, '/');
+ if (pch) {
+ *pch = '\0';
+ }
+ sprintf(new, "%s/%s", buf, value);
+ dmuci_set_value_by_section((struct uci_section *)data, "dest_ip", new);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_source_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char buf[64], new[64];
+ char *pch, *srcip;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_ip", &srcip);
+ strcpy(buf, srcip);
+ pch = strchr(buf, '/');
+ if (pch) {
+ sprintf(new, "%s%s", value, pch);
+ }
+ else {
+ strcpy(new, value);
+ }
+ dmuci_set_value_by_section((struct uci_section *)data, "src_ip", new);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_source_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char buf[64], new[64];
+ char *pch, *srcip;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_ip", &srcip);
+ strcpy(buf, srcip);
+ pch = strchr(buf, '/');
+ if (pch) {
+ *pch = '\0';
+ }
+ sprintf(new, "%s/%s", buf, value);
+ dmuci_set_value_by_section((struct uci_section *)data, "src_ip", new);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ if (*value == '-')
+ dmuci_set_value_by_section((struct uci_section *)data, "proto", "");
+ else
+ dmuci_set_value_by_section((struct uci_section *)data, "proto", value);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_dest_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *v, buffer[64], *tmp;
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ if (*value == '-')
+ value = "";
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest_port", &v);
+ tmp = strchr(v, ':');
+ if (tmp == NULL)
+ tmp = strchr(v, '-');
+
+ if (tmp == NULL) {
+ sprintf(buffer, "%s", value);
+ }
+ else {
+ sprintf(buffer, "%s%s", value, tmp);
+ }
+ dmuci_set_value_by_section((struct uci_section *)data, "dest_port", buffer);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_dest_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *v, *tmp, *buf, buffer[64];
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest_port", &v);
+ buf = dmstrdup(v);
+ v = buf;
+ tmp = strchr(buf, ':');
+ if (tmp == NULL)
+ tmp = strchr(v, '-');
+ if (tmp)
+ *tmp = '\0';
+ if (*value == '-') {
+ sprintf(buffer, "%s", v);
+ }
+ else {
+ sprintf(buffer, "%s:%s", v, value);
+ }
+ dmfree(buf);
+ dmuci_set_value_by_section((struct uci_section *)data, "dest_port", buffer);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_source_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *v, buffer[64], *tmp;
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ if (*value == '-')
+ value = "";
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_port", &v);
+ tmp = strchr(v, ':');
+ if (tmp == NULL)
+ tmp = strchr(v, '-');
+ if (tmp == NULL) {
+ sprintf(buffer, "%s", value);
+ }
+ else {
+ sprintf(buffer, "%s%s", value, tmp);
+ }
+ dmuci_set_value_by_section((struct uci_section *)data, "src_port", buffer);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_source_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *v, *tmp, *buf, buffer[64];
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_port", &v);
+ buf = dmstrdup(v);
+ v = buf;
+ tmp = strchr(buf, ':');
+ if (tmp == NULL)
+ tmp = strchr(buf, '-');
+ if (tmp)
+ *tmp = '\0';
+ if (*value == '-') {
+ sprintf(buffer, "%s", v);
+ }
+ else {
+ sprintf(buffer, "%s:%s", v, value);
+ }
+ dmfree(buf);
+ dmuci_set_value_by_section((struct uci_section *)data, "src_port", buffer);
+ break;
+ }
+ return 0;
+}
+
+int set_rule_icmp_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ int length, i;
+ char **devices= NULL;
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "icmp_type", "");
+ devices = strsplit(value, " ", &length);
+ for(i=0; i
+ */
+
+#ifndef _FIREWALL_H
+#define _FIREWALL_H
+
+extern DMOBJ tFirewallObj[];
+extern DMLEAF tFirewallParams[];
+extern DMLEAF tFirewallLevelParams[];
+extern DMLEAF tFirewallChainParams[];
+extern DMOBJ tFirewallChainObj[];
+extern DMLEAF tFirewallChainRuleParams[];
+extern DMOBJ tFirewallChainRuleObj[];
+extern DMLEAF tTimeSpanParams[];
+
+int browseLevelInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseChainInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseRuleInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int add_firewall_rule(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delete_firewall_rule(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int get_firewall_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_firewall_config(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_firewall_advanced_level(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_firewall_level_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_firewall_chain_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_level_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_level_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_level_chain(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_level_port_mapping_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_level_default_log_policy(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_chain_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_chain_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_chain_creator(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_chain_rule_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_target(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_target_chain(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_source_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_dest_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_i_p_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_dest_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_dest_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_source_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_source_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_dest_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_dest_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_source_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_source_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_icmp_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_rule_source_mac(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_time_span_supported_days(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_time_span_days(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_time_span_start_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_time_span_stop_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_firewall_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_firewall_config(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_firewall_advanced_level(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_level_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_level_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_level_port_mapping_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_level_default_log_policy(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_chain_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_chain_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_target(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_target_chain(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_source_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_dest_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_i_p_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_dest_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_dest_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_source_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_source_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_dest_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_dest_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_source_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_source_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_icmp_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_rule_source_mac(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_time_span_supported_days(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_time_span_days(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_time_span_start_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_time_span_stop_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+#endif
diff --git a/dmtree/tr181/hosts.c b/dmtree/tr181/hosts.c
new file mode 100644
index 00000000..f6c81768
--- /dev/null
+++ b/dmtree/tr181/hosts.c
@@ -0,0 +1,311 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2016 Inteno Broadband Technology AB
+ * Author: Anis Ellouze
+ *
+ */
+
+#include
+#include
+#include
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcwmp.h"
+#include "dmcommon.h"
+#include "hosts.h"
+#include "dmjson.h"
+#include "dmentry.h"
+
+/* *** Device.Hosts. *** */
+DMOBJ tHostsObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Host", &DMREAD, NULL, NULL, NULL, browsehostInst, NULL, NULL, NULL, tHostsHostParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tHostsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"HostNumberOfEntries", &DMREAD, DMT_UNINT, get_host_nbr_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Hosts.Host.{i}. *** */
+DMLEAF tHostsHostParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"AssociatedDevice", &DMREAD, DMT_STRING, get_host_associateddevice, NULL, NULL, NULL, BBFDM_BOTH},
+{"Layer3Interface", &DMREAD, DMT_STRING, get_host_layer3interface, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPAddress", &DMREAD, DMT_STRING, get_host_ipaddress, NULL, NULL, NULL, BBFDM_BOTH},
+{"HostName", &DMREAD, DMT_STRING, get_host_hostname, NULL, NULL, NULL, BBFDM_BOTH},
+{"Active", &DMREAD, DMT_BOOL, get_host_active, NULL, NULL, NULL, BBFDM_BOTH},
+{"PhysAddress", &DMREAD, DMT_STRING, get_host_phy_address, NULL, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"LinkType", &DMREAD, DMT_STRING, get_host_interfacetype, NULL, NULL, NULL, BBFDM_BOTH},
+{"AddressSource", &DMREAD, DMT_STRING, get_host_address_source, NULL, NULL, NULL, BBFDM_BOTH},
+{"LeaseTimeRemaining", &DMREAD, DMT_INT, get_host_leasetime_remaining, NULL, NULL, NULL, BBFDM_BOTH},
+{"DHCPClient", &DMREAD, DMT_STRING, get_host_dhcp_client, NULL, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"InterfaceType", &DMREAD, DMT_STRING, get_host_interface_type, NULL, NULL, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"ifname", &DMREAD, DMT_STRING, get_host_interfacename, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+
+/*************************************************************
+ * INIT
+/*************************************************************/
+inline int init_host_args(struct host_args *args, json_object *clients, char *key)
+{
+ args->client = clients;
+ args->key = key;
+ return 0;
+}
+/*************************************************************
+ * GET & SET PARAM
+/*************************************************************/
+int get_host_associateddevice(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *ss;
+ char *macaddr_linker = dmjson_get_value(((struct host_args *)data)->client, 1, "macaddr");
+ char *accesspointInstance = NULL, *wifiAssociativeDeviecPath;
+
+ uci_path_foreach_sections(icwmpd, "dmmap_wireless", "wifi-iface", ss) {
+ dmuci_get_value_by_section_string(ss, "accesspointinstance", &accesspointInstance);
+ if(accesspointInstance[0] != '\0')
+ dmasprintf(&wifiAssociativeDeviecPath, "Device.WiFi.AccessPoint.%s.AssociatedDevice.", accesspointInstance);
+ accesspointInstance = NULL;
+ adm_entry_get_linker_param(ctx, wifiAssociativeDeviecPath, macaddr_linker, value);
+ if(*value != NULL)
+ break;
+ }
+
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+int get_host_layer3interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ip_linker=dmjson_get_value(((struct host_args *)data)->client, 1, "network");
+ adm_entry_get_linker_param(ctx, "Device.IP.Interface.", ip_linker, value);
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+int get_host_interface_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *type= NULL;
+ char *ifname = dmjson_get_value(((struct host_args *)data)->client, 1, "network");
+ struct uci_section *ss = NULL;
+
+ uci_foreach_sections("network", "interface", ss) {
+ if(!strcmp(ifname, section_name(ss))){
+ dmuci_get_value_by_section_string(ss, "type", &type);
+ if(type!=NULL){
+ if(!strcmp(type, "bridge")) *value="Bridge";else *value= "Normal";
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+int get_host_interfacename(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *frequency, *wireless;
+
+ frequency = dmjson_get_value(((struct host_args *)data)->client, 1, "frequency");
+ wireless = dmjson_get_value(((struct host_args *)data)->client, 1, "wireless");
+ if( (*frequency != '\0') && (strcmp(wireless, "true")==0) )
+ {
+ if(strcmp(frequency,"5GHz")==0)
+ *value = "WiFi@5GHz";
+ else
+ *value = "WiFi@2.4GHz";
+ }
+ else
+ {
+ *value = dmjson_get_value(((struct host_args *)data)->client, 1, "ethport");
+ if (*value == NULL)
+ *value = "";
+ }
+ return 0;
+}
+
+int get_host_ipaddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = dmjson_get_value(((struct host_args *)data)->client, 1, "ipaddr");
+ return 0;
+}
+
+int get_host_hostname(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = dmjson_get_value(((struct host_args *)data)->client, 1, "hostname");
+ return 0;
+}
+
+int get_host_active(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = dmjson_get_value(((struct host_args *)data)->client, 1, "connected");
+ return 0;
+}
+
+int get_host_phy_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = dmjson_get_value(((struct host_args *)data)->client, 1, "macaddr");
+ return 0;
+}
+
+int get_host_address_source(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *dhcp;
+
+ dhcp = dmjson_get_value(((struct host_args *)data)->client, 1, "dhcp");
+ if (strcasecmp(dhcp, "true") == 0)
+ *value = "DHCP";
+ else
+ *value = "Static";
+ return 0;
+}
+
+int get_host_leasetime_remaining(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char buf[80], *dhcp;
+ FILE *fp;
+ char line[MAX_DHCP_LEASES];
+ struct tm ts;
+ char *leasetime, *mac_f, *mac, *line1;
+ char delimiter[] = " \t";
+
+ dhcp = dmjson_get_value(((struct host_args *)data)->client, 1, "dhcp");
+ if (strcmp(dhcp, "false") == 0) {
+ *value = "0";
+ }
+ else {
+ mac = dmjson_get_value(((struct host_args *)data)->client, 1, "macaddr");
+ fp = fopen(DHCP_LEASES_FILE, "r");
+ if ( fp != NULL)
+ {
+ while (fgets(line, MAX_DHCP_LEASES, fp) != NULL )
+ {
+ if (line[0] == '\n')
+ continue;
+ line1 = dmstrdup(line);
+ leasetime = cut_fx(line, delimiter, 1);
+ mac_f = cut_fx(line1, delimiter, 2);
+ if (strcasecmp(mac, mac_f) == 0) {
+ int rem_lease = atoi(leasetime) - time(NULL);
+ if (rem_lease < 0)
+ *value = "-1";
+ else
+ dmasprintf(value, "%d", rem_lease); // MEM WILL BE FREED IN DMMEMCLEAN
+ fclose(fp) ;
+ return 0;
+ }
+ }
+ fclose(fp);
+ *value = "0";
+ }
+ }
+ return 0;
+}
+
+int get_host_dhcp_client(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *linker;
+ dmasprintf(&linker, "%s", ((struct host_args *)data)->key);
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cDHCPv4%c", dmroot, dm_delim, dm_delim), linker, value); // MEM WILL BE FREED IN DMMEMCLEAN
+ if (*value == NULL) {
+ *value = "";
+ }
+ dmfree(linker);
+ return 0;
+}
+
+static char *get_interface_type(char *mac, char *ndev)
+{
+ json_object *res;
+ int wlctl_num;
+ struct uci_section *s, *d;
+ char *network, *device, *value, *wunit;
+ char buf[8], *p;
+
+ uci_foreach_sections("wireless", "wifi-device", d) {
+ wlctl_num = 0;
+ wunit = section_name(d);
+ uci_foreach_option_eq("wireless", "wifi-iface", "device", wunit, s) {
+ dmuci_get_value_by_section_string(s, "network", &network);
+ if (strcmp(network, ndev) == 0) {
+ if (wlctl_num != 0) {
+ sprintf(buf, "%s.%d", wunit, wlctl_num);
+ p = buf;
+ }
+ else {
+ p = wunit;
+ }
+ dmubus_call("router.wireless", "stas", UBUS_ARGS{{"vif", p, String}}, 1, &res);
+ if(res) {
+ json_object_object_foreach(res, key, val) {
+ value = dmjson_get_value(val, 1, "macaddr");
+ if (strcasecmp(value, mac) == 0)
+ return "802.11";
+ }
+ }
+ wlctl_num++;
+ }
+ }
+ }
+ return "Ethernet";
+}
+
+int get_host_interfacetype(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *mac, *network;
+
+ mac = dmjson_get_value(((struct host_args *)data)->client, 1, "macaddr");
+ network = dmjson_get_value(((struct host_args *)data)->client, 1, "network");
+ *value = get_interface_type(mac, network);
+ return 0;
+}
+
+int get_host_nbr_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int entries = 0;
+ json_object *res;
+
+ dmubus_call("router.network", "clients", UBUS_ARGS{}, 0, &res);
+ DM_ASSERT(res, *value = "0");
+ json_object_object_foreach(res, key, client_obj) {
+ entries++;
+ }
+ dmasprintf(value, "%d", entries); // MEM WILL BE FREED IN DMMEMCLEAN
+ return 0;
+}
+
+/*************************************************************
+ * ENTRY METHOD
+/*************************************************************/
+int browsehostInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ json_object *res, *client_obj;
+ char *idx, *idx_last = NULL, *connected;
+ int id = 0;
+ struct host_args curr_host_args = {0};
+
+ dmubus_call("router.network", "clients", UBUS_ARGS{}, 0, &res);
+ if (res) {
+ json_object_object_foreach(res, key, client_obj) {
+ connected = dmjson_get_value(client_obj, 1, "connected");
+ if(strcmp(connected, "false") == 0)
+ continue;
+ init_host_args(&curr_host_args, client_obj, key);
+ idx = handle_update_instance(2, dmctx, &idx_last, update_instance_without_section, 1, ++id);
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_host_args, idx) == DM_STOP)
+ break;
+ }
+ }
+ return 0;
+}
+
diff --git a/dmtree/tr181/hosts.h b/dmtree/tr181/hosts.h
new file mode 100644
index 00000000..aa77a642
--- /dev/null
+++ b/dmtree/tr181/hosts.h
@@ -0,0 +1,41 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2016 Inteno Broadband Technology AB
+ * Author: Anis Ellouze
+ *
+ */
+
+#ifndef __HOSTS_H
+#define __HOSTS_H
+
+struct host_args
+{
+ json_object *client;
+ char *key;
+};
+
+extern DMOBJ tHostsObj[];
+extern DMLEAF tHostsParams[];
+extern DMLEAF tHostsHostParams[];
+
+int browsehostInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int get_host_nbr_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_associateddevice(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_layer3interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_interface_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_interfacename(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_ipaddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_hostname(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_active(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_phy_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_interfacetype(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_address_source(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_leasetime_remaining(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_host_dhcp_client(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+#endif
diff --git a/dmtree/tr181/interfacestack.c b/dmtree/tr181/interfacestack.c
new file mode 100644
index 00000000..b3309b34
--- /dev/null
+++ b/dmtree/tr181/interfacestack.c
@@ -0,0 +1,534 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Amin Ben Ramdhane
+*/
+
+#include "dmcwmp.h"
+#include "dmcommon.h"
+#include "dmubus.h"
+#include "dmjson.h"
+#include "dmentry.h"
+#include "interfacestack.h"
+
+/* *** Device.InterfaceStack.{i}. *** */
+DMLEAF tInterfaceStackParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Alias", &DMWRITE, DMT_STRING, get_InterfaceStack_Alias, set_InterfaceStack_Alias, NULL, NULL, BBFDM_BOTH},
+{"HigherLayer", &DMREAD, DMT_STRING, get_InterfaceStack_HigherLayer, NULL, NULL, NULL, BBFDM_BOTH},
+{"LowerLayer", &DMREAD, DMT_STRING, get_InterfaceStack_LowerLayer, NULL, NULL, NULL, BBFDM_BOTH},
+{"HigherAlias", &DMREAD, DMT_STRING, get_InterfaceStack_HigherAlias, NULL, NULL, NULL, BBFDM_BOTH},
+{"LowerAlias", &DMREAD, DMT_STRING, get_InterfaceStack_LowerAlias, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*************************************************************
+ * ENTRY METHOD
+/*************************************************************/
+static char *get_instance_by_section(struct dmctx *dmctx, int mode, char *dmmap_config, char *section, struct uci_section *s, char *instance_option, char *alias_option)
+{
+ struct uci_section *dmmap_section;
+ char *instance;
+
+ get_dmmap_section_of_config_section(dmmap_config, section, section_name(s), &dmmap_section);
+ if(dmmap_section == NULL) {
+ return "";
+ }
+
+ if (mode == INSTANCE_MODE_NUMBER) {
+ dmuci_get_value_by_section_string(dmmap_section, instance_option, &instance);
+ }
+ else {
+ dmuci_get_value_by_section_string(dmmap_section, alias_option, &instance);
+ }
+ return instance;
+}
+
+static char *get_alias_by_section(char *dmmap_config, char *section, struct uci_section *s, char *alias_option)
+{
+ struct uci_section *dmmap_section;
+ char *alias;
+
+ get_dmmap_section_of_config_section(dmmap_config, section, section_name(s), &dmmap_section);
+ if(dmmap_section == NULL) {
+ return "";
+ }
+ dmuci_get_value_by_section_string(dmmap_section, alias_option, &alias);
+ return alias;
+}
+
+static struct uci_section *create_dmmap_interface_stack_section(char *curr_inst)
+{
+ struct uci_section *s = NULL;
+ char *name;
+
+ check_create_dmmap_package("dmmap_interface_stack");
+ uci_path_foreach_option_eq(icwmpd, "dmmap_interface_stack", "interface_stack", "interface_stack_instance", curr_inst, s) {
+ return s;
+ }
+ if (!s) {
+ DMUCI_ADD_SECTION(icwmpd, "dmmap_interface_stack", "interface_stack", &s, &name);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, "interface_stack_instance", curr_inst);
+ }
+ return s;
+}
+
+int browseInterfaceStackInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct interfacestack_data ifdata = {0};
+ struct uci_section *s = NULL, *sd = NULL, *port, *port_s, *ss, *dmmap_s = NULL;
+ char *proto, *type, *pch, *spch, *layer_inst, *v, *vb, *higheralias, *loweralias, *ifname, *br_inst, *mg, *value, *p, *device, *name;
+ char *interface_stack_int = NULL, *interface_stack_int_last = NULL, *wanifname, *wanlinker, *mac, *vlan_method, *sectionname, *package, *section;
+ char buf_lowerlayer[128] = "";
+ char buf_higherlayer[128] = "";
+ char buf_higheralias[64] = "";
+ char buf_loweralias[64] = "";
+ char buf_instance[32] = "";
+ char linker[64] = "";
+ char buf_tmp[64] = "";
+ int instance = 0, found = 0;
+ json_object *jobj;
+
+ /* Higher layers are Device.IP.Interface.{i}. */
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if (strcmp(type, "alias") == 0 || strcmp(section_name(s), "loopback")==0)
+ continue;
+ layer_inst = get_instance_by_section(dmctx, dmctx->instance_mode, "dmmap_network", "interface", s, "ip_int_instance", "ip_int_alias");
+ if (*layer_inst == '\0')
+ continue;
+ sprintf(buf_higherlayer, "Device.IP.Interface.%s.", layer_inst);
+ higheralias = get_alias_by_section("dmmap_network", "interface", s, "ip_int_alias");
+ sprintf(buf_higheralias, "%s", higheralias);
+ dmuci_get_value_by_section_string(s, "proto", &proto);
+ if (strstr(proto, "ppp")) {
+ layer_inst = get_instance_by_section(dmctx, dmctx->instance_mode, "dmmap_network", "interface", s, "ppp_int_instance", "ppp_int_alias");
+ if (*layer_inst == '\0')
+ continue;
+ sprintf(buf_lowerlayer, "Device.PPP.Interface.%s.", layer_inst);
+ loweralias = get_alias_by_section("dmmap_network", "interface", s, "ppp_int_alias");
+ sprintf(buf_loweralias, "%s", loweralias);
+ }
+ else {
+ device = get_device(section_name(s));
+ if (device[0] != '\0') {
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cEthernet%cVLANTermination%c", dmroot, dm_delim, dm_delim, dm_delim), device, &v);
+ dmuci_get_option_value_string("cwmp", "cpe", "vlan_method", &vlan_method);
+ if(strcmp(vlan_method, "2") == 0)
+ loweralias = get_alias_by_section("dmmap_network", "device", s, "all_vlan_term_alias");
+ else
+ loweralias = get_alias_by_section("dmmap_network", "device", s, "vlan_term_alias");
+ if (v != NULL)
+ found = 1;
+ }
+ mac = get_macaddr(section_name(s));
+ if (mac[0] != '\0' && found == 0) {
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), mac, &v);
+ loweralias = get_alias_by_section("dmmap", "link", s, "link_alias");
+ if (v == NULL)
+ v = "";
+ }
+ sprintf(buf_lowerlayer, "%s", v);
+ sprintf(buf_loweralias, "%s", loweralias);
+ }
+ ifdata.higherlayer = buf_higherlayer;
+ ifdata.lowerlayer = buf_lowerlayer;
+ ifdata.higheralias = buf_higheralias;
+ ifdata.loweralias = buf_loweralias;
+ sprintf(buf_instance, "%d", ++instance);
+ dmmap_s = create_dmmap_interface_stack_section(buf_instance);
+ interface_stack_int = handle_update_instance(1, dmctx, &interface_stack_int_last, update_instance_alias, 3, dmmap_s, "interface_stack_instance", "interface_stack_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&ifdata, interface_stack_int) == DM_STOP)
+ goto end;
+ }
+
+ /* Higher layers are Device.PPP.Interface.{i}. */
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "proto", &proto);
+ if (!strstr(proto, "ppp"))
+ continue;
+ layer_inst = get_instance_by_section(dmctx, dmctx->instance_mode, "dmmap_network", "interface", s, "ppp_int_instance", "ppp_int_alias");
+ if (*layer_inst == '\0')
+ continue;
+ sprintf(buf_higherlayer, "Device.PPP.Interface.%s.", layer_inst);
+ higheralias = get_alias_by_section("dmmap_network", "interface", s, "ppp_int_alias");
+ sprintf(buf_higheralias, "%s", higheralias);
+ found = 0;
+ device = get_device(section_name(s));
+ if (device[0] != '\0') {
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cEthernet%cVLANTermination%c", dmroot, dm_delim, dm_delim, dm_delim), device, &v);
+ dmuci_get_option_value_string("cwmp", "cpe", "vlan_method", &vlan_method);
+ if(strcmp(vlan_method, "2") == 0)
+ loweralias = get_alias_by_section("dmmap_network", "device", s, "all_vlan_term_alias");
+ else
+ loweralias = get_alias_by_section("dmmap_network", "device", s, "vlan_term_alias");
+ if (v != NULL)
+ found = 1;
+ }
+ mac = get_macaddr(section_name(s));
+ if (mac[0] != '\0' && found == 0) {
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), mac, &v);
+ loweralias = get_alias_by_section("dmmap", "link", s, "link_alias");
+ if (v == NULL)
+ v = "";
+ }
+ sprintf(buf_lowerlayer, "%s", v);
+ sprintf(buf_loweralias, "%s", loweralias);
+ ifdata.higherlayer = buf_higherlayer;
+ ifdata.lowerlayer = buf_lowerlayer;
+ ifdata.higheralias = buf_higheralias;
+ ifdata.loweralias = buf_loweralias;
+ sprintf(buf_instance, "%d", ++instance);
+ dmmap_s = create_dmmap_interface_stack_section(buf_instance);
+ interface_stack_int = handle_update_instance(1, dmctx, &interface_stack_int_last, update_instance_alias, 3, dmmap_s, "interface_stack_instance", "interface_stack_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&ifdata, interface_stack_int) == DM_STOP)
+ goto end;
+ }
+
+ /* Higher layers are Device.Ethernet.VLANTermination.{i}. */
+ uci_foreach_sections("network", "device", s) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ dmuci_get_option_value_string("cwmp", "cpe", "vlan_method", &vlan_method);
+ if ((strcmp(vlan_method, "2") != 0 && strcmp(vlan_method, "1") != 0) || (strcmp(vlan_method, "1") == 0 && strcmp(type, "untagged") == 0) )
+ continue;
+ if(strcmp(vlan_method, "2") == 0)
+ layer_inst = get_instance_by_section(dmctx, dmctx->instance_mode, "dmmap_network", "device", s, "all_vlan_term_instance", "all_vlan_term_alias");
+ else
+ layer_inst = get_instance_by_section(dmctx, dmctx->instance_mode, "dmmap_network", "device", s, "only_tagged_vlan_term_instance", "vlan_term_alias");
+ if (*layer_inst == '\0')
+ continue;
+ sprintf(buf_higherlayer, "Device.Ethernet.VLANTermination.%s.", layer_inst);
+ if(strcmp(vlan_method, "2") == 0)
+ higheralias = get_alias_by_section("dmmap_network", "device", s, "all_vlan_term_alias");
+ else
+ higheralias = get_alias_by_section("dmmap_network", "device", s, "vlan_term_alias");
+ sprintf(buf_higheralias, "%s", higheralias);
+
+ dmuci_get_value_by_section_string(s, "name", &value);
+ uci_foreach_sections("network", "interface", ss) {
+ dmuci_get_value_by_section_string(ss, "ifname", &ifname);
+ for (pch = strtok_r(ifname, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) {
+ if(strcmp(pch, value) == 0) {
+ mac = get_macaddr(section_name(ss));
+ if (mac[0] != '\0') {
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), mac, &v);
+ loweralias = get_alias_by_section("dmmap", "link", ss, "link_alias");
+ if (v == NULL)
+ v = "";
+ break;
+ }
+ }
+ }
+ }
+ sprintf(buf_lowerlayer, "%s", v);
+ sprintf(buf_loweralias, "%s", loweralias);
+ ifdata.higherlayer = buf_higherlayer;
+ ifdata.lowerlayer = buf_lowerlayer;
+ ifdata.higheralias = buf_higheralias;
+ ifdata.loweralias = buf_loweralias;
+ sprintf(buf_instance, "%d", ++instance);
+ dmmap_s = create_dmmap_interface_stack_section(buf_instance);
+ interface_stack_int = handle_update_instance(1, dmctx, &interface_stack_int_last, update_instance_alias, 3, dmmap_s, "interface_stack_instance", "interface_stack_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&ifdata, interface_stack_int) == DM_STOP)
+ goto end;
+ }
+
+ /* Higher layers are Device.Ethernet.Link.{i}. */
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if (strcmp(type, "alias") == 0 || strcmp(section_name(s), "loopback")==0)
+ continue;
+ dmuci_get_value_by_section_string(s, "ifname", &ifname);
+ if (*ifname == '\0' || *ifname == '@')
+ continue;
+ layer_inst = get_instance_by_section(dmctx, dmctx->instance_mode, "dmmap", "link", s, "link_instance", "link_alias");
+ if (*layer_inst == '\0')
+ continue;
+ sprintf(buf_higherlayer, "Device.Ethernet.Link.%s.", layer_inst);
+ higheralias = get_alias_by_section("dmmap", "link", s, "link_alias");
+ sprintf(buf_higheralias, "%s", higheralias);
+ if (strcmp(type, "bridge") == 0) {
+ br_inst = get_alias_by_section("dmmap_network", "interface", s, "bridge_instance");
+ uci_path_foreach_option_eq(icwmpd, "dmmap_bridge_port", "bridge_port", "bridge_key", br_inst, port) {
+ dmuci_get_value_by_section_string(port, "mg_port", &mg);
+ if (strcmp(mg, "true") == 0) {
+ sprintf(linker, "%s+", section_name(port));
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, dm_delim, dm_delim, dm_delim), linker, &v);
+ dmuci_get_value_by_section_string(port, "bridge_port_alias", &loweralias);
+ break;
+ }
+ }
+ } else {
+ uci_foreach_option_eq("ports", "ethport", "name", "WAN", port_s) {
+ dmuci_get_value_by_section_string(port_s, "ifname", &wanifname);
+ if(strstr(ifname, wanifname)) {
+ dmasprintf(&wanlinker, "%s.1", wanifname);
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cEthernet%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), wanlinker, &v);
+ dmfree(wanlinker);
+ loweralias = get_alias_by_section("dmmap_ports", "ethport", port_s, "eth_port_alias");
+ break;
+ }
+ }
+ }
+ if (v == NULL)
+ v = "";
+ sprintf(buf_loweralias, "%s", loweralias);
+ ifdata.higherlayer = buf_higherlayer;
+ ifdata.lowerlayer = v;
+ ifdata.higheralias = buf_higheralias;
+ ifdata.loweralias = buf_loweralias;
+ sprintf(buf_instance, "%d", ++instance);
+ dmmap_s = create_dmmap_interface_stack_section(buf_instance);
+ interface_stack_int = handle_update_instance(1, dmctx, &interface_stack_int_last, update_instance_alias, 3, dmmap_s, "interface_stack_instance", "interface_stack_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&ifdata, interface_stack_int) == DM_STOP)
+ goto end;
+ }
+
+ /* Higher layers are Device.Bridging.Bridge.{i}.Port.{i}.*/
+ uci_foreach_sections("network", "interface", s) {
+ dmuci_get_value_by_section_string(s, "type", &type);
+ if (strcmp(type, "bridge") != 0)
+ continue;
+ br_inst = get_instance_by_section(dmctx, dmctx->instance_mode, "dmmap_network", "interface", s, "bridge_instance", "bridge_alias");
+ if (*br_inst == '\0')
+ continue;
+ uci_path_foreach_option_eq(icwmpd, "dmmap_bridge_port", "bridge_port", "bridge_key", br_inst, port) {
+ dmuci_get_value_by_section_string(port, "mg_port", &mg);
+ if (strcmp(mg, "true") == 0) {
+ sprintf(linker, "%s+", section_name(port));
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, dm_delim, dm_delim, dm_delim), linker, &pch);
+ dmuci_get_value_by_section_string(port, "bridge_port_alias", &higheralias);
+ sprintf(buf_tmp, "%s", higheralias);
+ if (pch == NULL)
+ pch = "";
+ break;
+ }
+ }
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_bridge_port", "bridge_port", "bridge_key", br_inst, sd) {
+ dmuci_get_value_by_section_string(sd, "mg_port", &mg);
+ if (strcmp(mg, "true") == 0)
+ continue;
+
+ dmuci_get_value_by_section_string(sd, "section_name", §ionname);
+ dmuci_get_value_by_section_string(sd, "package", &package);
+ dmuci_get_value_by_section_string(sd, "section", §ion);
+
+ uci_foreach_sections(package, section, port_s) {
+ if(strcmp(section_name(port_s), sectionname) == 0) {
+ dmuci_get_value_by_section_string(port_s, "ifname", &ifname);
+ dmuci_get_value_by_section_string(port_s, "name", &name);
+ break;
+ }
+ }
+ if(strcmp(package, "network") == 0 && strcmp(section, "device") == 0)
+ sprintf(linker, "%s+%s", sectionname, name);
+ else
+ sprintf(linker, "%s+%s", sectionname, ifname);
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, dm_delim, dm_delim, dm_delim), linker, &vb);
+ if (vb == NULL)
+ vb = "";
+ dmuci_get_value_by_section_string(sd, "bridge_port_alias", &loweralias);
+ sprintf(buf_loweralias, "%s", loweralias);
+
+ ifdata.higherlayer = pch;
+ ifdata.lowerlayer = vb;
+ ifdata.higheralias = buf_tmp;
+ ifdata.loweralias = buf_loweralias;
+ sprintf(buf_instance, "%d", ++instance);
+ dmmap_s = create_dmmap_interface_stack_section(buf_instance);
+ interface_stack_int = handle_update_instance(1, dmctx, &interface_stack_int_last, update_instance_alias, 3, dmmap_s, "interface_stack_instance", "interface_stack_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&ifdata, interface_stack_int) == DM_STOP)
+ goto end;
+
+ sprintf(buf_higheralias, "%s", loweralias);
+ if(strcmp(package, "ports") == 0) {
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cEthernet%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), ifname, &v);
+ loweralias = get_alias_by_section("dmmap_ports", "ethport", port_s, "eth_port_alias");
+ } else if(strcmp(package, "wireless") == 0) {
+ adm_entry_get_linker_param(dmctx,dm_print_path("%s%cWiFi%cSSID%c", dmroot, dm_delim, dm_delim, dm_delim), ifname, &v);
+ loweralias = get_alias_by_section("dmmap_wireless", "wifi-iface", port_s, "ssidalias");
+ } else if(strcmp(package, "network") == 0) {
+ if(strstr(ifname, "atm")) {
+ adm_entry_get_linker_param(dmctx,dm_print_path("%s%cATM%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), ifname, &v);
+ uci_foreach_sections("dsl", "atm-device", ss) {
+ if(strcmp(section_name(ss), ifname) == 0) {
+ loweralias = get_alias_by_section("dmmap_dsl", "atm-device", ss, "atmlinkalias");
+ break;
+ }
+ }
+ } else if(strstr(ifname, "ptm")) {
+ adm_entry_get_linker_param(dmctx,dm_print_path("%s%cPTM%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), ifname, &v);
+ uci_foreach_sections("dsl", "ptm-device", ss) {
+ if(strcmp(section_name(ss), ifname) == 0) {
+ loweralias = get_alias_by_section("dmmap_dsl", "ptm-device", ss, "ptmlinkalias");
+ break;
+ }
+ }
+ } else {
+ sprintf(linker, "%s.1", ifname);
+ adm_entry_get_linker_param(dmctx,dm_print_path("%s%cEthernet%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, &v);
+ loweralias = get_alias_by_section("dmmap_ports", "ethport", port_s, "eth_port_alias");
+ }
+ }
+ sprintf(buf_loweralias, "%s", loweralias);
+ if (v == NULL)
+ v = "";
+ ifdata.higherlayer = vb;
+ ifdata.lowerlayer = v;
+ ifdata.higheralias = buf_higheralias;
+ ifdata.loweralias = buf_loweralias;
+ sprintf(buf_instance, "%d", ++instance);
+ dmmap_s = create_dmmap_interface_stack_section(buf_instance);
+ interface_stack_int = handle_update_instance(1, dmctx, &interface_stack_int_last, update_instance_alias, 3, dmmap_s, "interface_stack_instance", "interface_stack_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&ifdata, interface_stack_int) == DM_STOP)
+ goto end;
+
+ if(strcmp(package, "wireless") == 0) {
+ sprintf(buf_higheralias, "%s", loweralias);
+ uci_foreach_option_eq("wireless", "wifi-iface", "ifname", ifname, ss) {
+ dmuci_get_value_by_section_string(ss, "device", &device);
+ }
+ if (device[0] != '\0') {
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cWiFi%cRadio%c", dmroot, dm_delim, dm_delim, dm_delim), device, &vb);
+ uci_foreach_sections("wireless", "wifi-device", ss) {
+ if(strcmp(section_name(ss), device) == 0) {
+ loweralias = get_alias_by_section("dmmap_wireless", "wifi-device", ss, "radioalias");
+ break;
+ }
+ }
+ }
+ if (vb == NULL)
+ vb = "";
+ sprintf(buf_loweralias, "%s", loweralias);
+ ifdata.higherlayer = v;
+ ifdata.lowerlayer = vb;
+ ifdata.higheralias = buf_higheralias;
+ ifdata.loweralias = buf_loweralias;
+ sprintf(buf_instance, "%d", ++instance);
+ dmmap_s = create_dmmap_interface_stack_section(buf_instance);
+ interface_stack_int = handle_update_instance(1, dmctx, &interface_stack_int_last, update_instance_alias, 3, dmmap_s, "interface_stack_instance", "interface_stack_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&ifdata, interface_stack_int) == DM_STOP)
+ goto end;
+ }
+
+ if(strcmp(package, "network") == 0) {
+ if(strstr(ifname, "atm") || strstr(ifname, "ptm")) {
+ sprintf(buf_higheralias, "%s", loweralias);
+ char *link_channel = "channel_0";
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cDSL%cChannel%c", dmroot, dm_delim, dm_delim, dm_delim), link_channel, &vb);
+ if (vb == NULL)
+ vb = "";
+ uci_path_foreach_sections(icwmpd, "dmmap", "dsl_channel", ss) {
+ dmuci_get_value_by_section_string(ss, "dsl_channel_alias", &loweralias);
+ }
+ sprintf(buf_loweralias, "%s", loweralias);
+ ifdata.higherlayer = v;
+ ifdata.lowerlayer = vb;
+ ifdata.higheralias = buf_higheralias;
+ ifdata.loweralias = buf_loweralias;
+ sprintf(buf_instance, "%d", ++instance);
+ dmmap_s = create_dmmap_interface_stack_section(buf_instance);
+ interface_stack_int = handle_update_instance(1, dmctx, &interface_stack_int_last, update_instance_alias, 3, dmmap_s, "interface_stack_instance", "interface_stack_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&ifdata, interface_stack_int) == DM_STOP)
+ goto end;
+
+ sprintf(buf_higheralias, "%s", loweralias);
+ char *link_line = "line_0";
+ adm_entry_get_linker_param(dmctx, dm_print_path("%s%cDSL%cLine%c", dmroot, dm_delim, dm_delim, dm_delim), link_line, &value);
+ if (value == NULL)
+ value = "";
+ uci_path_foreach_sections(icwmpd, "dmmap", "dsl_line", ss) {
+ dmuci_get_value_by_section_string(ss, "dsl_line_alias", &loweralias);
+ }
+ sprintf(buf_loweralias, "%s", loweralias);
+ ifdata.higherlayer = vb;
+ ifdata.lowerlayer = value;
+ ifdata.higheralias = buf_higheralias;
+ ifdata.loweralias = buf_loweralias;
+ sprintf(buf_instance, "%d", ++instance);
+ dmmap_s = create_dmmap_interface_stack_section(buf_instance);
+ interface_stack_int = handle_update_instance(1, dmctx, &interface_stack_int_last, update_instance_alias, 3, dmmap_s, "interface_stack_instance", "interface_stack_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&ifdata, interface_stack_int) == DM_STOP)
+ goto end;
+ }
+ }
+ }
+ }
+
+end:
+ return 0;
+}
+
+/*************************************************************
+ * GET & SET PARAM
+/*************************************************************/
+int get_Device_InterfaceStackNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_path_foreach_sections(icwmpd, "dmmap_interface_stack", "interface_stack", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+int get_InterfaceStack_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ uci_path_foreach_option_eq(icwmpd, "dmmap_interface_stack", "interface_stack", "interface_stack_instance", instance, s) {
+ dmuci_get_value_by_section_string(s, "interface_stack_alias", value);
+ }
+ return 0;
+}
+
+int set_InterfaceStack_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ uci_path_foreach_option_eq(icwmpd, "dmmap_interface_stack", "interface_stack", "interface_stack_instance", instance, s) {
+ dmuci_set_value_by_section(s, "interface_stack_alias", value);
+ }
+ break;
+ }
+ return 0;
+}
+
+int get_InterfaceStack_HigherLayer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct interfacestack_data *ifdata = (struct interfacestack_data *) data;
+ *value = dmstrdup(ifdata->higherlayer);
+ return 0;
+}
+
+int get_InterfaceStack_LowerLayer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct interfacestack_data *ifdata = (struct interfacestack_data *) data;
+ *value = dmstrdup(ifdata->lowerlayer);
+ return 0;
+}
+
+int get_InterfaceStack_HigherAlias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct interfacestack_data *ifdata = (struct interfacestack_data *) data;
+ *value = dmstrdup(ifdata->higheralias);
+ return 0;
+}
+
+int get_InterfaceStack_LowerAlias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct interfacestack_data *ifdata = (struct interfacestack_data *) data;
+ *value = dmstrdup(ifdata->loweralias);
+ return 0;
+}
diff --git a/dmtree/tr181/interfacestack.h b/dmtree/tr181/interfacestack.h
new file mode 100644
index 00000000..112a1bef
--- /dev/null
+++ b/dmtree/tr181/interfacestack.h
@@ -0,0 +1,34 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Amin Ben Ramdhane
+*/
+
+#ifndef __INTERFACESTACK_H
+#define __INTERFACESTACK_H
+
+extern DMLEAF tInterfaceStackParams[];
+
+struct interfacestack_data {
+ char *lowerlayer;
+ char *higherlayer;
+ char *loweralias;
+ char *higheralias;
+};
+
+int browseInterfaceStackInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int get_Device_InterfaceStackNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_InterfaceStack_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_InterfaceStack_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_InterfaceStack_HigherLayer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_InterfaceStack_LowerLayer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_InterfaceStack_HigherAlias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_InterfaceStack_LowerAlias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+#endif //__INTERFACESTACK_H
diff --git a/dmtree/tr181/ip.c b/dmtree/tr181/ip.c
new file mode 100644
index 00000000..3263a19a
--- /dev/null
+++ b/dmtree/tr181/ip.c
@@ -0,0 +1,2017 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Anis Ellouze
+* Author: Amin Ben Ramdhane
+*
+*/
+
+#include
+#include
+#include
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcwmp.h"
+#include "dmcommon.h"
+#include "ip.h"
+#include "dmjson.h"
+#include "dmentry.h"
+#ifdef BBF_TR143
+#include "diagnostics.h"
+#endif
+
+struct dm_forced_inform_s IPv4INFRM = {0, get_ipv4_finform};
+struct dm_forced_inform_s IPv6INFRM = {0, get_ipv6_finform};
+
+/* *** Device.IP. *** */
+DMOBJ tIPObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"Interface", &DMWRITE, add_ip_interface, delete_ip_interface, NULL, browseIPIfaceInst, NULL, NULL, tInterfaceObj, tIPintParams, get_linker_ip_interface, BBFDM_BOTH},
+#ifdef BBF_TR143
+{"Diagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsObj, tIPDiagnosticsParams, NULL, BBFDM_BOTH},
+#endif
+{0}
+};
+
+DMLEAF tIPParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"IPv4Capable", &DMREAD, DMT_BOOL, get_IP_IPv4Capable, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPv4Enable", &DMWRITE, DMT_BOOL, get_IP_IPv4Enable, set_IP_IPv4Enable, NULL, NULL, BBFDM_BOTH},
+{"IPv4Status", &DMREAD, DMT_STRING, get_IP_IPv4Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPv6Capable", &DMREAD, DMT_BOOL, get_IP_IPv6Capable, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPv6Enable", &DMWRITE, DMT_BOOL, get_IP_IPv6Enable, set_IP_IPv6Enable, NULL, NULL, BBFDM_BOTH},
+{"IPv6Status", &DMREAD, DMT_STRING, get_IP_IPv6Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"ULAPrefix", &DMWRITE, DMT_STRING, get_IP_ULAPrefix, set_IP_ULAPrefix, NULL, NULL, BBFDM_BOTH},
+{"InterfaceNumberOfEntries", &DMREAD, DMT_UNINT, get_IP_InterfaceNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.IP.Interface. *** */
+DMOBJ tInterfaceObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"IPv4Address", &DMWRITE, add_ipv4, delete_ipv4, NULL, browseIfaceIPv4Inst, NULL, NULL, NULL, tIPv4Params, NULL, BBFDM_BOTH},
+{"IPv6Address", &DMWRITE, add_ipv6, delete_ipv6, NULL, browseIfaceIPv6Inst, NULL, NULL, NULL, tIPv6Params, NULL, BBFDM_BOTH},
+{"IPv6Prefix", &DMWRITE, add_ipv6_prefix, delete_ipv6_prefix, NULL, browseIfaceIPv6PrefixInst, NULL, NULL, NULL, tIPv6PrefixParams, get_linker_ipv6_prefix, BBFDM_BOTH},
+{"Stats", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIPInterfaceStatsParams, NULL, BBFDM_BOTH},
+{"TWAMPReflector", &DMWRITE, addObjIPInterfaceTWAMPReflector, delObjIPInterfaceTWAMPReflector, NULL, browseIPInterfaceTWAMPReflectorInst, NULL, NULL, NULL, tIPInterfaceTWAMPReflectorParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tIPintParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_IPInterface_Enable, set_IPInterface_Enable, NULL, NULL, BBFDM_BOTH},
+{"IPv4Enable", &DMWRITE, DMT_BOOL, get_IPInterface_IPv4Enable, set_IPInterface_IPv4Enable, NULL, NULL, BBFDM_BOTH},
+{"IPv6Enable", &DMWRITE, DMT_BOOL, get_IPInterface_IPv6Enable, set_IPInterface_IPv6Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_IPInterface_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_IPInterface_Alias, set_IPInterface_Alias, NULL, NULL, BBFDM_BOTH},
+{"Name", &DMREAD, DMT_STRING, get_IPInterface_Name, NULL, NULL, NULL, BBFDM_BOTH},
+{"LastChange", &DMREAD, DMT_UNINT, get_IPInterface_LastChange, NULL, NULL, NULL, BBFDM_BOTH},
+{"LowerLayers", &DMWRITE, DMT_STRING, get_IPInterface_LowerLayers, set_IPInterface_LowerLayers, NULL, NULL, BBFDM_BOTH},
+{"Router", &DMWRITE, DMT_STRING, get_IPInterface_Router, set_IPInterface_Router, NULL, NULL, BBFDM_BOTH},
+{"Reset", &DMWRITE, DMT_BOOL, get_IPInterface_Reset, set_IPInterface_Reset, NULL, NULL, BBFDM_BOTH},
+{"MaxMTUSize", &DMWRITE, DMT_UNINT, get_IPInterface_MaxMTUSize, set_IPInterface_MaxMTUSize, NULL, NULL, BBFDM_BOTH},
+{"Type", &DMREAD, DMT_STRING, get_IPInterface_Type, NULL, NULL, NULL, BBFDM_BOTH},
+{"Loopback", &DMWRITE, DMT_BOOL, get_IPInterface_Loopback, set_IPInterface_Loopback, NULL, NULL, BBFDM_BOTH},
+{"IPv4AddressNumberOfEntries", &DMREAD, DMT_UNINT, get_IPInterface_IPv4AddressNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPv6AddressNumberOfEntries", &DMREAD, DMT_UNINT, get_IPInterface_IPv6AddressNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"IPv6PrefixNumberOfEntries", &DMREAD, DMT_UNINT, get_IPInterface_IPv6PrefixNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{"TWAMPReflectorNumberOfEntries", &DMREAD, DMT_UNINT, get_IPInterface_TWAMPReflectorNumberOfEntries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.IP.Interface.{i}.IPv4Address.{i}. *** */
+DMLEAF tIPv4Params[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_IPInterface_Enable, set_IPInterface_Enable, &IPv4INFRM, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_IPInterface_Status, NULL, &IPv4INFRM, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_ipv4_alias, set_ipv4_alias, &IPv4INFRM, NULL, BBFDM_BOTH},
+{CUSTOM_PREFIX"FirewallEnabled", &DMWRITE, DMT_BOOL, get_firewall_enabled, set_firewall_enabled, &IPv4INFRM, NULL, BBFDM_BOTH},
+{"IPAddress", &DMWRITE, DMT_STRING, get_ipv4_address, set_ipv4_address, &IPv4INFRM, NULL, BBFDM_BOTH},
+{"SubnetMask", &DMWRITE, DMT_STRING, get_ipv4_netmask, set_ipv4_netmask, &IPv4INFRM, NULL, BBFDM_BOTH},
+{"AddressingType", &DMWRITE, DMT_STRING, get_ipv4_addressing_type, set_ipv4_addressing_type, &IPv4INFRM, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.IP.Interface.{i}.IPv6Address.{i}. *** */
+DMLEAF tIPv6Params[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_IPInterfaceIPv6Address_Enable, set_IPInterfaceIPv6Address_Enable, &IPv6INFRM, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_IPInterfaceIPv6Address_Status, NULL, &IPv6INFRM, NULL, BBFDM_BOTH},
+{"IPAddressStatus", &DMREAD, DMT_STRING, get_IPInterfaceIPv6Address_IPAddressStatus, NULL, &IPv6INFRM, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_IPInterfaceIPv6Address_Alias, set_IPInterfaceIPv6Address_Alias, &IPv6INFRM, NULL, BBFDM_BOTH},
+{"IPAddress", &DMWRITE, DMT_STRING, get_IPInterfaceIPv6Address_IPAddress, set_IPInterfaceIPv6Address_IPAddress, &IPv6INFRM, NULL, BBFDM_BOTH},
+{"Origin", &DMREAD, DMT_STRING, get_IPInterfaceIPv6Address_Origin, NULL, &IPv6INFRM, NULL, BBFDM_BOTH},
+{"Prefix", &DMWRITE, DMT_STRING, get_IPInterfaceIPv6Address_Prefix, set_IPInterfaceIPv6Address_Prefix, &IPv6INFRM, NULL, BBFDM_BOTH},
+{"PreferredLifetime", &DMWRITE, DMT_TIME, get_IPInterfaceIPv6Address_PreferredLifetime, set_IPInterfaceIPv6Address_PreferredLifetime, &IPv6INFRM, NULL, BBFDM_BOTH},
+{"ValidLifetime", &DMWRITE, DMT_TIME, get_IPInterfaceIPv6Address_ValidLifetime, set_IPInterfaceIPv6Address_ValidLifetime, &IPv6INFRM, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.IP.Interface.{i}.IPv6Prefix.{i}. *** */
+DMLEAF tIPv6PrefixParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_IPInterfaceIPv6Prefix_Enable, set_IPInterfaceIPv6Prefix_Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_IPInterfaceIPv6Prefix_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"PrefixStatus", &DMREAD, DMT_STRING, get_IPInterfaceIPv6Prefix_PrefixStatus, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_IPInterfaceIPv6Prefix_Alias, set_IPInterfaceIPv6Prefix_Alias, NULL, NULL, BBFDM_BOTH},
+{"Prefix", &DMWRITE, DMT_STRING, get_IPInterfaceIPv6Prefix_Prefix, set_IPInterfaceIPv6Prefix_Prefix, NULL, NULL, BBFDM_BOTH},
+{"Origin", &DMREAD, DMT_STRING, get_IPInterfaceIPv6Prefix_Origin, NULL, NULL, NULL, BBFDM_BOTH},
+{"StaticType", &DMWRITE, DMT_STRING, get_IPInterfaceIPv6Prefix_StaticType, set_IPInterfaceIPv6Prefix_StaticType, NULL, NULL, BBFDM_BOTH},
+{"ParentPrefix", &DMWRITE, DMT_STRING, get_IPInterfaceIPv6Prefix_ParentPrefix, set_IPInterfaceIPv6Prefix_ParentPrefix, NULL, NULL, BBFDM_BOTH},
+{"ChildPrefixBits", &DMWRITE, DMT_STRING, get_IPInterfaceIPv6Prefix_ChildPrefixBits, set_IPInterfaceIPv6Prefix_ChildPrefixBits, NULL, NULL, BBFDM_BOTH},
+{"PreferredLifetime", &DMWRITE, DMT_TIME, get_IPInterfaceIPv6Prefix_PreferredLifetime, set_IPInterfaceIPv6Prefix_PreferredLifetime, NULL, NULL, BBFDM_BOTH},
+{"ValidLifetime", &DMWRITE, DMT_TIME, get_IPInterfaceIPv6Prefix_ValidLifetime, set_IPInterfaceIPv6Prefix_ValidLifetime, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.IP.Interface.{i}.Stats. *** */
+DMLEAF tIPInterfaceStatsParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"BytesSent", &DMREAD, DMT_UNINT, get_ip_interface_statistics_tx_bytes, NULL, NULL, NULL, BBFDM_BOTH},
+{"BytesReceived", &DMREAD, DMT_UNINT, get_ip_interface_statistics_rx_bytes, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsSent", &DMREAD, DMT_UNINT, get_ip_interface_statistics_tx_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"PacketsReceived", &DMREAD, DMT_UNINT, get_ip_interface_statistics_rx_packets, NULL, NULL, NULL, BBFDM_BOTH},
+{"ErrorsSent", &DMREAD, DMT_UNINT, get_ip_interface_statistics_tx_errors, NULL, NULL, NULL, BBFDM_BOTH},
+{"ErrorsReceived", &DMREAD, DMT_UNINT, get_ip_interface_statistics_rx_errors, NULL, NULL, NULL, BBFDM_BOTH},
+{"DiscardPacketsSent", &DMREAD, DMT_UNINT, get_ip_interface_statistics_tx_discardpackets, NULL, NULL, NULL, BBFDM_BOTH},
+{"DiscardPacketsReceived", &DMREAD, DMT_UNINT, get_ip_interface_statistics_rx_discardpackets, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnicastPacketsSent", &DMREAD, DMT_UNINT, get_ip_interface_statistics_tx_unicastpackets, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnicastPacketsReceived", &DMREAD, DMT_UNINT, get_ip_interface_statistics_rx_unicastpackets, NULL, NULL, NULL, BBFDM_BOTH},
+{"MulticastPacketsSent", &DMREAD, DMT_UNINT, get_ip_interface_statistics_tx_multicastpackets, NULL, NULL, NULL, BBFDM_BOTH},
+{"MulticastPacketsReceived", &DMREAD, DMT_UNINT, get_ip_interface_statistics_rx_multicastpackets, NULL, NULL, NULL, BBFDM_BOTH},
+{"BroadcastPacketsSent", &DMREAD, DMT_UNINT, get_ip_interface_statistics_tx_broadcastpackets, NULL, NULL, NULL, BBFDM_BOTH},
+{"BroadcastPacketsReceived", &DMREAD, DMT_UNINT, get_ip_interface_statistics_rx_broadcastpackets, NULL, NULL, NULL, BBFDM_BOTH},
+{"UnknownProtoPacketsReceived", &DMREAD, DMT_UNINT, get_ip_interface_statistics_rx_unknownprotopackets, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.IP.Interface.{i}.TWAMPReflector.{i}. *** */
+DMLEAF tIPInterfaceTWAMPReflectorParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_IPInterfaceTWAMPReflector_Enable, set_IPInterfaceTWAMPReflector_Enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_IPInterfaceTWAMPReflector_Status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_IPInterfaceTWAMPReflector_Alias, set_IPInterfaceTWAMPReflector_Alias, NULL, NULL, BBFDM_BOTH},
+{"Port", &DMWRITE, DMT_UNINT, get_IPInterfaceTWAMPReflector_Port, set_IPInterfaceTWAMPReflector_Port, NULL, NULL, BBFDM_BOTH},
+{"MaximumTTL", &DMWRITE, DMT_UNINT, get_IPInterfaceTWAMPReflector_MaximumTTL, set_IPInterfaceTWAMPReflector_MaximumTTL, NULL, NULL, BBFDM_BOTH},
+{"IPAllowedList", &DMWRITE, DMT_STRING, get_IPInterfaceTWAMPReflector_IPAllowedList, set_IPInterfaceTWAMPReflector_IPAllowedList, NULL, NULL, BBFDM_BOTH},
+{"PortAllowedList", &DMWRITE, DMT_STRING, get_IPInterfaceTWAMPReflector_PortAllowedList, set_IPInterfaceTWAMPReflector_PortAllowedList, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+unsigned char get_ipv4_finform(char *refparam, struct dmctx *dmctx, void *data, char *instance)
+{
+ return 1;
+}
+
+unsigned char get_ipv6_finform(char *refparam, struct dmctx *dmctx, void *data, char *instance)
+{
+ return 1;
+}
+
+/*************************************************************
+ * INIT
+/*************************************************************/
+inline int init_ip_args(struct ip_args *args, struct uci_section *s, char *ip_4address)
+{
+ args->ip_sec = s;
+ args->ip_4address = ip_4address;
+ return 0;
+}
+
+inline int init_ipv6_args(struct ipv6_args *args, struct uci_section *s, char *ip_6address, char *ip_6mask, char *ip_6preferred, char *ip_6valid)
+{
+ args->ip_sec = s;
+ args->ip_6address = ip_6address;
+ args->ip_6mask = ip_6mask;
+ args->ip_6preferred = ip_6preferred;
+ args->ip_6valid = ip_6valid;
+ return 0;
+}
+
+inline int init_ipv6prefix_args(struct ipv6prefix_args *args, struct uci_section *s, char *ip_6prefixaddress, char *ip_6prefixmask, char *ip_6prefixpreferred, char *ip_6prefixvalid)
+{
+ args->ip_sec = s;
+ args->ip_6prefixaddress = ip_6prefixaddress;
+ args->ip_6prefixmask = ip_6prefixmask;
+ args->ip_6prefixpreferred = ip_6prefixpreferred;
+ args->ip_6prefixvalid = ip_6prefixvalid;
+ return 0;
+}
+
+/*************************************************************
+ * COMMON Functions
+/*************************************************************/
+static char *ubus_call_get_value_with_two_objects(char *interface, char *obj1, char *obj2, char *key)
+{
+ json_object *res, *jobj1, *jobj2;
+ char *value = "";
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res);
+ if (res)
+ {
+ jobj1 = dmjson_select_obj_in_array_idx(res, 0, 1, obj1);
+ if(jobj1)
+ jobj2 = dmjson_get_obj(jobj1, 1, obj2);
+ if(jobj2)
+ value = dmjson_get_value(jobj2, 1, key);
+ }
+ return value;
+}
+
+static char *ubus_call_get_value(char *interface, char *obj, char *key)
+{
+ json_object *res, *jobj;
+ char *value = "";
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res);
+ if (res)
+ {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, obj);
+ value = dmjson_get_value(jobj, 1, key);
+ }
+ return value;
+}
+
+static char *get_child_prefix_linker(char *interface)
+{
+ char *address = NULL, *mask = NULL, *value;
+ json_object *res, *jobj, *jobj1, *jobj2;
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res);
+ if(res) {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv6-prefix");
+ if(jobj) {
+ jobj1 = dmjson_get_obj(jobj, 1, "assigned");
+ if(jobj1) {
+ jobj2 = dmjson_get_obj(jobj1, 1, "lan");
+ if(jobj2) {
+ address = dmjson_get_value(jobj2, 1, "address");
+ mask = dmjson_get_value(jobj2, 1, "mask");
+ dmasprintf(&value, "%s/%s", address,mask);
+ return value;
+ }
+ }
+ }
+ }
+ return "";
+}
+
+/*************************************************************
+ * GET & SET PARAM
+/*************************************************************/
+/*
+ * *** Device.IP. ***
+ */
+int get_IP_IPv4Capable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int get_IP_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int set_IP_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_IP_IPv4Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Enabled";
+ return 0;
+}
+
+int get_IP_IPv6Capable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int get_IP_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int set_IP_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_IP_IPv6Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Enabled";
+ return 0;
+}
+
+int get_IP_ULAPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("network", "globals", "ula_prefix", value);
+ return 0;
+}
+
+int set_IP_ULAPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value("network", "globals", "ula_prefix", value);
+ break;
+ }
+ return 0;
+}
+
+int get_IP_InterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_foreach_sections("network", "interface", s) {
+ if (strcmp(section_name(s), "loopback") == 0)
+ continue;
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+/*
+ * *** Device.IP.Interface. ***
+ */
+/*#Device.IP.Interface.{i}.Enable!UCI:network/interface,@i-1/disabled*/
+int get_IPInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+ dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "disabled", &v);
+ *value = (*v != '1') ? "1" : "0";
+ return 0;
+}
+
+int set_IPInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "disabled", (b) ? "0" : "1");
+ break;
+ }
+ return 0;
+}
+
+/*#Device.IP.Interface.{i}.Status!UCI:network/interface,@i-1/disabled*/
+int get_IPInterface_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ char *lan_name = section_name(((struct ip_args *)data)->ip_sec), *val= NULL;
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", lan_name, String}}, 1, &res);
+ val = dmjson_get_value(res, 1, "up");
+ *value = !strcmp(val, "true") ? "Up" : "Down";
+ return 0;
+}
+
+int get_IPInterface_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = dmstrdup(section_name(((struct ip_args *)data)->ip_sec));
+ return 0;
+}
+
+int get_IPInterface_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int set_IPInterface_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+/*#Device.IP.Interface.{i}.IPv6Enable!UCI:network/interface,@i-1/ipv6*/
+int get_IPInterface_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *v;
+ dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "ipv6", &v);
+ *value = (*v != '0') ? "1" : "0";
+ return 0;
+}
+
+int set_IPInterface_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ipv6", (b) ? "" : "0");
+ break;
+ }
+ return 0;
+}
+
+/*#Device.IP.Interface.{i}.LastChange!UBUS:network.interface/status/interface,@Name/uptime*/
+int get_IPInterface_LastChange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res;
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(((struct ip_args *)data)->ip_sec), String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ *value = dmjson_get_value(res, 1, "uptime");
+ return 0;
+}
+
+int get_IPInterface_Router(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Device.Routing.Router.1.";
+ return 0;
+}
+
+int set_IPInterface_Router(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterface_Reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ return 0;
+}
+
+int set_IPInterface_Reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b) {
+ set_interface_enable_ubus(section_name(((struct ip_args *)data)->ip_sec), refparam, ctx, action, "0");
+ set_interface_enable_ubus(section_name(((struct ip_args *)data)->ip_sec), refparam, ctx, action, "1");
+ }
+ break;
+ }
+ return 0;
+}
+
+/*#Device.IP.Interface.{i}.MaxMTUSize!UBUS:network.interface/status/interface,@Name/mtu*/
+int get_IPInterface_MaxMTUSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res, *diag;
+ char *device= NULL;
+
+ dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "mtu", value);
+ if(*value[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(((struct ip_args *)data)->ip_sec), String}}, 1, &res);
+ DM_ASSERT(res, *value = "");
+ device = dmjson_get_value(res, 1, "device");
+ if(device) {
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", device, String}}, 1, &diag);
+ DM_ASSERT(diag, *value = "");
+ *value = dmjson_get_value(diag, 1, "mtu");
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int set_IPInterface_MaxMTUSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "mtu", value);
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterface_Type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ if (strcmp(section_name(((struct ip_args *)data)->ip_sec), "loopback") == 0)
+ *value = "Loopback";
+ else
+ *value = "Normal";
+ return 0;
+}
+
+int get_IPInterface_Loopback(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ if (strcmp(section_name(((struct ip_args *)data)->ip_sec), "loopback") == 0)
+ *value = "1";
+ else
+ *value = "0";
+ return 0;
+}
+
+int set_IPInterface_Loopback(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterface_IPv4AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s;
+ char *inst;
+
+ *value = "0";
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "interface", "section_name", section_name(((struct ip_args *)data)->ip_sec), s) {
+ dmuci_get_value_by_section_string(s, "ipv4_instance", &inst);
+ if(inst[0] != '\0')
+ *value = "1";
+ }
+ return 0;
+}
+
+int get_IPInterface_IPv6AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s;
+ int cnt = 0;
+
+ *value = "0";
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "ipv6", "section_name", section_name(((struct ip_args *)data)->ip_sec), s) {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+int get_IPInterface_IPv6PrefixNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s;
+ int cnt = 0;
+
+ *value = "0";
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "ipv6prefix", "section_name", section_name(((struct ip_args *)data)->ip_sec), s) {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+int get_IPInterface_TWAMPReflectorNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+ uci_foreach_option_eq("cwmp_twamp", "twamp_refector", "interface", section_name(((struct ip_args *)data)->ip_sec), s) {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+/*
+ * *** Device.IP.Interface.{i}.IPv4Address.{i}. ***
+ */
+int get_firewall_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ get_interface_firewall_enabled(section_name(((struct ip_args *)data)->ip_sec), refparam, ctx, value);
+ return 0;
+}
+
+int set_firewall_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ set_interface_firewall_enabled(section_name(((struct ip_args *)data)->ip_sec), refparam, ctx, action, value);
+ return 0;
+}
+
+/*#Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress!UCI:network/interface,@i-1/ipaddr*/
+int get_ipv4_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ((struct ip_args *)data)->ip_4address;
+ return 0;
+}
+
+int set_ipv4_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *proto;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "proto", &proto);
+ if(strcmp(proto, "static") == 0)
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ipaddr", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.IP.Interface.{i}.IPv4Address.{i}.SubnetMask!UCI:network/interface,@i-1/netmask*/
+int get_ipv4_netmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ json_object *res, *jobj;
+ char *mask;
+
+ dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "netmask", &mask);
+ if (mask[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(((struct ip_args *)data)->ip_sec), String}}, 1, &res);
+ if (res) {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ mask = dmjson_get_value(jobj, 1, "mask");
+ if (mask[0] == '\0')
+ return 0;
+ mask = cidr2netmask(atoi(mask));
+ }
+ }
+ *value = mask;
+ return 0;
+}
+
+int set_ipv4_netmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *proto;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "proto", &proto);
+ if(strcmp(proto, "static") == 0)
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "netmask", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.IP.Interface.{i}.IPv4Address.{i}.AddressingType!UCI:network/interface,@i-1/proto*/
+int get_ipv4_addressing_type (char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "proto", value);
+ if (strcmp(*value, "static") == 0)
+ *value = "Static";
+ else if (strcmp(*value, "dhcp") == 0)
+ *value = "DHCP";
+ else
+ *value = "";
+ return 0;
+}
+
+int set_ipv4_addressing_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *proto;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if(strcasecmp(value, "static") == 0) {
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "proto", "static");
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ipaddr", "0.0.0.0");
+ }
+ if(strcasecmp(value, "dhcp") == 0) {
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "proto", "dhcp");
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ipaddr", "");
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+ char linker[64] = "", *proto, *device, *mac;
+
+ dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "proto", &proto);
+ if (strstr(proto, "ppp")) {
+ sprintf(linker, "%s", section_name(((struct ip_args *)data)->ip_sec));
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cPPP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
+ goto end;
+ }
+
+ device = get_device(section_name(((struct ip_args *)data)->ip_sec));
+ if (device[0] != '\0') {
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cVLANTermination%c", dmroot, dm_delim, dm_delim, dm_delim), device, value);
+ if (*value != NULL)
+ return 0;
+ }
+
+ mac = get_macaddr(section_name(((struct ip_args *)data)->ip_sec));
+ if (mac[0] != '\0') {
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), mac, value);
+ goto end;
+ }
+
+end :
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+int set_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *linker = NULL, *newvalue = NULL;
+ struct uci_section *s;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (value[strlen(value)-1]!='.') {
+ dmasprintf(&newvalue, "%s.", value);
+ adm_entry_get_linker_value(ctx, newvalue, &linker);
+ } else
+ adm_entry_get_linker_value(ctx, value, &linker);
+
+ if (linker)
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ifname", linker);
+ else
+ return FAULT_9005;
+
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * *** Device.IP.Interface.{i}.IPv6Address.{i}. ***
+ */
+/*#Device.IP.Interface.{i}.IPv6Address.{i}.IPAddress!UCI:network/interface,@i-1/ip6addr*/
+int get_IPInterfaceIPv6Address_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ((struct ipv6_args *)data)->ip_6address;
+ if(((struct ipv6_args *)data)->ip_6mask[0] != '\0')
+ dmasprintf(value, "%s/%s", ((struct ipv6_args *)data)->ip_6address, ((struct ipv6_args *)data)->ip_6mask);
+ return 0;
+}
+
+int set_IPInterfaceIPv6Address_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *proto;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(((struct ipv6_args *)data)->ip_sec, "proto", &proto);
+ if(strcmp(proto, "static") == 0)
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ip6addr", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Address_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int set_IPInterfaceIPv6Address_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Address_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Enabled";
+ return 0;
+}
+
+int get_IPInterfaceIPv6Address_IPAddressStatus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ if(((struct ipv6_args *)data)->ip_6valid[0] != '\0')
+ *value = "Preferred";
+ else
+ *value = "Unknown";
+ return 0;
+}
+
+int get_IPInterfaceIPv6Address_Origin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ubus_call_get_value_with_two_objects(section_name(((struct ipv6_args *)data)->ip_sec), "ipv6-prefix-assignment", "local-address", "address");
+ if(*value[0] != '\0')
+ *value = "AutoConfigured";
+ else {
+ dmuci_get_value_by_section_string(((struct ipv6_args *)data)->ip_sec, "proto", value);
+ if (strcmp(*value, "static") == 0)
+ *value = "Static";
+ else if (strcmp(*value, "dhcpv6") == 0)
+ *value = "DHCPv6";
+ else
+ *value = "WellKnown";
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Address_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+ char *inst;
+
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct ipv6_args *)data)->ip_sec), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "ip_int_instance", &inst);
+
+ *value = "";
+ if(((struct ipv6prefix_args *)data)->ip_6prefixaddress[0] != '\0')
+ dmasprintf(value, "Device.IP.Interface.%s.IPv6Prefix.1.", inst);
+ return 0;
+}
+
+int set_IPInterfaceIPv6Address_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+/*#Device.IP.Interface.{i}.IPv6Address.{i}.PreferredLifetime!UCI:network/interface,@i-1/adv_preferred_lifetime*/
+int get_IPInterfaceIPv6Address_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char local_time[32] = {0};
+ char *preferred = ((struct ipv6_args *)data)->ip_6preferred;
+ *value = "0001-01-01T00:00:00Z";
+ if (get_shift_time_time(atoi(preferred), local_time, sizeof(local_time)) == -1)
+ return 0;
+ *value = dmstrdup(local_time);
+ return 0;
+}
+
+int set_IPInterfaceIPv6Address_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char buf[32] = "", *proto;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(((struct ipv6_args *)data)->ip_sec, "proto", &proto);
+ if(strcasecmp(proto, "static") == 0) {
+ get_shift_time_shift(value, buf);
+ if (!(*buf))
+ return 0;
+ dmuci_set_value_by_section(((struct ipv6_args *)data)->ip_sec, "adv_preferred_lifetime", buf);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.IP.Interface.{i}.IPv6Address.{i}.ValidLifetime!UCI:network/interface,@i-1/adv_valid_lifetime*/
+int get_IPInterfaceIPv6Address_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char local_time[32] = {0};
+ char *preferred = ((struct ipv6_args *)data)->ip_6valid;
+ *value = "0001-01-01T00:00:00Z";
+ if (get_shift_time_time(atoi(preferred), local_time, sizeof(local_time)) == -1)
+ return 0;
+ *value = dmstrdup(local_time);
+ return 0;
+}
+
+int set_IPInterfaceIPv6Address_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char buf[32] = "", *proto;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(((struct ipv6_args *)data)->ip_sec, "proto", &proto);
+ if(strcasecmp(proto, "static") == 0) {
+ get_shift_time_shift(value, buf);
+ if (!(*buf))
+ return 0;
+ dmuci_set_value_by_section(((struct ipv6_args *)data)->ip_sec, "adv_valid_lifetime", buf);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * *** Device.IP.Interface.{i}.IPv6Prefix.{i}. ***
+ */
+int get_IPInterfaceIPv6Prefix_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "1";
+ return 0;
+}
+
+int set_IPInterfaceIPv6Prefix_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Prefix_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Enabled";
+ return 0;
+}
+
+int get_IPInterfaceIPv6Prefix_PrefixStatus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ if(((struct ipv6prefix_args *)data)->ip_6prefixvalid[0] != '\0')
+ *value = "Preferred";
+ else
+ *value = "Unknown";
+ return 0;
+}
+
+/*#Device.IP.Interface.{i}.IPv6Prefix.{i}.Prefix!UCI:network/interface,@i-1/ip6prefix*/
+int get_IPInterfaceIPv6Prefix_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ((struct ipv6prefix_args *)data)->ip_6prefixaddress;
+ if(((struct ipv6prefix_args *)data)->ip_6prefixmask[0] != '\0')
+ dmasprintf(value, "%s/%s", ((struct ipv6prefix_args *)data)->ip_6prefixaddress, ((struct ipv6prefix_args *)data)->ip_6prefixmask);
+ return 0;
+}
+
+int set_IPInterfaceIPv6Prefix_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *proto;
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string(((struct ipv6prefix_args *)data)->ip_sec, "proto", &proto);
+ if(strcmp(proto, "static") == 0)
+ dmuci_set_value_by_section(((struct ipv6prefix_args *)data)->ip_sec, "ip6prefix", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Prefix_Origin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = ubus_call_get_value(section_name(((struct ipv6prefix_args *)data)->ip_sec), "ipv6-prefix-assignment", "address");
+ if(*value[0] != '\0')
+ *value = "AutoConfigured";
+ else {
+ dmuci_get_value_by_section_string(((struct ipv6prefix_args *)data)->ip_sec, "proto", value);
+ if (strcmp(*value, "static") == 0)
+ *value = "Static";
+ else if (strcmp(*value, "dhcpv6") == 0)
+ *value = "DHCPv6";
+ else
+ *value = "WellKnown";
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Prefix_StaticType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "Static";
+ return 0;
+}
+
+int set_IPInterfaceIPv6Prefix_StaticType(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Prefix_ParentPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *linker;
+ dmasprintf(&linker, "%s/%s", ((struct ipv6prefix_args *)data)->ip_6prefixaddress, ((struct ipv6prefix_args *)data)->ip_6prefixmask);
+ if(linker[0] != '\0')
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%Interface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
+ if (*value == NULL)
+ *value = "";
+ return 0;
+}
+
+int set_IPInterfaceIPv6Prefix_ParentPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Prefix_ChildPrefixBits(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_child_prefix_linker(section_name(((struct ipv6prefix_args *)data)->ip_sec));
+ return 0;
+}
+
+int set_IPInterfaceIPv6Prefix_ChildPrefixBits(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Prefix_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char local_time[32] = {0};
+ char *preferred = ((struct ipv6prefix_args *)data)->ip_6prefixpreferred;
+ *value = "0001-01-01T00:00:00Z";
+ if (get_shift_time_time(atoi(preferred), local_time, sizeof(local_time)) == -1)
+ return 0;
+ *value = dmstrdup(local_time);
+ return 0;
+}
+
+int set_IPInterfaceIPv6Prefix_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Prefix_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char local_time[32] = {0};
+ char *preferred = ((struct ipv6prefix_args *)data)->ip_6prefixvalid;
+ *value = "0001-01-01T00:00:00Z";
+ if (get_shift_time_time(atoi(preferred), local_time, sizeof(local_time)) == -1)
+ return 0;
+ *value = dmstrdup(local_time);
+ return 0;
+}
+
+int set_IPInterfaceIPv6Prefix_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ break;
+ }
+ return 0;
+}
+
+/*
+ * *** Device.IP.Interface.{i}.Stats. ***
+ */
+static char *get_ip_interface_statistics(char *interface, char *key)
+{
+ json_object *res, *diag;
+ char *device, *value = "0";
+
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res);
+ device = dmjson_get_value(res, 1, "device");
+ if(device[0] != '\0') {
+ dmubus_call("network.device", "status", UBUS_ARGS{{"name", device, String}}, 1, &diag);
+ value = dmjson_get_value(diag, 2, "statistics", key);
+ }
+ return value;
+}
+
+int get_ip_interface_statistics_tx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "tx_bytes");
+ return 0;
+}
+
+int get_ip_interface_statistics_rx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "rx_bytes");
+ return 0;
+}
+
+int get_ip_interface_statistics_tx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "tx_packets");
+ return 0;
+}
+
+int get_ip_interface_statistics_rx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "rx_packets");
+ return 0;
+}
+
+int get_ip_interface_statistics_tx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "tx_errors");
+ return 0;
+}
+
+int get_ip_interface_statistics_rx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "rx_errors");
+ return 0;
+}
+
+int get_ip_interface_statistics_tx_discardpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "tx_dropped");
+ return 0;
+}
+
+int get_ip_interface_statistics_rx_discardpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "rx_dropped");
+ return 0;
+}
+
+int get_ip_interface_statistics_tx_unicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
+ if(device[0] != '\0')
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "TX", "unicast"));
+ return 0;
+}
+
+int get_ip_interface_statistics_rx_unicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
+ if(device[0] != '\0')
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "RX", "unicast"));
+ return 0;
+}
+
+int get_ip_interface_statistics_tx_multicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
+ if(device[0] != '\0')
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "TX", "multicast"));
+ return 0;
+}
+
+int get_ip_interface_statistics_rx_multicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
+ if(device[0] != '\0')
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "RX", "multicast"));
+ return 0;
+}
+
+int get_ip_interface_statistics_tx_broadcastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
+ if(device[0] != '\0')
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "TX", "broadcast"));
+ return 0;
+}
+
+int get_ip_interface_statistics_rx_broadcastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
+ if(device[0] != '\0')
+ dmasprintf(value, "%d", get_stats_from_ifconfig_command(device, "RX", "broadcast"));
+ return 0;
+}
+
+int get_ip_interface_statistics_rx_unknownprotopackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = get_ip_interface_statistics(section_name(((struct ip_args *)data)->ip_sec), "rx_over_errors");
+ return 0;
+}
+
+/*
+ * *** Device.IP.Interface.{i}.TWAMPReflector.{i}. ***
+ */
+int get_IPInterfaceTWAMPReflector_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", value);
+ return 0;
+}
+
+int set_IPInterfaceTWAMPReflector_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ struct uci_section *s;
+ char *type, *interface, *device, *id, *ipv4addr = "";
+ json_object *res, *jobj;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ break;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b) {
+ dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &interface);
+ dmuci_get_value_by_section_string((struct uci_section *)data, "id", &id);
+ dmuci_set_value_by_section((struct uci_section *)data, "enable", "1");
+ dmuci_set_value("cwmp_twamp", "twamp", "id", id);
+ uci_foreach_sections("network", "interface", s) {
+ if(strcmp(section_name(s), interface) != 0)
+ continue;
+ dmuci_get_value_by_section_string(s, "ipaddr", &ipv4addr);
+ break;
+ }
+ if (ipv4addr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res);
+ if (res)
+ {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ ipv4addr = dmjson_get_value(jobj, 1, "address");
+ if (ipv4addr[0] == '\0')
+ dmuci_set_value_by_section((struct uci_section *)data, "ip_version", "6");
+ else
+ dmuci_set_value_by_section((struct uci_section *)data, "ip_version", "4");
+ }
+ }
+ else
+ dmuci_set_value_by_section((struct uci_section *)data, "ip_version", "4");
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res);
+ if (res)
+ {
+ device = dmjson_get_value(res, 1, "device");
+ dmuci_set_value_by_section((struct uci_section *)data, "device", device);
+ }
+ } else {
+ dmuci_set_value_by_section((struct uci_section *)data, "enable", "0");
+ }
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceTWAMPReflector_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *enable;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &enable);
+ if(strcmp(enable, "1")==0)
+ *value = "Active";
+ else
+ *value = "Disabled";
+ return 0;
+}
+
+int get_IPInterfaceTWAMPReflector_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "twamp_alias", value);
+ return 0;
+}
+
+int set_IPInterfaceTWAMPReflector_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "twamp_alias", value);
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceTWAMPReflector_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "port", value);
+ return 0;
+}
+
+int set_IPInterfaceTWAMPReflector_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "port", value);
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceTWAMPReflector_MaximumTTL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "max_ttl", value);
+ return 0;
+}
+
+int set_IPInterfaceTWAMPReflector_MaximumTTL(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "max_ttl", value);
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceTWAMPReflector_IPAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "ip_list", value);
+ return 0;
+}
+
+int set_IPInterfaceTWAMPReflector_IPAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "ip_list", value);
+ break;
+ }
+ return 0;
+}
+
+int get_IPInterfaceTWAMPReflector_PortAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "port_list", value);
+ return 0;
+}
+
+int set_IPInterfaceTWAMPReflector_PortAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "port_list", value);
+ break;
+ }
+ return 0;
+}
+
+/*************************************************************
+ * GET & SET ALIAS
+/*************************************************************/
+int get_IPInterface_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct ip_args *)data)->ip_sec), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "ip_int_alias", value);
+ return 0;
+}
+
+int set_IPInterface_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section =NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct ip_args *)data)->ip_sec), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_set_value_by_section(dmmap_section, "ip_int_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_ipv4_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct ip_args *)data)->ip_sec), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "ipv4_alias", value);
+ return 0;
+}
+
+int set_ipv4_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section =NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct ip_args *)data)->ip_sec), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_set_value_by_section(dmmap_section, "ipv4_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Address_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+ char *name;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "ipv6", "ipv6_instance", instance, dmmap_section) {
+ dmuci_get_value_by_section_string(dmmap_section, "section_name", &name);
+ if(strcmp(name, section_name(((struct ipv6_args *)data)->ip_sec)) == 0)
+ dmuci_get_value_by_section_string(dmmap_section, "ipv6_alias", value);
+ }
+ return 0;
+}
+
+int set_IPInterfaceIPv6Address_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section;
+ char *name;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "ipv6", "ipv6_instance", instance, dmmap_section) {
+ dmuci_get_value_by_section_string(dmmap_section, "section_name", &name);
+ if(strcmp(name, section_name(((struct ipv6_args *)data)->ip_sec)) == 0)
+ break;
+ }
+ dmuci_set_value_by_section(dmmap_section, "ipv6_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_IPInterfaceIPv6Prefix_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+ char *name;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "ipv6prefix", "ipv6prefix_instance", instance, dmmap_section) {
+ dmuci_get_value_by_section_string(dmmap_section, "section_name", &name);
+ if(strcmp(name, section_name(((struct ipv6prefix_args *)data)->ip_sec)) == 0)
+ dmuci_get_value_by_section_string(dmmap_section, "ipv6prefix_alias", value);
+ }
+ return 0;
+}
+
+int set_IPInterfaceIPv6Prefix_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section;
+ char *name;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "ipv6prefix", "ipv6prefix_instance", instance, dmmap_section) {
+ dmuci_get_value_by_section_string(dmmap_section, "section_name", &name);
+ if(strcmp(name, section_name(((struct ipv6prefix_args *)data)->ip_sec)) == 0)
+ break;
+ }
+ dmuci_set_value_by_section(dmmap_section, "ipv6prefix_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*************************************************************
+ * ADD & DEL OBJ
+/*************************************************************/
+char *get_last_instance_cond(char* dmmap_package, char *package, char *section, char *opt_inst, char *opt_cond, char *cond_val, char *opt_filter, char *filter_val, char *refused_interface)
+{
+ struct uci_section *s, *dmmap_section;
+ char *inst = NULL, *val, *val_f;
+ char *type, *ipv4addr = "", *ipv6addr = "", *proto;
+ json_object *res, *jobj;
+
+ uci_foreach_sections(package, section, s) {
+ if (opt_cond) dmuci_get_value_by_section_string(s, opt_cond, &val);
+ if (opt_filter) dmuci_get_value_by_section_string(s, opt_filter, &val_f);
+ if(opt_cond && opt_filter && (strcmp(val, cond_val) == 0 || strcmp(val_f, filter_val) == 0))
+ continue;
+ if (strcmp(section_name(s), refused_interface)==0)
+ continue;
+
+ dmuci_get_value_by_section_string(s, "ipaddr", &ipv4addr);
+ if (ipv4addr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(s), String}}, 1, &res);
+ if (res)
+ {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
+ ipv4addr = dmjson_get_value(jobj, 1, "address");
+ }
+ }
+ dmuci_get_value_by_section_string(s, "ip6addr", &ipv6addr);
+ if (ipv6addr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(s), String}}, 1, &res);
+ if (res)
+ {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv6-address");
+ ipv6addr = dmjson_get_value(jobj, 1, "address");
+ }
+ }
+ dmuci_get_value_by_section_string(s, "proto", &proto);
+ if (ipv4addr[0] == '\0' && ipv6addr[0] == '\0' && strcmp(proto, "dhcp") != 0 && strcmp(proto, "dhcpv6") != 0 && strcmp(val, "bridge") != 0) {
+ continue;
+ }
+ get_dmmap_section_of_config_section(dmmap_package, section, section_name(s), &dmmap_section);
+ inst = update_instance_icwmpd(dmmap_section, inst, opt_inst);
+ }
+ return inst;
+}
+
+int add_ip_interface(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ char *last_inst, *v;
+ char ip_name[32], ib[8];
+ char *p = ip_name;
+ struct uci_section *dmmap_ip_interface, *dmmap_section;
+
+ last_inst = get_last_instance_cond("dmmap_network", "network", "interface", "ip_int_instance", "type", "alias", "proto", "", "loopback");
+ sprintf(ib, "%d", last_inst ? atoi(last_inst)+1 : 1);
+ dmstrappendstr(p, "ip_interface_");
+ dmstrappendstr(p, ib);
+ dmstrappendend(p);
+ dmuci_set_value("network", ip_name, "", "interface");
+ dmuci_set_value("network", ip_name, "proto", "dhcp");
+
+ dmuci_add_section_icwmpd("dmmap_network", "interface", &dmmap_ip_interface, &v);
+ dmuci_set_value_by_section(dmmap_ip_interface, "section_name", ip_name);
+ *instance = update_instance_icwmpd(dmmap_ip_interface, last_inst, "ip_int_instance");
+ return 0;
+}
+
+int delete_ip_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *dmmap_section = NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ dmuci_delete_by_section(((struct ip_args *)data)->ip_sec, NULL, NULL);
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct ip_args *)data)->ip_sec), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_delete_by_section(dmmap_section, NULL, NULL);
+ break;
+ case DEL_ALL:
+ return FAULT_9005;
+ }
+ return 0;
+}
+
+int add_ipv4(char *refparam, struct dmctx *ctx, void *data, char **instancepara)
+{
+ char *instance;
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct ip_args *)data)->ip_sec), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "ipv4_instance", &instance);
+ *instancepara = update_instance_icwmpd(dmmap_section, instance, "ipv4_instance");
+ if(instance[0] == '\0') {
+ dmuci_set_value_by_section(dmmap_section, "ipv4_instance", *instancepara);
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ipaddr", "0.0.0.0");
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "proto", "static");
+ }
+ return 0;
+}
+
+int delete_ipv4(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *dmmap_section;
+
+ switch (del_action) {
+ case DEL_INST:
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ipaddr", "");
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "proto", "");
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct ip_args *)data)->ip_sec), &dmmap_section);
+ if(dmmap_section != NULL)
+ dmuci_set_value_by_section(dmmap_section, "ipv4_instance", "");
+ break;
+ case DEL_ALL:
+ return FAULT_9005;
+ }
+ return 0;
+}
+
+int add_ipv6(char *refparam, struct dmctx *ctx, void *data, char **instancepara)
+{
+ struct uci_section *s, *ss;
+ char *ip, *name, *inst, *curr_inst;
+
+ uci_foreach_sections("network", "interface", s) {
+ if(strcmp(section_name(s), section_name(((struct ipv6_args *)data)->ip_sec)) != 0)
+ continue;
+ dmuci_get_value_by_section_string(s, "ip6addr", &ip);
+ break;
+ }
+ if(ip[0] == '\0') {
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "ipv6", "section_name", section_name(((struct ipv6_args *)data)->ip_sec), s) {
+ dmuci_get_value_by_section_string(s, "ipv6_instance", &inst);
+ }
+ dmasprintf(&curr_inst, "%d", atoi(inst)+1);
+ dmuci_set_value_by_section(((struct ipv6_args *)data)->ip_sec, "ip6addr", "::");
+ dmuci_set_value_by_section(((struct ipv6_args *)data)->ip_sec, "proto", "static");
+ DMUCI_ADD_SECTION(icwmpd, "dmmap_network", "ipv6", &ss, &name);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, ss, "section_name", section_name(((struct ipv6_args *)data)->ip_sec));
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, ss, "ipv6_instance", curr_inst);
+ }
+ return 0;
+}
+
+int delete_ipv6(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_network", "ipv6", section_name(((struct ipv6_args *)data)->ip_sec), &dmmap_section);
+ switch (del_action) {
+ case DEL_INST:
+ dmuci_set_value_by_section(((struct ipv6_args *)data)->ip_sec, "ip6addr", "");
+ dmuci_set_value_by_section(dmmap_section, "ipv6_instance", "");
+ dmuci_set_value_by_section(((struct ipv6_args *)data)->ip_sec, "proto", "");
+ break;
+ case DEL_ALL:
+ return FAULT_9005;
+ }
+ return 0;
+}
+
+int add_ipv6_prefix(char *refparam, struct dmctx *ctx, void *data, char **instancepara)
+{
+ struct uci_section *s, *ss;
+ char *ip, *name, *inst, *curr_inst;
+
+ uci_foreach_sections("network", "interface", s) {
+ if(strcmp(section_name(s), section_name(((struct ipv6prefix_args *)data)->ip_sec)) != 0)
+ continue;
+ dmuci_get_value_by_section_string(s, "ip6prefix", &ip);
+ break;
+ }
+ if(ip[0] == '\0') {
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "ipv6prefix", "section_name", section_name(((struct ipv6prefix_args *)data)->ip_sec), s) {
+ dmuci_get_value_by_section_string(s, "ipv6prefix_instance", &inst);
+ }
+ dmasprintf(&curr_inst, "%d", atoi(inst)+1);
+ dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ip6prefix", "::");
+ dmuci_set_value_by_section(((struct ipv6prefix_args *)data)->ip_sec, "proto", "static");
+ DMUCI_ADD_SECTION(icwmpd, "dmmap_network", "ipv6prefix", &ss, &name);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, ss, "section_name", section_name(((struct ipv6prefix_args *)data)->ip_sec));
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, ss, "ipv6prefix_instance", curr_inst);
+ }
+ return 0;
+}
+
+int delete_ipv6_prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_network", "ipv6prefix", section_name(((struct ipv6prefix_args *)data)->ip_sec), &dmmap_section);
+ switch (del_action) {
+ case DEL_INST:
+ dmuci_set_value_by_section(((struct ipv6prefix_args *)data)->ip_sec, "ip6prefix", "");
+ dmuci_set_value_by_section(dmmap_section, "ipv6prefix_instance", "");
+ dmuci_set_value_by_section(((struct ipv6prefix_args *)data)->ip_sec, "proto", "");
+ break;
+ case DEL_ALL:
+ return FAULT_9005;
+ }
+ return 0;
+}
+
+static char *get_last_instance_with_option(char *package, char *section, char *option, char *val, char *opt_inst)
+{
+ struct uci_section *s;
+ char *inst = NULL;
+
+ uci_foreach_option_eq(package, section, option, val, s) {
+ inst = update_instance(s, inst, opt_inst);
+ }
+ return inst;
+}
+
+static char *get_last_id(char *package, char *section)
+{
+ struct uci_section *s;
+ char *id;
+ int cnt = 0;
+
+ uci_foreach_sections(package, section, s) {
+ cnt++;
+ }
+ dmasprintf(&id, "%d", cnt+1);
+ return id;
+}
+
+int addObjIPInterfaceTWAMPReflector(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ struct uci_section *connection;
+ char *value1, *last_inst, *id;
+
+ last_inst = get_last_instance_with_option("cwmp_twamp", "twamp_refector", "interface", section_name(((struct ip_args *)data)->ip_sec), "twamp_inst");
+ id = get_last_id("cwmp_twamp", "twamp_refector");
+ dmuci_add_section("cwmp_twamp", "twamp_refector", &connection, &value1);
+ dmasprintf(instance, "%d", last_inst?atoi(last_inst)+1:1);
+ dmuci_set_value_by_section(connection, "twamp_inst", *instance);
+ dmuci_set_value_by_section(connection, "id", id);
+ dmuci_set_value_by_section(connection, "enable", "0");
+ dmuci_set_value_by_section(connection, "interface", section_name(((struct ip_args *)data)->ip_sec));
+ dmuci_set_value_by_section(connection, "port", "862");
+ dmuci_set_value_by_section(connection, "max_ttl", "1");
+ return 0;
+}
+
+int delObjIPInterfaceTWAMPReflector(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ int found = 0;
+ struct uci_section *s, *ss = NULL;
+ char *interface;
+ struct uci_section *section = (struct uci_section *)data;
+
+ switch (del_action) {
+ case DEL_INST:
+ dmuci_delete_by_section(section, NULL, NULL);
+ return 0;
+ case DEL_ALL:
+ uci_foreach_sections("cwmp_twamp", "twamp_refector", s) {
+ dmuci_get_value_by_section_string(s, "interface", &interface);
+ if(strcmp(interface, section_name(((struct ip_args *)data)->ip_sec)) != 0)
+ continue;
+ if (found != 0) {
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL) {
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/**************************************************************************
+* LINKER
+***************************************************************************/
+int get_linker_ip_interface(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker) {
+ if(data && ((struct ip_args *)data)->ip_sec) {
+ dmasprintf(linker,"%s", section_name(((struct ip_args *)data)->ip_sec));
+ return 0;
+ } else {
+ *linker = "";
+ return 0;
+ }
+}
+
+int get_linker_ipv6_prefix(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker) {
+ if(((struct ipv6prefix_args *)data)->ip_sec) {
+ dmasprintf(linker,"%s", get_child_prefix_linker(section_name(((struct ipv6prefix_args *)data)->ip_sec)));
+ return 0;
+ } else {
+ *linker = "";
+ return 0;
+ }
+}
+
+/*************************************************************
+ * ENTRY METHOD
+/*************************************************************/
+/*#Device.IP.Interface.{i}.!UCI:network/interface/dmmap_network*/
+int browseIPIfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *ip_int = NULL, *ip_int_last = NULL;
+ char *type, *ipv4addr = "";
+ struct ip_args curr_ip_args = {0};
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap("network", "interface", "dmmap_network", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ dmuci_get_value_by_section_string(p->config_section, "type", &type);
+ if (strcmp(type, "alias") == 0 || strcmp(section_name(p->config_section), "loopback")==0)
+ continue;
+
+ /* IPv4 address */
+ dmuci_get_value_by_section_string(p->config_section, "ipaddr", &ipv4addr);
+ if (ipv4addr[0] == '\0')
+ ipv4addr = ubus_call_get_value(section_name(p->config_section), "ipv4-address", "address");
+
+ init_ip_args(&curr_ip_args, p->config_section, ipv4addr);
+ ip_int = handle_update_instance(1, dmctx, &ip_int_last, update_instance_alias, 3, p->dmmap_section, "ip_int_instance", "ip_int_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_ip_args, ip_int) == DM_STOP)
+ break;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
+
+int browseIfaceIPv4Inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *ipv4_inst = NULL, *ipv4_inst_last = NULL;
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct ip_args *)prev_data)->ip_sec), &dmmap_section);
+ if(((struct ip_args *)prev_data)->ip_4address[0] != '\0') {
+ ipv4_inst = handle_update_instance(2, dmctx, &ipv4_inst_last, update_instance_alias, 3, dmmap_section, "ipv4_instance", "ipv4_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, prev_data, ipv4_inst) == DM_STOP)
+ goto end;
+ }
+end:
+ return 0;
+}
+
+static struct uci_section *update_dmmap_network_ipv6(char *curr_inst, char *section_name)
+{
+ struct uci_section *s = NULL;
+ char *inst, *name;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "ipv6", "section_name", section_name, s) {
+ dmuci_get_value_by_section_string(s, "ipv6_instance", &inst);
+ if(strcmp(curr_inst, inst) == 0)
+ return s;
+ }
+ if (!s) {
+ DMUCI_ADD_SECTION(icwmpd, "dmmap_network", "ipv6", &s, &name);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, "section_name", section_name);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, "ipv6_instance", curr_inst);
+ }
+ return s;
+}
+
+int browseIfaceIPv6Inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s;
+ char *ipv6_int = NULL, *ipv6_int_last = NULL, *ipv6addr = "", *ipv6mask = "", *ipv6_preferred = "", *ipv6_valid = "", buf[4]="";
+ struct ipv6_args curr_ipv6_args = {0};
+ json_object *res, *jobj, *jobj1;
+ int entries = 0;
+
+ if(prev_data && ((struct ip_args *)prev_data)->ip_sec) {
+ dmuci_get_value_by_section_string(((struct ip_args *)prev_data)->ip_sec, "ip6addr", &ipv6addr);
+ dmuci_get_value_by_section_string(((struct ip_args *)prev_data)->ip_sec, "adv_preferred_lifetime", &ipv6_preferred);
+ dmuci_get_value_by_section_string(((struct ip_args *)prev_data)->ip_sec, "adv_valid_lifetime", &ipv6_valid);
+ if (ipv6addr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(((struct ip_args *)prev_data)->ip_sec), String}}, 1, &res);
+ while (res) {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv6-prefix-assignment");
+ if(jobj) {
+ jobj1 = dmjson_get_obj(jobj, 1, "local-address");
+ if(jobj1) {
+ ipv6addr = dmjson_get_value(jobj1, 1, "address");
+ ipv6mask = dmjson_get_value(jobj1, 1, "mask");
+ goto browse;
+ }
+ }
+ jobj = dmjson_select_obj_in_array_idx(res, entries, 1, "ipv6-address");
+ if(jobj) {
+ ipv6addr = dmjson_get_value(jobj, 1, "address");
+ ipv6mask = dmjson_get_value(jobj, 1, "mask");
+ if (ipv6_preferred[0] == '\0')
+ ipv6_preferred = dmjson_get_value(jobj, 1, "preferred");
+ if (ipv6_valid[0] == '\0')
+ ipv6_valid = dmjson_get_value(jobj, 1, "valid");
+ entries++;
+ sprintf(buf, "%d", entries);
+ s = update_dmmap_network_ipv6(buf, section_name(((struct ip_args *)prev_data)->ip_sec));
+ init_ipv6_args(&curr_ipv6_args, ((struct ip_args *)prev_data)->ip_sec, ipv6addr, ipv6mask, ipv6_preferred, ipv6_valid);
+ ipv6_int = handle_update_instance(1, dmctx, &ipv6_int_last, update_instance_alias, 3, s, "ipv6_instance", "ipv6_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_ipv6_args, ipv6_int) == DM_STOP)
+ goto end;
+ } else
+ goto end;
+ }
+ }
+browse:
+ s = update_dmmap_network_ipv6("1", section_name(((struct ip_args *)prev_data)->ip_sec));
+ init_ipv6_args(&curr_ipv6_args, ((struct ip_args *)prev_data)->ip_sec, ipv6addr, ipv6mask, ipv6_preferred, ipv6_valid);
+ ipv6_int = handle_update_instance(1, dmctx, &ipv6_int_last, update_instance_alias, 3, s, "ipv6_instance", "ipv6_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_ipv6_args, ipv6_int) == DM_STOP)
+ goto end;
+ }
+end:
+ return 0;
+}
+
+
+static struct uci_section *update_dmmap_network_ipv6prefix(char *curr_inst, char *section_name)
+{
+ struct uci_section *s = NULL;
+ char *inst, *name;
+
+ uci_path_foreach_option_eq(icwmpd, "dmmap_network", "ipv6prefix", "section_name", section_name, s) {
+ dmuci_get_value_by_section_string(s, "ipv6prefix_instance", &inst);
+ if(strcmp(curr_inst, inst) == 0)
+ return s;
+ }
+ if (!s) {
+ DMUCI_ADD_SECTION(icwmpd, "dmmap_network", "ipv6prefix", &s, &name);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, "section_name", section_name);
+ DMUCI_SET_VALUE_BY_SECTION(icwmpd, s, "ipv6prefix_instance", curr_inst);
+ }
+ return s;
+}
+
+int browseIfaceIPv6PrefixInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s;
+ char *ipv6prefix_int = NULL, *ipv6prefix_int_last = NULL, *ipv6prefixaddr = "", *ipv6prefixmask = "", *ipv6prefix_preferred = "", *ipv6prefix_valid = "", buf[4] = "";
+ struct ipv6prefix_args curr_ipv6prefix_args = {0};
+ json_object *res, *jobj;
+ int entries = 0;
+
+ if(prev_data && ((struct ip_args *)prev_data)->ip_sec) {
+ dmuci_get_value_by_section_string(((struct ip_args *)prev_data)->ip_sec, "ip6prefix", &ipv6prefixaddr);
+ if (ipv6prefixaddr[0] == '\0') {
+ dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(((struct ip_args *)prev_data)->ip_sec), String}}, 1, &res);
+ while (res) {
+ jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv6-prefix-assignment");
+ if(jobj) {
+ ipv6prefixaddr = dmjson_get_value(jobj, 1, "address");
+ ipv6prefixmask = dmjson_get_value(jobj, 1, "mask");
+ ipv6prefix_preferred = dmjson_get_value(jobj, 1, "preferred");
+ ipv6prefix_valid = dmjson_get_value(jobj, 1, "valid");
+ goto browse;
+ }
+ jobj = dmjson_select_obj_in_array_idx(res, entries, 1, "ipv6-prefix");
+ if(jobj) {
+ ipv6prefixaddr = dmjson_get_value(jobj, 1, "address");
+ ipv6prefixmask = dmjson_get_value(jobj, 1, "mask");
+ ipv6prefix_preferred = dmjson_get_value(jobj, 1, "preferred");
+ ipv6prefix_valid = dmjson_get_value(jobj, 1, "valid");
+ entries++;
+ sprintf(buf, "%d", entries);
+ s = update_dmmap_network_ipv6prefix(buf, section_name(((struct ip_args *)prev_data)->ip_sec));
+ init_ipv6prefix_args(&curr_ipv6prefix_args, ((struct ip_args *)prev_data)->ip_sec, ipv6prefixaddr, ipv6prefixmask, ipv6prefix_preferred, ipv6prefix_valid);
+ ipv6prefix_int = handle_update_instance(1, dmctx, &ipv6prefix_int_last, update_instance_alias, 3, s, "ipv6prefix_instance", "ipv6prefix_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_ipv6prefix_args, ipv6prefix_int) == DM_STOP)
+ goto end;
+ } else
+ goto end;
+ }
+ }
+browse:
+ s = update_dmmap_network_ipv6prefix("1", section_name(((struct ip_args *)prev_data)->ip_sec));
+ init_ipv6prefix_args(&curr_ipv6prefix_args, ((struct ip_args *)prev_data)->ip_sec, ipv6prefixaddr, ipv6prefixmask, ipv6prefix_preferred, ipv6prefix_valid);
+ ipv6prefix_int = handle_update_instance(1, dmctx, &ipv6prefix_int_last, update_instance_alias, 3, s, "ipv6prefix_instance", "ipv6prefix_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_ipv6prefix_args, ipv6prefix_int) == DM_STOP)
+ goto end;
+ }
+end:
+ return 0;
+}
+
+int browseIPInterfaceTWAMPReflectorInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ struct uci_section *s = NULL;
+ char *twamp_inst = NULL, *twamp_inst_last = NULL;
+
+ uci_foreach_option_eq("cwmp_twamp", "twamp_refector", "interface", section_name(((struct ip_args *)prev_data)->ip_sec), s)
+ {
+ twamp_inst = handle_update_instance(2, dmctx, &twamp_inst_last, update_instance_alias, 3, (void *)s, "twamp_inst", "twamp_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, twamp_inst) == DM_STOP)
+ break;
+ }
+ return 0;
+}
diff --git a/dmtree/tr181/ip.h b/dmtree/tr181/ip.h
new file mode 100644
index 00000000..f755c329
--- /dev/null
+++ b/dmtree/tr181/ip.h
@@ -0,0 +1,189 @@
+/*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* Copyright (C) 2019 iopsys Software Solutions AB
+* Author: Anis Ellouze
+* Author: Amin Ben Ramdhane
+*
+*/
+
+#ifndef __IP_H
+#define __IP_H
+
+struct ip_args
+{
+ struct uci_section *ip_sec;
+ char *ip_4address;
+};
+
+struct ipv6_args
+{
+ struct uci_section *ip_sec;
+ char *ip_6address;
+ char *ip_6mask;
+ char *ip_6preferred;
+ char *ip_6valid;
+};
+
+struct ipv6prefix_args
+{
+ struct uci_section *ip_sec;
+ char *ip_6prefixaddress;
+ char *ip_6prefixmask;
+ char *ip_6prefixpreferred;
+ char *ip_6prefixvalid;
+};
+
+extern DMOBJ tIPObj[];
+extern DMLEAF tIPParams[];
+extern DMOBJ tInterfaceObj[];
+extern DMLEAF tIPintParams[];
+extern DMLEAF tIPv4Params[];
+extern DMLEAF tIPv6Params[];
+extern DMLEAF tIPv6PrefixParams[];
+extern DMLEAF tIPInterfaceStatsParams[];
+extern DMLEAF tIPInterfaceTWAMPReflectorParams[];
+
+unsigned char get_ipv4_finform(char *refparam, struct dmctx *dmctx, void *data, char *instance);
+unsigned char get_ipv6_finform(char *refparam, struct dmctx *dmctx, void *data, char *instance);
+
+int get_linker_ip_interface(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+int get_linker_ipv6_prefix(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
+
+int browseIPIfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseIfaceIPv4Inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseIfaceIPv6Inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseIfaceIPv6PrefixInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browseIPInterfaceTWAMPReflectorInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int add_ip_interface(char *refparam, struct dmctx *ctx, void *data, char **instancepara);
+int delete_ip_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int add_ipv4(char *refparam, struct dmctx *ctx, void *data, char **instancepara);
+int delete_ipv4(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int add_ipv6(char *refparam, struct dmctx *ctx, void *data, char **instancepara);
+int delete_ipv6(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int add_ipv6_prefix(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delete_ipv6_prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int addObjIPInterfaceTWAMPReflector(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjIPInterfaceTWAMPReflector(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+
+int get_IP_IPv4Capable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IP_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IP_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IP_IPv4Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IP_IPv6Capable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IP_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IP_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IP_IPv6Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IP_ULAPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IP_ULAPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IP_InterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_ipv4_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ipv4_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_firewall_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_firewall_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ipv4_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ipv4_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ipv4_netmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ipv4_netmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_ipv4_addressing_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_ipv4_addressing_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int get_IPInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterface_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterface_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterface_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterface_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterface_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterface_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterface_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterface_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterface_LastChange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterface_Router(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterface_Router(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterface_Reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterface_Reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterface_MaxMTUSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterface_MaxMTUSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterface_Type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterface_Loopback(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterface_Loopback(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterface_IPv4AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterface_IPv6AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterface_IPv6PrefixNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterface_TWAMPReflectorNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_IPInterfaceIPv6Address_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Address_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Address_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterfaceIPv6Address_IPAddressStatus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterfaceIPv6Address_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Address_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Address_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Address_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Address_Origin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterfaceIPv6Address_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Address_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Address_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Address_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Address_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Address_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int get_IPInterfaceIPv6Prefix_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Prefix_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Prefix_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterfaceIPv6Prefix_PrefixStatus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterfaceIPv6Prefix_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Prefix_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Prefix_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Prefix_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Prefix_Origin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterfaceIPv6Prefix_StaticType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Prefix_StaticType(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Prefix_ParentPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Prefix_ParentPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Prefix_ChildPrefixBits(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Prefix_ChildPrefixBits(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Prefix_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Prefix_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceIPv6Prefix_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceIPv6Prefix_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int get_IPInterfaceTWAMPReflector_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceTWAMPReflector_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceTWAMPReflector_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_IPInterfaceTWAMPReflector_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceTWAMPReflector_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceTWAMPReflector_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceTWAMPReflector_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceTWAMPReflector_MaximumTTL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceTWAMPReflector_MaximumTTL(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceTWAMPReflector_IPAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceTWAMPReflector_IPAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_IPInterfaceTWAMPReflector_PortAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_IPInterfaceTWAMPReflector_PortAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int get_ip_interface_statistics_tx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_rx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_tx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_rx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_tx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_rx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_tx_discardpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_rx_discardpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_tx_unicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_rx_unicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_tx_multicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_rx_multicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_tx_broadcastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_rx_broadcastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_ip_interface_statistics_rx_unknownprotopackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+#endif
diff --git a/dmtree/tr181/managementserver.c b/dmtree/tr181/managementserver.c
new file mode 100644
index 00000000..8da4fa9c
--- /dev/null
+++ b/dmtree/tr181/managementserver.c
@@ -0,0 +1,717 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2012-2014 PIVA SOFTWARE (www.pivasoftware.com)
+ * Author: Imen Bhiri
+ * Author: Feten Besbes
+ * Author: Amin Ben Ramdhane
+ */
+
+#include
+#include
+#include
+#include
+#include "dmmem.h"
+#include "dmcwmp.h"
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcommon.h"
+#include "managementserver.h"
+#include "dmjson.h"
+
+#define DEFAULT_ACSURL "http://192.168.1.1:8080/openacs/acs"
+
+/*** ManagementServer. ***/
+DMLEAF tManagementServerParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"URL", &DMWRITE, DMT_STRING, get_management_server_url, set_management_server_url, NULL, NULL, BBFDM_CWMP},
+{"Username", &DMWRITE, DMT_STRING, get_management_server_username, set_management_server_username, NULL, NULL, BBFDM_CWMP},
+{"Password", &DMWRITE, DMT_STRING, get_empty, set_management_server_passwd, NULL, NULL, BBFDM_CWMP},
+{"ParameterKey", &DMREAD, DMT_STRING, get_management_server_key, NULL, &DMFINFRM, &DMNONE, BBFDM_CWMP},
+{"PeriodicInformEnable", &DMWRITE, DMT_BOOL, get_management_server_periodic_inform_enable, set_management_server_periodic_inform_enable, NULL, NULL, BBFDM_CWMP},
+{"PeriodicInformInterval", &DMWRITE, DMT_UNINT, get_management_server_periodic_inform_interval, set_management_server_periodic_inform_interval, NULL, NULL, BBFDM_CWMP},
+{"PeriodicInformTime", &DMWRITE, DMT_TIME, get_management_server_periodic_inform_time, set_management_server_periodic_inform_time, NULL, NULL, BBFDM_CWMP},
+{"ConnectionRequestURL", &DMREAD, DMT_STRING, get_management_server_connection_request_url, NULL, &DMFINFRM, &DMACTIVE, BBFDM_CWMP},
+{"ConnectionRequestUsername", &DMWRITE, DMT_STRING, get_management_server_connection_request_username, set_management_server_connection_request_username, NULL, NULL, BBFDM_CWMP},
+{"ConnectionRequestPassword", &DMWRITE, DMT_STRING, get_empty, set_management_server_connection_request_passwd, NULL, NULL, BBFDM_CWMP},
+{"HTTPCompressionSupported", &DMREAD, DMT_STRING, get_management_server_http_compression_supportted, NULL, NULL, NULL, BBFDM_CWMP},
+{"HTTPCompression", &DMWRITE, DMT_STRING, get_management_server_http_compression, set_management_server_http_compression, NULL, NULL, BBFDM_CWMP},
+{"LightweightNotificationProtocolsSupported", &DMREAD, DMT_STRING, get_lwn_protocol_supported, NULL, NULL, NULL, BBFDM_CWMP},
+{"LightweightNotificationProtocolsUsed", &DMWRITE, DMT_STRING, get_lwn_protocol_used, set_lwn_protocol_used, NULL, NULL, BBFDM_CWMP},
+{"UDPLightweightNotificationHost", &DMWRITE, DMT_STRING, get_lwn_host, set_lwn_host, NULL, NULL, BBFDM_CWMP},
+{"UDPLightweightNotificationPort", &DMWRITE, DMT_UNINT, get_lwn_port, set_lwn_port, NULL, NULL, BBFDM_CWMP},
+{"CWMPRetryMinimumWaitInterval", &DMWRITE, DMT_UNINT, get_management_server_retry_min_wait_interval, set_management_server_retry_min_wait_interval, NULL, NULL, BBFDM_CWMP},
+{"CWMPRetryIntervalMultiplier", &DMWRITE, DMT_UNINT, get_management_server_retry_interval_multiplier, set_management_server_retry_interval_multiplier, NULL, NULL, BBFDM_CWMP},
+{"AliasBasedAddressing", &DMREAD, DMT_BOOL, get_alias_based_addressing, NULL, &DMFINFRM, NULL, BBFDM_CWMP},
+{"InstanceMode", &DMWRITE, DMT_STRING, get_instance_mode, set_instance_mode, NULL, NULL, BBFDM_CWMP},
+{"ConnReqAllowedJabberIDs", &DMWRITE, DMT_STRING, get_management_server_conn_rep_allowed_jabber_id, set_management_server_conn_rep_allowed_jabber_id, NULL, NULL, BBFDM_CWMP},
+{"ConnReqJabberID", &DMREAD, DMT_STRING, get_management_server_conn_req_jabber_id, NULL, &DMFINFRM, &DMACTIVE, BBFDM_CWMP},
+{"ConnReqXMPPConnection", &DMWRITE, DMT_STRING, get_management_server_conn_req_xmpp_connection, set_management_server_conn_req_xmpp_connection, &DMFINFRM, NULL, BBFDM_CWMP},
+{"SupportedConnReqMethods", &DMREAD, DMT_STRING, get_management_server_supported_conn_req_methods, NULL, NULL, NULL, BBFDM_CWMP},
+{"UDPConnectionRequestAddress", &DMREAD, DMT_STRING, get_upd_cr_address, NULL, NULL, &DMACTIVE, BBFDM_CWMP},
+{"STUNEnable", &DMWRITE, DMT_BOOL, get_stun_enable, set_stun_enable, NULL, NULL, BBFDM_CWMP},
+{"STUNServerAddress", &DMWRITE, DMT_STRING, get_stun_server_address, set_stun_server_address, NULL, NULL, BBFDM_CWMP},
+{"STUNServerPort", &DMWRITE, DMT_UNINT, get_stun_server_port, set_stun_server_port, NULL, NULL, BBFDM_CWMP},
+{"STUNUsername", &DMWRITE, DMT_STRING, get_stun_username, set_stun_username, NULL, NULL, BBFDM_CWMP},
+{"STUNPassword", &DMWRITE, DMT_STRING, get_stun_password, set_stun_password, NULL, NULL, BBFDM_CWMP},
+{"STUNMaximumKeepAlivePeriod", &DMWRITE, DMT_INT, get_stun_maximum_keepalive_period, set_stun_maximum_keepalive_period, NULL, NULL, BBFDM_CWMP},
+{"STUNMinimumKeepAlivePeriod", &DMWRITE, DMT_UNINT, get_stun_minimum_keepalive_period, set_stun_minimum_keepalive_period, NULL, NULL, BBFDM_CWMP},
+{"NATDetected", &DMREAD, DMT_BOOL, get_nat_detected, NULL, NULL, NULL, BBFDM_CWMP},
+{0}
+};
+
+/*#Device.ManagementServer.URL!UCI:cwmp/cwmp,acs/url*/
+int get_management_server_url(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ int i = 1;
+ char *dhcp = NULL, *pch = NULL, *spch = NULL;
+ char *url = NULL;
+ char *provisioning_value = NULL;
+ char package[64] = "", section[64] = "", option[64] = "";
+
+ dmuci_get_option_value_string("cwmp", "acs", "dhcp_discovery", &dhcp);
+ dmuci_get_option_value_string("cwmp", "acs", "url", &url);
+ dmuci_get_varstate_string("cwmp", "acs", "dhcp_url", &provisioning_value);
+
+ if ( ((dhcp && strcmp(dhcp, "enable") == 0 ) || ((url == NULL) || (url[0] == '\0'))) && ((provisioning_value != NULL) && (provisioning_value[0] != '\0')) )
+ {
+ *value = provisioning_value;
+ }
+ else if ((url != NULL) && (url[0] != '\0'))
+ *value = url;
+ else
+ *value = dmstrdup(DEFAULT_ACSURL);
+ return 0;
+}
+
+int set_management_server_url(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp", "acs", "dhcp_discovery", "disable");
+ dmuci_set_value("cwmp", "acs", "url", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.Username!UCI:cwmp/cwmp,acs/userid*/
+int get_management_server_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "acs", "userid", value);
+ return 0;
+}
+
+int set_management_server_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp", "acs", "userid", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.Password!UCI:cwmp/cwmp,acs/passwd*/
+int set_management_server_passwd(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp", "acs", "passwd", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.ParameterKey!UCI:cwmp/cwmp,acs/ParameterKey*/
+int get_management_server_key(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "acs", "ParameterKey", value);
+ return 0;
+}
+
+/*#Device.ManagementServer.PeriodicInformEnable!UCI:cwmp/cwmp,acs/periodic_inform_enable*/
+int get_management_server_periodic_inform_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "acs", "periodic_inform_enable", value);
+ return 0;
+}
+
+int set_management_server_periodic_inform_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if (b)
+ dmuci_set_value("cwmp", "acs", "periodic_inform_enable", "1");
+ else
+ dmuci_set_value("cwmp", "acs", "periodic_inform_enable", "0");
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.PeriodicInformInterval!UCI:cwmp/cwmp,acs/periodic_inform_interval*/
+int get_management_server_periodic_inform_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "acs", "periodic_inform_interval", value);
+ return 0;
+}
+
+int set_management_server_periodic_inform_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp", "acs", "periodic_inform_interval", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.PeriodicInformTime!UCI:cwmp/cwmp,acs/periodic_inform_time*/
+int get_management_server_periodic_inform_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ time_t time_value;
+
+ dmuci_get_option_value_string("cwmp", "acs", "periodic_inform_time", value);
+ if ((*value)[0] != '0' && (*value)[0] != '\0') {
+ time_value = atoi(*value);
+ char s_now[sizeof "AAAA-MM-JJTHH:MM:SS.000Z"];
+ strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S.000Z", localtime(&time_value));
+ *value = dmstrdup(s_now); // MEM WILL BE FREED IN DMMEMCLEAN
+ }
+ else {
+ *value = "0001-01-01T00:00:00Z";
+ }
+ return 0;
+}
+
+int set_management_server_periodic_inform_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct tm tm;
+ char *p, buf[16];
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (!(strptime(value, "%Y-%m-%dT%H:%M:%S", &tm))) {
+ return 0;
+ }
+ sprintf(buf, "%ld", mktime(&tm));
+ dmuci_set_value("cwmp", "acs", "periodic_inform_time", buf);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.ConnectionRequestURL!UCI:cwmp/cwmp,cpe/port*/
+int get_management_server_connection_request_url(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *ip, *port, *iface;
+
+ *value = "";
+ dmuci_get_option_value_string("cwmp", "cpe", "default_wan_interface", &iface);
+ network_get_ipaddr(&ip, iface);
+ dmuci_get_option_value_string("cwmp", "cpe", "port", &port);
+ if (ip[0] != '\0' && port[0] != '\0') {
+ char buf[64];
+ sprintf(buf,"http://%s:%s/", ip, port);
+ *value = dmstrdup(buf); // MEM WILL BE FREED IN DMMEMCLEAN
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.ConnectionRequestUsername!UCI:cwmp/cwmp,cpe/userid*/
+int get_management_server_connection_request_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "cpe", "userid", value);
+ return 0;
+}
+
+int set_management_server_connection_request_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp", "cpe", "userid", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.ConnectionRequestPassword!UCI:cwmp/cwmp,cpe/passwd*/
+int set_management_server_connection_request_passwd(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp", "cpe", "passwd", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+int get_lwn_protocol_supported(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "UDP";
+ return 0;
+}
+
+/*#Device.ManagementServer.LightweightNotificationProtocolsUsed!UCI:cwmp/cwmp,lwn/enable*/
+int get_lwn_protocol_used(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ bool b;
+ char *tmp;
+
+ dmuci_get_option_value_string("cwmp", "lwn", "enable", &tmp);
+ string_to_bool(tmp, &b);
+ if (b)
+ *value = "UDP";
+ else
+ *value = "";
+ return 0;
+}
+
+int set_lwn_protocol_used(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (strcmp(value,"UDP") ==0) {
+ dmuci_set_value("cwmp", "lwn", "enable", "1");
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ }
+ else {
+ dmuci_set_value("cwmp", "lwn", "enable", "0");
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.UDPLightweightNotificationHost!UCI:cwmp/cwmp,lwn/hostname*/
+int get_lwn_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "lwn", "hostname", value);
+ return 0;
+}
+
+int set_lwn_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp", "lwn", "hostname", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.UDPLightweightNotificationPort!UCI:cwmp/cwmp,lwn/port*/
+int get_lwn_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "lwn", "port", value);
+ return 0;
+}
+
+int set_lwn_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp", "lwn", "port", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+int get_management_server_http_compression_supportted(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "GZIP,Deflate";
+ return 0;
+}
+
+/*#Device.ManagementServer.HTTPCompression!UCI:cwmp/cwmp,acs/compression*/
+int get_management_server_http_compression(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "acs", "compression", value);
+ return 0;
+}
+
+int set_management_server_http_compression(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ if (0 == strcasecmp(value, "gzip") || 0 == strcasecmp(value, "deflate") || 0 == strncasecmp(value, "disable", 7)) {
+ return 0;
+ }
+ return FAULT_9007;
+ case VALUESET:
+ dmuci_set_value("cwmp", "acs", "compression", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.CWMPRetryMinimumWaitInterval!UCI:cwmp/cwmp,acs/retry_min_wait_interval*/
+int get_management_server_retry_min_wait_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "acs", "retry_min_wait_interval", value);
+ return 0;
+}
+
+int set_management_server_retry_min_wait_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ int a;
+ switch (action) {
+ case VALUECHECK:
+ a = atoi(value);
+ if (a <= 65535 && a >= 1) {
+ return 0;
+ }
+ return FAULT_9007;
+ case VALUESET:
+ dmuci_set_value("cwmp", "acs", "retry_min_wait_interval", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.CWMPRetryIntervalMultiplier!UCI:cwmp/cwmp,acs/retry_interval_multiplier*/
+int get_management_server_retry_interval_multiplier(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "acs", "retry_interval_multiplier", value);
+ return 0;
+}
+
+int set_management_server_retry_interval_multiplier(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ int a;
+ switch (action) {
+ case VALUECHECK:
+ a = atoi(value);
+ if (a <= 65535 && a >= 1000) {
+ return 0;
+ }
+ return FAULT_9007;
+ case VALUESET:
+ dmuci_set_value("cwmp", "acs", "retry_interval_multiplier", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.AliasBasedAddressing!UCI:cwmp/cwmp,cpe/amd_version*/
+int get_alias_based_addressing(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "cpe", "amd_version", value);
+ if((*value)[0] == '\0'|| atoi(*value) <= AMD_4) {
+ *value = "false";
+ }
+ else {
+ *value = "true";
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.InstanceMode!UCI:cwmp/cwmp,cpe/instance_mode*/
+int get_instance_mode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp", "cpe", "instance_mode", value);
+ return 0;
+}
+
+int set_instance_mode(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ if (0 == strcmp(value, "InstanceNumber") || 0 == strcmp(value, "InstanceAlias") ) {
+ return 0;
+ }
+ return FAULT_9007;
+ case VALUESET:
+ dmuci_set_value("cwmp", "cpe", "instance_mode", value);
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * STUN parameters
+ */
+/*#Device.ManagementServer.UDPConnectionRequestAddress!UCI:cwmp_stun/stun,stun/crudp_address*/
+int get_upd_cr_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ dmuci_get_varstate_string("cwmp_stun", "stun", "crudp_address", value);
+ return 0;
+}
+
+int get_stun_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ char *path = "/etc/rc.d/*icwmp_stund";
+ if (check_file(path))
+ *value = "1";
+ else
+ *value = "0";
+ return 0;
+}
+
+int set_stun_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ bool b;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ if(b) {
+ DMCMD("/etc/rc.common", 2, "/etc/init.d/icwmp_stund", "enable");
+ DMCMD("/etc/rc.common", 2, "/etc/init.d/icwmp_stund", "start");
+ }
+ else {
+ DMCMD("/etc/rc.common", 2, "/etc/init.d/icwmp_stund", "disable");
+ DMCMD("/etc/rc.common", 2, "/etc/init.d/icwmp_stund", "stop");
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.STUNServerAddress!UCI:cwmp_stun/stun,stun/server_address*/
+int get_stun_server_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ dmuci_get_option_value_string("cwmp_stun", "stun", "server_address", value);
+ return 0;
+}
+
+int set_stun_server_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp_stun", "stun", "server_address", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.STUNServerPort!UCI:cwmp_stun/stun,stun/server_port*/
+int get_stun_server_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ dmuci_get_option_value_string("cwmp_stun", "stun", "server_port", value);
+ return 0;
+}
+
+int set_stun_server_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp_stun", "stun", "server_port", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.STUNUsername!UCI:cwmp_stun/stun,stun/username*/
+int get_stun_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ dmuci_get_option_value_string("cwmp_stun", "stun", "username", value);
+ return 0;
+}
+
+int set_stun_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp_stun", "stun", "username", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.STUNPassword!UCI:cwmp_stun/stun,stun/password*/
+int get_stun_password(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ dmuci_get_option_value_string("cwmp_stun", "stun", "password", value);
+ return 0;
+}
+
+int set_stun_password(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp_stun", "stun", "password", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.STUNMaximumKeepAlivePeriod!UCI:cwmp_stun/stun,stun/max_keepalive*/
+int get_stun_maximum_keepalive_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ dmuci_get_option_value_string("cwmp_stun", "stun", "max_keepalive", value);
+ return 0;
+}
+
+int set_stun_maximum_keepalive_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp_stun", "stun", "max_keepalive", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.STUNMinimumKeepAlivePeriod!UCI:cwmp_stun/stun,stun/min_keepalive*/
+int get_stun_minimum_keepalive_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ dmuci_get_option_value_string("cwmp_stun", "stun", "min_keepalive", value);
+ return 0;
+}
+
+int set_stun_minimum_keepalive_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action){
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp_stun", "stun", "min_keepalive", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.ManagementServer.NATDetected!UCI:cwmp_stun/stun,stun/nat_detected*/
+int get_nat_detected(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value){
+ char *path = "/etc/rc.d/*icwmp_stund";
+ char *v;
+
+ if (check_file(path)) { //stun is enabled
+ dmuci_get_varstate_string("cwmp_stun", "stun", "nat_detected", &v);
+ *value = (*v == '1') ? "true" : "false";
+ }
+ else {
+ *value = "false";
+ }
+
+ return 0;
+}
+
+
+/*
+ * XMPP parameters
+ */
+/*#Device.ManagementServer.ConnReqAllowedJabberIDs!UCI:cwmp_xmpp/cwmp,xmpp/allowed_jid*/
+int get_management_server_conn_rep_allowed_jabber_id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_option_value_string("cwmp_xmpp", "xmpp", "allowed_jid", value);
+ return 0;
+}
+
+int set_management_server_conn_rep_allowed_jabber_id(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value("cwmp_xmpp", "xmpp", "allowed_jid", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_management_server_conn_req_jabber_id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s;
+ char *username, *domain, *resource, *tmpPtr, *strResponse = "";
+ *value = "";
+
+ uci_foreach_sections("cwmp_xmpp", "xmpp_connection", s) {
+ dmuci_get_value_by_section_string(s, "username", &username);
+ dmuci_get_value_by_section_string(s, "domain", &domain);
+ dmuci_get_value_by_section_string(s, "resource", &resource);
+ if(*username != '\0' || *domain != '\0' || *resource != '\0') {
+ if(*strResponse == '\0')
+ dmasprintf(&strResponse, "%s@%s/%s", username, domain, resource);
+ else {
+ tmpPtr = dmstrdup(strResponse);
+ dmasprintf(&strResponse, "%s, %s@%s/%s", tmpPtr, username, domain, resource);
+ }
+ }
+ }
+ *value = dmstrdup(strResponse);
+ return 0;
+}
+
+int get_management_server_conn_req_xmpp_connection(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *id;
+
+ dmuci_get_option_value_string("cwmp_xmpp", "xmpp", "id", &id);
+ dmasprintf(value, "Device.XMPP.Connection.%s", id);
+ return 0;
+}
+
+int set_management_server_conn_req_xmpp_connection(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *str, *connection_instance;
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ if (str = strstr(value, "Device.XMPP.Connection.")) {
+ value = dmstrdup(str + sizeof("Device.XMPP.Connection.") - 1); //MEM WILL BE FREED IN DMMEMCLEAN
+ }
+ uci_foreach_sections("cwmp_xmpp", "xmpp_connection", s) {
+ dmuci_get_value_by_section_string(s, "connection_instance", &connection_instance);
+ if(strcmp(value, connection_instance) == 0) {
+ dmuci_set_value("cwmp_xmpp", "xmpp", "id", value);
+ break;
+ }
+ }
+ cwmp_set_end_session(END_SESSION_RELOAD);
+ return 0;
+ }
+ return 0;
+}
+
+int get_management_server_supported_conn_req_methods(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "HTTP,XMPP,STUN";
+ return 0;
+}
diff --git a/dmtree/tr181/managementserver.h b/dmtree/tr181/managementserver.h
new file mode 100644
index 00000000..ddc427aa
--- /dev/null
+++ b/dmtree/tr181/managementserver.h
@@ -0,0 +1,79 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2012-2014 PIVA SOFTWARE (www.pivasoftware.com)
+ * Author: Imen Bhiri
+ * Author: Feten Besbes
+ */
+
+#ifndef __MANAGEMENT_SERVER_H
+#define __MANAGEMENT_SERVER_H
+#include "dmcwmp.h"
+extern DMLEAF tManagementServerParams[];
+
+int get_management_server_url(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_empty(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_key(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_periodic_inform_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_periodic_inform_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_periodic_inform_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_connection_request_url(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_connection_request_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_http_compression_supportted(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_http_compression(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_lwn_protocol_supported(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_lwn_protocol_used(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_lwn_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_lwn_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_retry_min_wait_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_retry_interval_multiplier(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_alias_based_addressing(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_instance_mode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_conn_rep_allowed_jabber_id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_conn_req_jabber_id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_conn_req_xmpp_connection(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_management_server_supported_conn_req_methods(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_upd_cr_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_upd_cr_address_notification_limit(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_stun_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_stun_server_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_stun_server_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_stun_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_stun_password(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_stun_maximum_keepalive_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_stun_minimum_keepalive_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nat_detected(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int set_management_server_url(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_passwd(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_periodic_inform_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_periodic_inform_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_periodic_inform_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_connection_request_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_connection_request_passwd(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_http_compression(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_lwn_protocol_used(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_lwn_protocol_used(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_lwn_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_lwn_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_retry_min_wait_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_retry_interval_multiplier(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_instance_mode(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_conn_rep_allowed_jabber_id(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_management_server_conn_req_xmpp_connection(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int set_upd_cr_address_notification_limit(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_stun_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_stun_server_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_stun_server_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_stun_username(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_stun_password(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_stun_maximum_keepalive_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int set_stun_minimum_keepalive_period(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+#endif
diff --git a/dmtree/tr181/nat.c b/dmtree/tr181/nat.c
new file mode 100644
index 00000000..2207a7ed
--- /dev/null
+++ b/dmtree/tr181/nat.c
@@ -0,0 +1,686 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB
+ * Author: Anis Ellouze
+ * Author: Amin Ben Ramdhane
+ *
+ */
+
+#include
+#include
+#include
+#include "dmuci.h"
+#include "dmubus.h"
+#include "dmcwmp.h"
+#include "dmcommon.h"
+#include "dmentry.h"
+#include "nat.h"
+
+/* *** Device.NAT. *** */
+DMOBJ tNATObj[] = {
+/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextobj, leaf, linker, bbfdm_type*/
+{"InterfaceSetting", &DMWRITE, add_NAT_InterfaceSetting, delete_NAT_InterfaceSetting, NULL, browseInterfaceSettingInst, NULL, NULL, NULL, tNATInterfaceSettingParams, NULL, BBFDM_BOTH},
+{"PortMapping", &DMWRITE, add_NAT_PortMapping, delete_NAT_PortMapping, NULL, browsePortMappingInst, NULL, NULL, NULL, tNATPortMappingParams, NULL, BBFDM_BOTH},
+{0}
+};
+
+DMLEAF tNATParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"InterfaceSettingNumberOfEntries", &DMREAD, DMT_UNINT, get_nat_interface_setting_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{"PortMappingNumberOfEntries", &DMREAD, DMT_UNINT, get_nat_port_mapping_number_of_entries, NULL, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.NAT.InterfaceSetting.{i}. *** */
+DMLEAF tNATInterfaceSettingParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_nat_interface_setting_enable, set_nat_interface_setting_enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMWRITE, DMT_STRING, get_nat_interface_setting_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_nat_interface_setting_alias, set_nat_interface_setting_alias, NULL, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_nat_interface_setting_interface, set_nat_interface_setting_interface, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.NAT.PortMapping.{i}. *** */
+DMLEAF tNATPortMappingParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
+{"Enable", &DMWRITE, DMT_BOOL, get_nat_port_mapping_enable, set_nat_port_mapping_enable, NULL, NULL, BBFDM_BOTH},
+{"Status", &DMWRITE, DMT_STRING, get_nat_port_mapping_status, NULL, NULL, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_nat_port_mapping_alias, set_nat_port_mapping_alias, NULL, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_nat_port_mapping_interface, set_nat_port_mapping_interface, NULL, NULL, BBFDM_BOTH},
+{"AllInterfaces", &DMWRITE, DMT_BOOL, get_nat_port_mapping_all_interface, set_nat_port_mapping_all_interface, NULL, NULL, BBFDM_BOTH},
+{"LeaseDuration", &DMWRITE, DMT_UNINT, get_nat_port_mapping_lease_duration, set_nat_port_mapping_lease_duration, NULL, NULL, BBFDM_BOTH},
+{"RemoteHost", &DMWRITE, DMT_STRING, get_nat_port_mapping_remote_host, set_nat_port_mapping_remote_host, NULL, NULL, BBFDM_BOTH},
+{"ExternalPort", &DMWRITE, DMT_UNINT, get_nat_port_mapping_external_port, set_nat_port_mapping_external_port, NULL, NULL, BBFDM_BOTH},
+{"ExternalPortEndRange", &DMWRITE, DMT_UNINT, get_nat_port_mapping_external_port_end_range, set_nat_port_mapping_external_port_end_range, NULL, NULL, BBFDM_BOTH},
+{"InternalPort", &DMWRITE, DMT_UNINT, get_nat_port_mapping_internal_port, set_nat_port_mapping_internal_port, NULL, NULL, BBFDM_BOTH},
+{"Protocol", &DMWRITE, DMT_STRING, get_nat_port_mapping_protocol, set_nat_port_mapping_protocol, NULL, NULL, BBFDM_BOTH},
+{"InternalClient", &DMWRITE, DMT_STRING, get_nat_port_mapping_internal_client, set_nat_port_mapping_internal_client, NULL, NULL, BBFDM_BOTH},
+{"Description", &DMWRITE, DMT_STRING, get_nat_port_mapping_description, set_nat_port_mapping_description, NULL, NULL, BBFDM_BOTH},
+{0}
+};
+
+/*************************************************************
+ * ADD DEL OBJ
+/*************************************************************/
+int add_NAT_InterfaceSetting(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ char *value, *v, *inst, name[16];
+ struct uci_section *s = NULL, *dmmap_firewall = NULL;
+
+ check_create_dmmap_package("dmmap_firewall");
+ inst = get_last_instance_icwmpd("dmmap_firewall", "zone", "interface_setting_instance");
+ sprintf(name, "iface_set_%d", inst ? (atoi(inst)+1) : 1);
+ dmuci_add_section_and_rename("firewall", "zone", &s, &value);
+ dmuci_set_value_by_section(s, "input", "REJECT");
+ dmuci_set_value_by_section(s, "output", "ACCEPT");
+ dmuci_set_value_by_section(s, "forward", "REJECT");
+ dmuci_set_value_by_section(s, "name", name);
+
+ dmuci_add_section_icwmpd("dmmap_firewall", "zone", &dmmap_firewall, &v);
+ dmuci_set_value_by_section(dmmap_firewall, "section_name", section_name(s));
+ *instance = update_instance_icwmpd(dmmap_firewall, inst, "interface_setting_instance");
+ return 0;
+
+}
+
+int delete_NAT_InterfaceSetting(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ int found = 0;
+ char *lan_name;
+ struct uci_section *s = NULL, *ss = NULL, *dmmap_firewall= NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ get_dmmap_section_of_config_section("dmmap_firewall", "zone", section_name((struct uci_section *)data), &dmmap_firewall);
+ if(dmmap_firewall != NULL)
+ dmuci_delete_by_section(dmmap_firewall, NULL, NULL);
+ dmuci_delete_by_section((struct uci_section *)data, NULL, NULL);
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("firewall", "zone", s) {
+ if (found != 0){
+ get_dmmap_section_of_config_section("dmmap_firewall", "zone", section_name(ss), &dmmap_firewall);
+ if(dmmap_firewall != NULL)
+ dmuci_delete_by_section(dmmap_firewall, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL){
+ get_dmmap_section_of_config_section("dmmap_firewall", "zone", section_name(ss), &dmmap_firewall);
+ if(dmmap_firewall != NULL)
+ dmuci_delete_by_section(dmmap_firewall, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int add_NAT_PortMapping(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+ char *value, *v, *inst, name[16];
+ struct uci_section *s = NULL, *dmmap_firewall = NULL;
+
+ check_create_dmmap_package("dmmap_firewall");
+ inst = get_last_instance_icwmpd("dmmap_firewall", "redirect", "port_mapping_instance");
+ sprintf(name, "port_map_%d", inst ? (atoi(inst)+1) : 1);
+ dmuci_add_section_and_rename("firewall", "redirect", &s, &value);
+ dmuci_set_value_by_section(s, "name", name);
+ dmuci_set_value_by_section(s, "src", "wan");
+ dmuci_set_value_by_section(s, "target", "DNAT");
+ dmuci_set_value_by_section(s, "dest", "lan");
+
+ dmuci_add_section_icwmpd("dmmap_firewall", "redirect", &dmmap_firewall, &v);
+ dmuci_set_value_by_section(dmmap_firewall, "section_name", section_name(s));
+ *instance = update_instance_icwmpd(dmmap_firewall, inst, "port_mapping_instance");
+ return 0;
+
+}
+
+int delete_NAT_PortMapping(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+ int found = 0;
+ char *lan_name;
+ struct uci_section *s = NULL, *ss = NULL, *dmmap_firewall= NULL;
+
+ switch (del_action) {
+ case DEL_INST:
+ get_dmmap_section_of_config_section("dmmap_firewall", "redirect", section_name((struct uci_section *)data), &dmmap_firewall);
+ if(dmmap_firewall != NULL)
+ dmuci_delete_by_section(dmmap_firewall, NULL, NULL);
+ dmuci_delete_by_section((struct uci_section *)data, NULL, NULL);
+ break;
+ case DEL_ALL:
+ uci_foreach_sections("firewall", "redirect", s) {
+ if (found != 0){
+ get_dmmap_section_of_config_section("dmmap_firewall", "redirect", section_name(ss), &dmmap_firewall);
+ if(dmmap_firewall != NULL)
+ dmuci_delete_by_section(dmmap_firewall, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ ss = s;
+ found++;
+ }
+ if (ss != NULL){
+ get_dmmap_section_of_config_section("dmmap_firewall", "redirect", section_name(ss), &dmmap_firewall);
+ if(dmmap_firewall != NULL)
+ dmuci_delete_by_section(dmmap_firewall, NULL, NULL);
+ dmuci_delete_by_section(ss, NULL, NULL);
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/**************************************************************************
+* SET & GET VALUE
+***************************************************************************/
+/*#Device.NAT.InterfaceSettingNumberOfEntries!UCI:firewall/zone/*/
+int get_nat_interface_setting_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+/*#Device.NAT.PortMappingNumberOfEntries!UCI:firewall/redirect/*/
+int get_nat_port_mapping_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ int cnt = 0;
+
+ uci_foreach_sections("firewall", "redirect", s)
+ {
+ cnt++;
+ }
+ dmasprintf(value, "%d", cnt);
+ return 0;
+}
+
+/*#Device.NAT.InterfaceSetting.{i}.Enable!UCI:firewall/zone,@i-1/masq*/
+int get_nat_interface_setting_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *val;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "masq", &val);
+ *value = (*val == '1') ? "1" : "0";
+ return 0;
+}
+
+int set_nat_interface_setting_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ dmuci_set_value_by_section((struct uci_section *)data, "masq", b ? "1" : "0");
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.NAT.InterfaceSetting.{i}.Status!UCI:firewall/zone,@i-1/masq*/
+int get_nat_interface_setting_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *val;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "masq", &val);
+ *value = (*val == '1') ? "Enabled" : "Disabled";
+ return 0;
+}
+
+int get_nat_interface_setting_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_firewall", "zone", section_name((struct uci_section *)data), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "interface_setting_alias", value);
+ return 0;
+}
+
+int set_nat_interface_setting_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_firewall", "zone", section_name((struct uci_section *)data), &dmmap_section);
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(dmmap_section, "interface_setting_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_nat_interface_setting_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_list *v;
+ struct uci_element *e;
+ char *ifaceobj, buf[256] = "";
+
+ *value = "";
+ dmuci_get_value_by_section_list((struct uci_section *)data, "network", &v);
+ if (v == NULL)
+ return 0;
+ uci_foreach_element(v, e) {
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), e->name, &ifaceobj); // MEM WILL BE FREED IN DMMEMCLEAN
+ if (ifaceobj == NULL)
+ continue;
+ if (*buf != '\0')
+ strcat(buf, ",");
+ strcat(buf, ifaceobj);
+ }
+ *value = dmstrdup(buf);
+ return 0;
+}
+
+int set_nat_interface_setting_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *iface, *pch, *pchr, buf[256] = "";
+
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ strcpy(buf, value);
+ dmuci_set_value_by_section((struct uci_section *)data, "network", "");
+ for(pch = strtok_r(buf, ",", &pchr); pch != NULL; pch = strtok_r(NULL, ",", &pchr)) {
+ adm_entry_get_linker_value(ctx, pch, &iface);
+ if (iface) {
+ dmuci_add_list_value_by_section((struct uci_section *)data, "network", iface);
+ free(iface);
+ }
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.Enable!UCI:firewall/redirect,@i-1/enabled*/
+int get_nat_port_mapping_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *val;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enabled", &val);
+ *value = (*val == '1') ? "1" : "0";
+ return 0;
+}
+
+int set_nat_port_mapping_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ string_to_bool(value, &b);
+ dmuci_set_value_by_section((struct uci_section *)data, "enabled", b ? "1" : "0");
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.Status!UCI:firewall/redirect,@i-1/enabled*/
+int get_nat_port_mapping_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *val;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "enabled", &val);
+ *value = (*val == '1') ? "Enabled" : "Disabled";
+ return 0;
+}
+
+int get_nat_port_mapping_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_firewall", "redirect", section_name((struct uci_section *)data), &dmmap_section);
+ dmuci_get_value_by_section_string(dmmap_section, "port_mapping_alias", value);
+ return 0;
+}
+
+int set_nat_port_mapping_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ struct uci_section *dmmap_section;
+
+ get_dmmap_section_of_config_section("dmmap_firewall", "redirect", section_name((struct uci_section *)data), &dmmap_section);
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section(dmmap_section, "port_mapping_alias", value);
+ return 0;
+ }
+ return 0;
+}
+
+int get_nat_port_mapping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_section *s = NULL;
+ struct uci_list *v;
+ struct uci_element *e;
+ char *zone, *name, *ifaceobj, buf[256] = "";
+
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src", &zone);
+ uci_foreach_sections("firewall", "zone", s) {
+ dmuci_get_value_by_section_string(s, "name", &name);
+ if (strcmp(zone, name) == 0) {
+ dmuci_get_value_by_section_list(s, "network", &v);
+ break;
+ }
+ }
+ if (v == NULL)
+ return 0;
+ uci_foreach_element(v, e) {
+ adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), e->name, &ifaceobj); // MEM WILL BE FREED IN DMMEMCLEAN
+ if (ifaceobj == NULL)
+ continue;
+ if (*buf != '\0')
+ strcat(buf, ",");
+ strcat(buf, ifaceobj);
+ }
+ *value = dmstrdup(buf);
+ return 0;
+}
+
+int set_nat_port_mapping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *iface, *network, *zone;
+ struct uci_section *s = NULL;
+
+ switch (action) {
+ case VALUECHECK:
+ break;
+ case VALUESET:
+ adm_entry_get_linker_value(ctx, value, &iface);
+ if (iface[0] != '\0') {
+ uci_foreach_sections("firewall", "zone", s)
+ {
+ dmuci_get_value_by_section_string(s, "network", &network);
+ if (is_strword_in_optionvalue(network, iface)){
+ dmuci_get_value_by_section_string(s, "name", &zone);
+ dmuci_set_value_by_section((struct uci_section *)data, "src", zone);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+int get_nat_port_mapping_all_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ *value = "0";
+ return 0;
+}
+
+int set_nat_port_mapping_all_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ bool b;
+ switch (action) {
+ case VALUECHECK:
+ if (string_to_bool(value, &b))
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ return 0;
+ }
+ return 0;
+}
+
+int get_nat_port_mapping_lease_duration(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ // CPE only supports static port forwards
+ *value = "0";
+ return 0;
+}
+
+int set_nat_port_mapping_lease_duration(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ // CPE only supports static port forwards
+ if (strcmp(value, "0") != 0)
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ // Nothing to set for static port forwards
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.RemoteHost!UCI:firewall/redirect,@i-1/src_dip*/
+int get_nat_port_mapping_remote_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_dip", value);
+ return 0;
+}
+
+int set_nat_port_mapping_remote_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "src_dip", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.ExternalPort!UCI:firewall/redirect,@i-1/src_dport*/
+int get_nat_port_mapping_external_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *dport, *tmp;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_dport", &dport);
+ if (*dport == '\0') {
+ *value = "0";
+ return 0;
+ }
+ tmp = strchr(dport, ':');
+ if (tmp)
+ *tmp = '\0';
+ *value = dport;
+ return 0;
+}
+
+int set_nat_port_mapping_external_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *dport, buffer[64];
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_dport", &dport);
+ dport = strchr(dport, ':');
+ if (dport == NULL)
+ sprintf(buffer, "%s", value);
+ else
+ sprintf(buffer, "%s%s", value, dport);
+ dmuci_set_value_by_section((struct uci_section *)data, "src_dport", buffer);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.ExternalPortEndRange!UCI:firewall/redirect,@i-1/src_dport*/
+int get_nat_port_mapping_external_port_end_range(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *dport, *tmp;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_dport", &dport);
+ tmp = strchr(dport, ':');
+ *value = (tmp) ? tmp+1 : "0";
+ return 0;
+}
+
+int set_nat_port_mapping_external_port_end_range(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *dport, *tmp, buffer[64];
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_get_value_by_section_string((struct uci_section *)data, "src_dport", &dport);
+ tmp = strchr(dport, ':');
+ if (tmp)
+ *tmp = '\0';
+ if (*value == '0')
+ sprintf(buffer, "%s", dport);
+ else
+ sprintf(buffer, "%s:%s", dport, value);
+ dmuci_set_value_by_section((struct uci_section *)data, "src_dport", buffer);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.InternalPort!UCI:firewall/redirect,@i-1/dest_port*/
+int get_nat_port_mapping_internal_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest_port", value);
+ return 0;
+}
+
+int set_nat_port_mapping_internal_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "dest_port", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.Protocol!UCI:firewall/redirect,@i-1/proto*/
+int get_nat_port_mapping_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ char *proto;
+ dmuci_get_value_by_section_string((struct uci_section *)data, "proto", &proto);
+ if (strcasecmp(proto, "tcp") == 0)
+ *value = "TCP";
+ else if (strcasecmp(proto, "udp") == 0)
+ *value = "UDP";
+ else
+ *value = "TCP/UDP";
+ return 0;
+ return 0;
+}
+
+int set_nat_port_mapping_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ char *v;
+ switch (action) {
+ case VALUECHECK:
+ if (strcasecmp("TCP", value) != 0 && strcasecmp("UDP", value) != 0 && strcasecmp("TCP/UDP", value) != 0)
+ return FAULT_9007;
+ return 0;
+ case VALUESET:
+ if (strcasecmp("TCP", value) == 0)
+ v = "tcp";
+ else if (strcasecmp("UDP", value) == 0)
+ v = "udp";
+ else
+ v = "tcpudp";
+ dmuci_set_value_by_section((struct uci_section *)data, "proto", v);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.InternalClient!UCI:firewall/redirect,@i-1/dest_ip*/
+int get_nat_port_mapping_internal_client(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "dest_ip", value);
+ return 0;
+}
+
+int set_nat_port_mapping_internal_client(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "dest_ip", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.Description!UCI:firewall/redirect,@i-1/name*/
+int get_nat_port_mapping_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ dmuci_get_value_by_section_string((struct uci_section *)data, "name", value);
+ return 0;
+}
+
+int set_nat_port_mapping_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ switch (action) {
+ case VALUECHECK:
+ return 0;
+ case VALUESET:
+ dmuci_set_value_by_section((struct uci_section *)data, "name", value);
+ return 0;
+ }
+ return 0;
+}
+
+/*************************************************************
+ * ENTRY METHOD
+/*************************************************************/
+/*#Device.NAT.InterfaceSetting.{i}.!UCI:firewall/zone/dmmap_firewall*/
+int browseInterfaceSettingInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *nati, *nati_last = NULL;
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap("firewall", "zone", "dmmap_firewall", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ nati = handle_update_instance(1, dmctx, &nati_last, update_instance_alias, 3, p->dmmap_section, "interface_setting_instance", "interface_setting_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, nati) == DM_STOP)
+ break;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.!UCI:firewall/redirect/dmmap_firewall*/
+int browsePortMappingInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+ char *natp, *natp_last = NULL, *target;
+ struct dmmap_dup *p;
+ LIST_HEAD(dup_list);
+
+ synchronize_specific_config_sections_with_dmmap("firewall", "redirect", "dmmap_firewall", &dup_list);
+ list_for_each_entry(p, &dup_list, list) {
+ dmuci_get_value_by_section_string(p->config_section, "target", &target);
+ if (*target != '\0' && strcmp(target, "DNAT") != 0)
+ continue;
+ natp = handle_update_instance(1, dmctx, &natp_last, update_instance_alias, 3, p->dmmap_section, "port_mapping_instance", "port_mapping_alias");
+ if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, natp) == DM_STOP)
+ break;
+ }
+ free_dmmap_config_dup_list(&dup_list);
+ return 0;
+}
diff --git a/dmtree/tr181/nat.h b/dmtree/tr181/nat.h
new file mode 100644
index 00000000..32f0a916
--- /dev/null
+++ b/dmtree/tr181/nat.h
@@ -0,0 +1,66 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB
+ * Author: Imen BHIRI
+ * Author: Amin Ben Ramdhane
+ *
+ */
+
+#ifndef __NAT_H
+#define __NAT_H
+
+extern DMOBJ tNATObj[];
+extern DMLEAF tNATParams[];
+extern DMLEAF tNATInterfaceSettingParams[];
+extern DMLEAF tNATPortMappingParams[];
+
+int browseInterfaceSettingInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int browsePortMappingInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+
+int add_NAT_InterfaceSetting(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delete_NAT_InterfaceSetting(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int add_NAT_PortMapping(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delete_NAT_PortMapping(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+
+int get_nat_interface_setting_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nat_port_mapping_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+int get_nat_interface_setting_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_interface_setting_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_interface_setting_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nat_interface_setting_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_interface_setting_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_interface_setting_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_interface_setting_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+int get_nat_port_mapping_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int get_nat_port_mapping_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_all_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_all_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_lease_duration(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_lease_duration(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_remote_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_remote_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_external_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_external_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_external_port_end_range(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_external_port_end_range(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_internal_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_internal_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_internal_client(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_internal_client(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+int get_nat_port_mapping_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+int set_nat_port_mapping_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
+
+#endif
diff --git a/dmtree/tr181/ppp.c b/dmtree/tr181/ppp.c
new file mode 100644
index 00000000..89db476f
--- /dev/null
+++ b/dmtree/tr181/ppp.c
@@ -0,0 +1,600 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2016 Inteno Broadband Technology AB
+ * Author: Anis Ellouze
+ *
+ */
+
+#include