diff --git a/CHANGELOG.md b/CHANGELOG.md index ff1a1db6..48aecb65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ * Applications which have not strictly enforced the identities may now have problems with validation and may need to be modified. ### Minor changes: -* Dedicated xml,json,yang and xsl parser utility programs added +* Changed `plugin_init()` backend return semantics: If returns NULL, _without_ calling clicon_err(), the module is disabled. +* Dedicated standalone xml,json,yang and xsl parser utility test programs added under lib/src/. * CDATA xml support (patch by David Cornejo, Netgate) * Encode and decode (parsing) support * Validation of yang bits type space-separated list value diff --git a/example/README.md b/example/README.md index cafd796f..e373476b 100644 --- a/example/README.md +++ b/example/README.md @@ -23,7 +23,7 @@ routing example. It contains the following files: ``` Start backend: ``` - clixon_backend -f /usr/local/etc/example.xml -I + sudo clixon_backend -f /usr/local/etc/example.xml -s init ``` Edit cli: ``` diff --git a/example/example_backend_nacm.c b/example/example_backend_nacm.c index d6ed4600..f484362e 100644 --- a/example/example_backend_nacm.c +++ b/example/example_backend_nacm.c @@ -114,6 +114,13 @@ static clixon_plugin_api api = { clixon_plugin_api * clixon_plugin_init(clicon_handle h) { + char *nacm_mode; + clicon_debug(1, "%s backend nacm", __FUNCTION__); + nacm_mode = clicon_option_str(h, "CLICON_NACM_MODE"); + if (nacm_mode==NULL || strcmp(nacm_mode, "disabled") == 0){ + clicon_debug(1, "%s CLICON_NACM_MODE not enabled: example nacm module disabled", __FUNCTION__); + return NULL; + } return &api; } diff --git a/lib/clixon/clixon_plugin.h b/lib/clixon/clixon_plugin.h index cd340458..cd6038aa 100644 --- a/lib/clixon/clixon_plugin.h +++ b/lib/clixon/clixon_plugin.h @@ -41,7 +41,9 @@ /* * Constants */ -/* Hardcoded plugin symbol. Must exist in all plugins to kickstart */ +/* Hardcoded plugin symbol. Must exist in all plugins to kickstart + * @see clixon_plugin_init + */ #define CLIXON_PLUGIN_INIT "clixon_plugin_init" /* @@ -181,6 +183,7 @@ typedef struct clixon_plugin clixon_plugin; /*! Plugin initialization function. Must appear in all plugins * @param[in] h Clixon handle * @retval api Pointer to API struct + * @retval NULL Failure (if clixon_err() called), module disabled otherwise. * @see CLIXON_PLUGIN_INIT default symbol */ clixon_plugin_api *clixon_plugin_init(clicon_handle h); diff --git a/lib/src/clixon_plugin.c b/lib/src/clixon_plugin.c index 3d0b80ae..2631938c 100644 --- a/lib/src/clixon_plugin.c +++ b/lib/src/clixon_plugin.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -204,12 +205,16 @@ plugin_load_one(clicon_handle h, clicon_err(OE_UNIX, 0, "dlsym: %s: %s", file, error); goto done; } + clicon_err_reset(); if ((api = initfn(h)) == NULL) { - clicon_err(OE_PLUGIN, errno, "Failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file); - if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ - clicon_err(OE_DB, 0, "Unknown error: %s: plugin_init does not make clicon_err call on error", - file); - goto err; + if (!clicon_errno){ /* if clicon_err() is not called then log and continue */ + clicon_log(LOG_WARNING, "Warning: failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file); + dlclose(handle); + } + else{ + clicon_err(OE_PLUGIN, errno, "Failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file); + goto err; + } } /* Note: sizeof clixon_plugin_api which is largest of clixon_plugin_api:s */ if ((cp = (clixon_plugin *)malloc(sizeof(struct clixon_plugin))) == NULL){ @@ -228,7 +233,8 @@ plugin_load_one(clicon_handle h, snprintf(cp->cp_name, sizeof(cp->cp_name), "%*s", (int)strlen(name), name); - cp->cp_api = *api; + if (api) + cp->cp_api = *api; clicon_debug(1, "%s", __FUNCTION__); done: return cp; diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index 1e80bf68..c2393782 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -1487,8 +1487,6 @@ int xml_copy_one(cxobj *x0, cxobj *x1) { - cg_var *cv1; - xml_type_set(x1, xml_type(x0)); if (xml_value(x0)){ /* malloced string */ if ((x1->x_value = strdup(x0->x_value)) == NULL){ diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index 7e1b69e4..88aa0d6d 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -1715,6 +1715,7 @@ xml_merge1(cxobj *x0, cxobj *x1c; /* mod child */ char *x1bstr; /* mod body string */ yang_stmt *yc; /* yang child */ + cbuf *cbr = NULL; /* Reason buffer */ assert(x1 && xml_type(x1) == CX_ELMNT); assert(y0); @@ -1753,9 +1754,16 @@ xml_merge1(cxobj *x0, x1cname = xml_name(x1c); /* Get yang spec of the child */ if ((yc = yang_find_datanode(y0, x1cname)) == NULL){ - if (reason && (*reason = strdup("XML node has no corresponding yang specification (Invalid XML or wrong Yang spec?")) == NULL){ - clicon_err(OE_UNIX, errno, "strdup"); - goto done; + if (reason){ + if ((cbr = cbuf_new()) == NULL){ + clicon_err(OE_XML, errno, "cbuf_new"); + goto done; + } + cprintf(cbr, "XML node %s/%s has no corresponding yang specification (Invalid XML or wrong Yang spec?", xml_name(x1), x1cname); + if ((*reason = strdup(cbuf_get(cbr))) == NULL){ + clicon_err(OE_UNIX, errno, "strdup"); + goto done; + } } break; } @@ -1772,6 +1780,8 @@ xml_merge1(cxobj *x0, ok: retval = 0; done: + if (cbr) + cbuf_free(cbr); return retval; } @@ -1797,6 +1807,7 @@ xml_merge(cxobj *x0, cxobj *x0c; /* base child */ cxobj *x1c; /* mod child */ yang_stmt *yc; + cbuf *cbr = NULL; /* Reason buffer */ /* Loop through children of the modification tree */ x1c = NULL; @@ -1804,9 +1815,16 @@ xml_merge(cxobj *x0, x1cname = xml_name(x1c); /* Get yang spec of the child */ if ((yc = yang_find_topnode(yspec, x1cname, YC_DATANODE)) == NULL){ - if (reason && (*reason = strdup("XML node has no corresponding yang specification (Invalid XML or wrong Yang spec?")) == NULL){ - clicon_err(OE_UNIX, errno, "strdup"); - goto done; + if (reason){ + if ((cbr = cbuf_new()) == NULL){ + clicon_err(OE_XML, errno, "cbuf_new"); + goto done; + } + cprintf(cbr, "XML node %s/%s has no corresponding yang specification (Invalid XML or wrong Yang spec?", xml_name(x1), x1cname); + if ((*reason = strdup(cbuf_get(cbr))) == NULL){ + clicon_err(OE_UNIX, errno, "strdup"); + goto done; + } } break; } @@ -1820,6 +1838,8 @@ xml_merge(cxobj *x0, } retval = 0; /* OK */ done: + if (cbr) + cbuf_free(cbr); return retval; }