From 319e7707d8b757a8ab548af6baff053b68c04eb0 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Mon, 9 Jan 2017 21:26:50 +0100 Subject: [PATCH] Empty yang type. Relaxed yang types for unions, eg two strings with different length. --- CHANGELOG | 2 + apps/cli/cli_common.c | 17 ++--- apps/cli/cli_generate.c | 115 +++++++--------------------------- apps/cli/cli_main.c | 3 + apps/cli/cli_show.c | 6 +- doc/FAQ.txt | 3 +- lib/clixon/clixon_proto.h | 2 +- lib/src/clixon_proto_client.c | 2 +- lib/src/clixon_proto_encode.c | 10 ++- lib/src/clixon_xml_db.c | 5 +- lib/src/clixon_yang_parse.h | 3 + lib/src/clixon_yang_parse.l | 3 + lib/src/clixon_yang_parse.y | 3 + lib/src/clixon_yang_type.c | 3 +- 14 files changed, 64 insertions(+), 113 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index bdfc22b1..29816d40 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,6 +29,8 @@ # # ***** END LICENSE BLOCK ***** +- Empty yang type. Relaxed yang types for unions, eg two strings with different length. + Dec 2016: Dual license: both GPLv3 and APLv2 Feb 2016: Forked new clixon repository from clicon diff --git a/apps/cli/cli_common.c b/apps/cli/cli_common.c index 07fa8a1f..ff148c8e 100644 --- a/apps/cli/cli_common.c +++ b/apps/cli/cli_common.c @@ -495,7 +495,7 @@ compare_dbs(clicon_handle h, cvec *cvv, cg_var *arg) * cvv[2] = "bgp" * arg = "/interfaces/interface/%s/type" * op: OP_MERGE - * @see cli_callback_xmlkeyfmt_generate where arg is generated + * @see cli_callback_generate where arg is generated */ static int cli_dbxml(clicon_handle h, @@ -508,17 +508,20 @@ cli_dbxml(clicon_handle h, char *xkfmt; /* xml key format */ char *xk = NULL; /* xml key */ cg_var *cval; - char *val = NULL; + int len; xkfmt = cv_string_get(arg); if (xmlkeyfmt2key(xkfmt, cvv, &xk) < 0) goto done; - cval = cvec_i(cvv, cvec_len(cvv)-1); - if ((val = cv2str_dup(cval)) == NULL){ - clicon_err(OE_UNIX, errno, "cv2str_dup"); - goto done; + len = cvec_len(cvv); + if (len > 1){ + cval = cvec_i(cvv, len-1); + if ((str = cv2str_dup(cval)) == NULL){ + clicon_err(OE_UNIX, errno, "cv2str_dup"); + goto done; + } } - if (clicon_rpc_change(h, "candidate", op, xk, val) < 0) + if (clicon_rpc_change(h, "candidate", op, xk, str) < 0) goto done; if (clicon_autocommit(h)) { if (clicon_rpc_commit(h, "candidate", "running", 0, 0) < 0) diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index 656d5486..177d58aa 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -72,104 +72,31 @@ /*===================================================================== * YANG generate CLI *=====================================================================*/ -#if 0 /* examples/ntp */ - ntp("Network Time Protocol"),cli_set("ntp");{ - logging("Configure NTP message logging"),cli_set("ntp.logging");{ - status (),cli_set("ntp.logging $status:bool"); - } - server("Configure NTP Server") (("IPv4 address of peer")),cli_set("ntp.server[] $!ipv4addr:ipv4addr"); - } -#endif -#if 0 /* examples/datamodel */ - -WITH COMPLETION: - a (|),cli_set("a[] $!x");{ - b,cli_set("a[].b $!x");{ - y (|),cli_set("a[].b $!x $y"); - } - z (|),cli_set("a[] $!x $z"); - } - -#endif - -#ifndef HAVE_CLIGEN_MAX2STR /* XXX cligen 3.6 feature */ - -/*! Print max value of a CLIgen variable type as string - * @param[in] type CLIgen variable type - * @param[out] str Max value printed in this string - * @param[in] size Length of 'str' - * @retval len How many bytes printed - * @see cvtype_max2str_dup - * You can use str=NULL to get the expected length. - * The number of (potentially if str=NULL) written bytes is returned. - */ -static int -cvtype_max2str(enum cv_type type, char *str, size_t size) -{ - int len = 0; - - switch (type){ - case CGV_INT8: - len = snprintf(str, size, "%" PRId8, INT8_MAX); - break; - case CGV_INT16: - len = snprintf(str, size, "%" PRId16, INT16_MAX); - break; - case CGV_INT32: - len = snprintf(str, size, "%" PRId32, INT32_MAX); - break; - case CGV_INT64: - len = snprintf(str, size, "%" PRId64, INT64_MAX); - break; - case CGV_UINT8: - len = snprintf(str, size, "%" PRIu8, UINT8_MAX); - break; - case CGV_UINT16: - len = snprintf(str, size, "%" PRIu16, UINT16_MAX); - break; - case CGV_UINT32: - len = snprintf(str, size, "%" PRIu32, UINT32_MAX); - break; - case CGV_UINT64: - len = snprintf(str, size, "%" PRIu64, UINT64_MAX); - break; - case CGV_DEC64: - len = snprintf(str, size, "%" PRId64 ".0", INT64_MAX); - break; - case CGV_BOOL: - len = snprintf(str, size, "true"); - break; - default: - break; +/* + This is an example yang module: +module m { + container x { + list m1 { + key "a"; + leaf a { + type string; + } + leaf b { + type string; + } } - return len; + } } -/*! Print max value of a CLIgen variable type as string - * - * The string should be freed after use. - * @param[in] type CLIgen variable type - * @retval str Malloced string containing value. Should be freed after use. - * @see cvtype_max2str - */ -static char * -cvtype_max2str_dup(enum cv_type type) +You can see which CLISPEC it generates via clixon_cli -D 1: +Jan 2 11:17:58: yang2cli: buf +} x,cli_set("/x");{ + m1 (|),cli_set("/x/m1/%s"); { - int len; - char *str; - - if ((len = cvtype_max2str(type, NULL, 0)) < 0) - return NULL; - if ((str = (char *)malloc (len+1)) == NULL) - return NULL; - memset (str, '\0', len+1); - if ((cvtype_max2str(type, str, len+1)) < 0){ - free(str); - return NULL; - } - return str; -} -#endif /* HAVE_CLIGEN_MAX2STR */ + b (|),cli_set("/x/m1/%s/b"); + } + } +*/ /*! Create cligen variable expand entry with xmlkey format string as argument * @param[in] h clicon handle diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index 3becb8ad..10fe40da 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -377,6 +377,9 @@ main(int argc, char **argv) /* Join rest of argv to a single command */ restarg = clicon_strjoin(argc, argv, " ", __FUNCTION__); + /* If several cligen object variables match same preference, select first */ + cligen_match_cgvar_same(1); + /* Call start function in all plugins before we go interactive Pass all args after the standard options to plugin_start */ diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index e58d610a..428955a4 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -81,9 +81,9 @@ static int xml2csv(FILE *f, cxobj *x, cvec *cvv); * Returns an expand-type list of commands as used by cligen 'expand' * functionality. * - * Assume callback given in a cligen spec: a " * @param[out] len len of return commands & helptxt @@ -121,7 +121,7 @@ expand_dbvar(void *h, clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__); goto done; } - /* In the example, str = "candidate a[].b[] $!x $!y" */ + /* In the example, str = "candidate /x/m1/%s/b" */ if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){ clicon_err(OE_PLUGIN, errno, "clicon_strsplit"); goto done; diff --git a/doc/FAQ.txt b/doc/FAQ.txt index 51af8c6e..6ce91d6a 100644 --- a/doc/FAQ.txt +++ b/doc/FAQ.txt @@ -170,7 +170,8 @@ Q: How do you use netconf? -------------------------- As an alternative to cli configuration, you can use netconf -directly. Easiesty is to just pipe netconf commands to the +directly. Easiest is to just pipe netconf commands to the clixon_netconf application. Example: echo "]]>]]>" | clixon_netconf -f /usr/local/etc/routing.conf + diff --git a/lib/clixon/clixon_proto.h b/lib/clixon/clixon_proto.h index aca8731a..485e0a12 100644 --- a/lib/clixon/clixon_proto.h +++ b/lib/clixon/clixon_proto.h @@ -63,7 +63,7 @@ enum clicon_msg_type{ 2. uint32: length of value string 3. string: name of database to change (eg "running") 4. string: key - 5. string: value + 5. string: value (can be NULL) */ CLICON_MSG_XMLPUT, /* Send database entries as XML to backend daemon 1. uint32: operation: LV_SET/LV_DELETE diff --git a/lib/src/clixon_proto_client.c b/lib/src/clixon_proto_client.c index 48e59964..f0b78e4c 100644 --- a/lib/src/clixon_proto_client.c +++ b/lib/src/clixon_proto_client.c @@ -200,7 +200,7 @@ clicon_rpc_change(clicon_handle h, op, key, val, - strlen(val)+1, + val?strlen(val)+1:0, __FUNCTION__)) == NULL) goto done; if (clicon_rpc_msg(h, msg, NULL, NULL, NULL, __FUNCTION__) < 0) diff --git a/lib/src/clixon_proto_encode.c b/lib/src/clixon_proto_encode.c index 73002781..a03eec9c 100644 --- a/lib/src/clixon_proto_encode.c +++ b/lib/src/clixon_proto_encode.c @@ -199,7 +199,9 @@ clicon_msg_change_encode(char *db, op, str_len, db, key); p = 0; len = sizeof(*msg) + 2*sizeof(uint32_t) + strlen(db) + 1 + - strlen(key) + 1 + str_len; + strlen(key) + str_len; + if (str_len) + len++; /* if str not null add end of string */ if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){ clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__); return NULL; @@ -221,8 +223,10 @@ clicon_msg_change_encode(char *db, p += strlen(db)+1; strncpy(msg->op_body+p, key, len-p-hdrlen); p += strlen(key)+1; - memcpy(msg->op_body+p, str, str_len); - p += str_len; + if (str_len){ + memcpy(msg->op_body+p, str, str_len); + p += str_len; + } return msg; } diff --git a/lib/src/clixon_xml_db.c b/lib/src/clixon_xml_db.c index fa3441cc..78b62835 100644 --- a/lib/src/clixon_xml_db.c +++ b/lib/src/clixon_xml_db.c @@ -221,6 +221,7 @@ yang2xmlkeyfmt(yang_stmt *ys, * @param[in] cvv cligen variable vector, one for every wildchar in xkfmt * @param[out] xk XML key, eg /aaa/17. Free after use * @note first and last elements of cvv are not used,.. + * @see cli_dbxml where this function is called */ int xmlkeyfmt2key(char *xkfmt, @@ -247,7 +248,7 @@ xmlkeyfmt2key(char *xkfmt, j, cvec_len(cvv), cv_string_get(cvec_i(cvv, 0))); - // goto done; + goto done; } #endif if ((cb = cbuf_new()) == NULL){ @@ -1689,7 +1690,7 @@ xmldb_put_xkey_local(clicon_handle h, case OP_MERGE: case OP_REPLACE: if (y->ys_keyword == Y_LEAF || y->ys_keyword == Y_LEAF_LIST){ - if (db_set(filename, xk, val, strlen(val)+1) < 0) + if (db_set(filename, xk, val, val?strlen(val)+1:0) < 0) goto done; } else diff --git a/lib/src/clixon_yang_parse.h b/lib/src/clixon_yang_parse.h index 1deaa9a3..a63253c0 100644 --- a/lib/src/clixon_yang_parse.h +++ b/lib/src/clixon_yang_parse.h @@ -1,4 +1,7 @@ /* + * Yang 1.0 parser according to RFC6020. + * It is hopefully useful but not complete + * RFC7950 defines Yang version 1.1 * ***** BEGIN LICENSE BLOCK ***** diff --git a/lib/src/clixon_yang_parse.l b/lib/src/clixon_yang_parse.l index 5f46aa64..885cc708 100644 --- a/lib/src/clixon_yang_parse.l +++ b/lib/src/clixon_yang_parse.l @@ -1,4 +1,7 @@ /* + * Yang 1.0 parser according to RFC6020. + * It is hopefully useful but not complete + * RFC7950 defines Yang version 1.1 * ***** BEGIN LICENSE BLOCK ***** diff --git a/lib/src/clixon_yang_parse.y b/lib/src/clixon_yang_parse.y index c7f57ff7..31c59afd 100644 --- a/lib/src/clixon_yang_parse.y +++ b/lib/src/clixon_yang_parse.y @@ -1,4 +1,7 @@ /* + * Yang 1.0 parser according to RFC6020. + * It is hopefully useful but not complete + * RFC7950 defines Yang version 1.1 * ***** BEGIN LICENSE BLOCK ***** diff --git a/lib/src/clixon_yang_type.c b/lib/src/clixon_yang_type.c index 0fd7d553..0cb1dbf3 100644 --- a/lib/src/clixon_yang_type.c +++ b/lib/src/clixon_yang_type.c @@ -104,7 +104,7 @@ static const struct map_str2int ytmap[] = { {"uint16", CGV_UINT16}, {"uint32", CGV_UINT32}, {"uint64", CGV_UINT64}, - {"union", CGV_VOID}, /* Is replaced by actual type */ + {"union", CGV_REST}, /* Is replaced by actual type */ {NULL, -1} }; @@ -912,6 +912,7 @@ yang_type_get(yang_stmt *ys, clicon_err(OE_DB, 0, "%s: mandatory type object is not found", __FUNCTION__); goto done; } + /* XXX: here we seem to have some problems if type is union */ type = ytype_id(ytype); if (origtype) *origtype = type;