diff --git a/CHANGELOG.md b/CHANGELOG.md index 42da280c..2d53ca60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -390,7 +390,7 @@ The main improvement in this release concerns security in terms of priveleges an * You can start as root and drop privileges either permanently or temporary * use `-U ` clixon_backend command-line option to drop to `user` * Generic options are the following: - * `CLICON_BACKEND_USER` sets the user to drop priveleges to + * `CLICON_BACKEND_USER` drop of privileges to this user * `CLICON_BACKEND_PRIVELEGES` can have the following values: * `none` Make no drop/change in privileges. This is currently the default. * `drop_perm` After initialization, drop privileges permanently diff --git a/apps/backend/backend_plugin.c b/apps/backend/backend_plugin.c index e2b3bcc3..7d6ab008 100644 --- a/apps/backend/backend_plugin.c +++ b/apps/backend/backend_plugin.c @@ -236,8 +236,21 @@ clixon_plugin_statedata_all(clicon_handle h, while ((cp = clixon_plugin_each(h, cp)) != NULL) { if ((ret = clixon_plugin_statedata_one(cp, h, nsc, xpath, &x)) < 0) goto done; - if (ret == 0) + if (ret == 0){ + if ((cberr = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + /* error reason should be in clicon_err_reason */ + cprintf(cberr, "Internal error, state callback in plugin %s returned invalid XML: %s", + cp->cp_name, clicon_err_reason); + if (netconf_operation_failed_xml(&xerr, "application", cbuf_get(cberr)) < 0) + goto done; + xml_free(*xret); + *xret = xerr; + xerr = NULL; goto fail; + } if (x == NULL) continue; if (xml_child_nr(x) == 0){ diff --git a/configure b/configure index 3cf981b2..9bb1966b 100755 --- a/configure +++ b/configure @@ -4292,7 +4292,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu - CPPFLAGS="-DHAVE_CONFIG_H ${CPPFLAGS}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: compiler is $CC" >&5 @@ -4552,7 +4551,10 @@ if test "${with_cligen+set}" = set; then : withval=$with_cligen; fi -if test "${with_cligen}"; then +if test -n "${CLIGEN_DIR}" -a -d "${CLIGEN_DIR}"; then + with_cligen=${CLIGEN_DIR} +fi +if test -d "${with_cligen}"; then echo "Using CLIGEN here: ${with_cligen}" CPPFLAGS="-I${with_cligen}/include ${CPPFLAGS}" LDFLAGS="-L${with_cligen}/lib ${LDFLAGS}" diff --git a/configure.ac b/configure.ac index 27c8f465..07859e22 100644 --- a/configure.ac +++ b/configure.ac @@ -147,9 +147,11 @@ fi SH_SUFFIX=".so" # This is for cligen -AC_ARG_WITH([cligen], - AS_HELP_STRING([--with-cligen=dir],[Use CLIGEN installation in this dir])) -if test "${with_cligen}"; then +AC_ARG_WITH([cligen], AS_HELP_STRING([--with-cligen=dir],[Use CLIGEN installation in this dir])) +if test -n "${CLIGEN_DIR}" -a -d "${CLIGEN_DIR}"; then + with_cligen=${CLIGEN_DIR} +fi +if test -d "${with_cligen}"; then echo "Using CLIGEN here: ${with_cligen}" CPPFLAGS="-I${with_cligen}/include ${CPPFLAGS}" LDFLAGS="-L${with_cligen}/lib ${LDFLAGS}" diff --git a/test/test_yang_anydata.sh b/test/test_yang_anydata.sh new file mode 100755 index 00000000..3a1d873a --- /dev/null +++ b/test/test_yang_anydata.sh @@ -0,0 +1,226 @@ +#!/usr/bin/env bash +# Test YANG ANYDATA: +# Also Test CLICON_YANG_UNKNOWN_ANYDATA: Treat unknown XML/JSON nodes as anydata. +# Test matric is three dimensions: +# 1. YANG spec: u-elements are a) anydata or b) unknown +# 2. Access is made to top-elements: a) top-level, b) in container, c) in list +# 3. data is in a) startup b) netconf 3)state + +# Load an XML file with unknown yang constructs that is labelled as anydata +# Ensure clixon is robust to handle that +# Test is that unknown XML subcomponents (with label u) are loaded in an xml file. + +# Magic line must be first in script (see README.md) +s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi + +APPNAME=example + +test -d $dir/yang || mkdir $dir/yang +cfg=$dir/conf_yang.xml +fanydata=$dir/yang/anydata.yang +funknown=$dir/yang/unknown.yang +fstate=$dir/state.xml + +cat < $fanydata +module any{ + yang-version 1.1; + prefix any; + namespace "urn:example:any"; + container ca{ + list b{ + key k; + leaf k { + type string; + } + anydata u3; + } + anydata u2; + } + anydata u1; + container sa{ + config false; + list sb{ + key k; + leaf k { + type string; + } + anydata u5; + } + anydata u4; + } +} +EOF + +cat < $funknown +module unknown{ + yang-version 1.1; + prefix un; + namespace "urn:example:unknown"; + container cu{ + list b{ + key k; + leaf k { + type string; + } + } + } + container su{ + config false; + list sb{ + key k; + leaf k { + type string; + } + } + } +} +EOF + +# For edit config +XMLA='2255a string23' + +XMLU='2255a string23' + +# Full state +STATE0='2255a string2255a string' + +# Partial state with unknowns removed in the unknown module +STATE1='2255a string22' + +# Run anydata and unknown tests +# From a startup db or via netconf commands as well as state data +# Test both anydata and unknown +# Args: +# 1: bool: startup (or not) +# 2: bool: treat unknown as anydata (or not) +testrun() +{ + startup=$1 + unknown=$2 + + if $unknown; then # treat unknown as anydata or not + unknownreply="]]>]]>" + XML="$XMLA$XMLU" + else + unknownreply="applicationunknown-elementu1errorUnassigned yang spec]]>]]>" + XML="$XMLA" + fi + + if $startup; then # get config from startup + F="ietf-netconf:startup" + else + F="" + fi + cat < $cfg + + $cfg + /usr/local/share/clixon + $dir + $IETFRFC + $dir/yang + /usr/local/lib/$APPNAME/clispec + /usr/local/lib/$APPNAME/cli + /usr/local/lib/$APPNAME/netconf + /usr/local/lib/$APPNAME/backend + $APPNAME + /usr/local/var/$APPNAME/$APPNAME.sock + /usr/local/var/$APPNAME/$APPNAME.pidfile + $dir + false + $unknown + $F + +EOF + + if $startup; then + # Only positive startup test, ie dont add XMLU if unknown not treated as anyxml + # and check for errors + cat < $dir/startup_db + + $XML + +EOF + fi + + if [ $BE -ne 0 ]; then + new "kill old backend" + sudo clixon_backend -zf $cfg + if [ $? -ne 0 ]; then + err + fi + if $startup; then + new "start backend -s startup -f $cfg -- -sS $fstate" + start_backend -s startup -f $cfg -- -sS $fstate + else + new "start backend -s init -f $cfg -- -sS $fstate" + start_backend -s init -f $cfg -- -sS $fstate + fi + + new "waiting" + wait_backend + fi + + + if ! $startup; then # If not startup, add xml using netconf + new "Put anydata" + expecteof "$clixon_netconf -qf $cfg -D $DBG" 0 "$XMLA]]>]]>" "]]>]]>" + + new "Put unknown" + expecteof "$clixon_netconf -qf $cfg -D $DBG" 0 "$XMLU]]>]]>" "$unknownreply" + + new "commit" + expecteof "$clixon_netconf -qf $cfg -D $DBG" 0 "]]>]]>" "]]>]]>" + fi + + new "Get candidate" + expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^$XML]]>]]>$" + + new "Get running" + expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^$XML]]>]]>$" + + if $unknown; then + STATE="$STATE0" # full state + else + STATE="$STATE1" # partial state + fi + echo "$STATE" > $fstate + + new "Get state (positive test)" + expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^$STATE]]>]]>" + + echo "$STATE0" > $fstate # full state + + new "Get state (negative test)" + if $unknown; then + expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^$STATE]]>]]>" + else + expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "error-message>Failed to find YANG spec of XML node: u5 with parent: sb in namespace: urn:example:unknown. Internal error, state callback returned invalid XML: example_backend" + fi + if [ $BE -ne 0 ]; then + new "Kill backend" + # Check if premature kill + pid=$(pgrep -u root -f clixon_backend) + if [ -z "$pid" ]; then + err "backend already dead" + fi + # kill backend + stop_backend -f $cfg + sudo pkill -u root -f clixon_backend + fi +} + +new "test params: -f $cfg" + +new "no startup, dont treat unknown as anydata" +testrun false false + +new "startup, dont treat unknown as anydata" +testrun true false + +new "no startup, treat unknown as anydata" +testrun false true + +new "startup, treat unknown as anydata" +testrun true true + +rm -rf $dir