CliXoN
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
Macros | Functions | Variables
clixon_yang.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>
#include <arpa/inet.h>
#include <regex.h>
#include <dirent.h>
#include <syslog.h>
#include <assert.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <cligen/cligen.h>
#include "clixon_log.h"
#include "clixon_err.h"
#include "clixon_string.h"
#include "clixon_queue.h"
#include "clixon_hash.h"
#include "clixon_handle.h"
#include "clixon_file.h"
#include "clixon_yang.h"
#include "clixon_chunk.h"
#include "clixon_options.h"
#include "clixon_yang_type.h"
#include "clixon_yang_parse.h"

Macros

#define __USE_GNU   /* strverscmp */
 
#define YANG_TYPE_CACHE   1
 

Functions

yang_spec * yspec_new (void)
 
yang_stmt * ys_new (enum rfc_6020 keyw)
 
static int ys_free1 (yang_stmt *ys)
 
int ys_free (yang_stmt *ys)
 
int yspec_free (yang_spec *yspec)
 
static int yn_realloc (yang_node *yn)
 
int ys_cp (yang_stmt *ynew, yang_stmt *yold)
 
yang_stmt * ys_dup (yang_stmt *old)
 
int yn_insert (yang_node *yn_parent, yang_stmt *ys_child)
 
yang_stmt * yn_each (yang_node *yn, yang_stmt *ys)
 
yang_stmt * yang_find (yang_node *yn, int keyword, char *argument)
 
yang_stmt * yang_find_syntax (yang_node *yn, char *argument)
 
yang_stmt * yang_find_topnode (yang_spec *ysp, char *name)
 
static yang_stmt * yang_find_xpath_stmt (yang_node *yn, char *argument)
 
static int ys_flag_reset (yang_stmt *ys, void *arg)
 
char * yang_key2str (int keyword)
 
yang_stmt * ys_module (yang_stmt *ys)
 
yang_spec * ys_spec (yang_stmt *ys)
 
char * ytype_id (yang_stmt *ys)
 
char * ytype_prefix (yang_stmt *ys)
 
yang_stmt * ys_module_import (yang_stmt *ymod, char *prefix)
 
static int quotedstring (char *s)
 
int yang_print (FILE *f, yang_node *yn, int marginal)
 
int yang_print_cbuf (cbuf *cb, yang_node *yn, int marginal)
 
static int ys_populate_leaf (yang_stmt *ys, void *arg)
 
static int ys_populate_range (yang_stmt *ys, void *arg)
 
static int ys_populate_type (yang_stmt *ys, void *arg)
 
static int ys_populate_identity (yang_stmt *ys, void *arg)
 
static int ys_populate (yang_stmt *ys, void *arg)
 
static int ys_grouping_resolve (yang_stmt *ys, char *prefix, char *name, yang_stmt **ygrouping0)
 
static int yang_augment_node (yang_stmt *ys, yang_spec *ysp)
 
static int yang_augment_spec (yang_spec *ysp)
 
static int yang_expand (yang_node *yn)
 
static yang_stmt * yang_parse_str (clicon_handle h, char *str, const char *name, yang_spec *yspec)
 
static yang_stmt * yang_parse_file (clicon_handle h, FILE *f, const char *name, yang_spec *ysp)
 
static int yang_parse_find_match (clicon_handle h, const char *yang_dir, const char *module, cbuf *fbuf)
 
static yang_stmt * yang_parse2 (clicon_handle h, const char *yang_dir, const char *module, const char *revision, yang_spec *ysp)
 
static yang_stmt * yang_parse1 (clicon_handle h, const char *yang_dir, const char *module, const char *revision, yang_spec *ysp)
 
int yang_parse (clicon_handle h, const char *yang_dir, const char *module, const char *revision, yang_spec *ysp)
 
int yang_apply (yang_node *yn, yang_applyfn_t fn, void *arg)
 
static yang_node * yang_xpath_vec (yang_node *yn, char **vec, int nvec)
 
yang_node * yang_xpath_abs (yang_node *yn, char *xpath)
 
yang_node * yang_xpath (yang_node *yn, char *xpath)
 
cg_var * ys_parse (yang_stmt *ys, enum cv_type cvtype)
 
int ys_parse_sub (yang_stmt *ys)
 
int yang_mandatory (yang_stmt *ys)
 
int yang_config (yang_stmt *ys)
 
int yang_spec_main (clicon_handle h, FILE *f, int printspec)
 
cvec * yang_arg2cvec (yang_stmt *ys, char *delim)
 
int yang_key_match (yang_node *yn, char *name)
 

Variables

static const struct map_str2int ykmap []
 

Macro Definition Documentation

#define __USE_GNU   /* strverscmp */
#define YANG_TYPE_CACHE   1

Function Documentation

static int quotedstring ( char *  s)
inlinestatic

string is quoted if it contains space or tab, needs double ''

int yang_apply ( yang_node *  yn,
yang_applyfn_t  fn,
void *  arg 
)

Apply a function call recursively on all yang-stmt s recursively

Recursively traverse all yang-nodes in a parse-tree and apply fn(arg) for each object found. The function is called with the yang-stmt and an argument as args. The tree is traversed depth-first, which at least guarantees that a parent is traversed before a child.

Parameters
[in]xnXML node
[in]typematching type or -1 for any
[in]fnCallback
[in]argArgument
int ys_fn(yang_stmt *ys, void *arg)
{
return 0;
}
yang_apply((yang_node*)ys, ys_fn, NULL);
Note
do not delete or move around any children during this function
cvec* yang_arg2cvec ( yang_stmt *  ys,
char *  delim 
)

Given a yang node, translate the argument string to a cv vector

Parameters
[in]ysYang statement
[in]delimiterDelimiter character (eg ' ' or ',')
Return values
NULLError
cvecVector of strings. Free with cvec_free()
cvec *cvv;
cg_var *cv = NULL;
if ((cvv = yang_arg2cvec(ys, " ")) == NULL)
goto err;
while ((cv = cvec_each(cvv, cv)) != NULL)
...cv_string_get(cv);
cvec_free(cvv);
Note: must free return value after use w cvec_free
static int yang_augment_node ( yang_stmt *  ys,
yang_spec *  ysp 
)
static

This is an augment node, augment the original datamodel. The target node MUST be either a container, list, choice, case, input, output, or notification node. If the "augment" statement is on the top level the absolute form MUST be used. XXX: Destructively changing a datamodel may affect outlying loop?

static int yang_augment_spec ( yang_spec *  ysp)
static

Find all top-level augments and change original datamodels.

int yang_config ( yang_stmt *  ys)

Return config state of this node config statement is default true. Note that a node with config=false may not have a sub statement where config=true. And this function does not check the sttaus of a parent.

Return values
0if node has a config sub-statement and it is false
1node has not config sub-statement or it is true
static int yang_expand ( yang_node *  yn)
static

Macro expansion of grouping/uses done in step 2 of yang parsing NOTE RFC6020 says this: Identifiers appearing inside the grouping are resolved relative to the scope in which the grouping is defined, not where it is used. Prefix mappings, type names, grouping names, and extension usage are evaluated in the hierarchy where the "grouping" statement appears. But it will be very difficult to generate keys etc with this semantics. So for now I macro-expand them

yang_stmt* yang_find ( yang_node *  yn,
int  keyword,
char *  argument 
)

Find first child yang_stmt with matching keyword and argument

Parameters
[in]ynYang node, current context node.
[in]keywordif 0 match any keyword
[in]argumentif NULL, match any argument. This however means that if you actually want to match only a yang-stmt with argument==NULL you cannot, but I have not seen any such examples.
See Also
yang_find_syntax
yang_stmt* yang_find_syntax ( yang_node *  yn,
char *  argument 
)

Find a child syntax-node yang_stmt with matching argument (container, leaf, etc)

Parameters
[in]ynYang node, current context node.
[in]argumentif NULL, match any(first) argument.
See Also
yang_find But this looks only for the yang specification nodes with the following keyword: container, leaf, list, leaf-list That is, basic syntax nodes.
Note
check if argument==NULL really required? Is this yang-stmt a container, list, leaf or leaf-list?
yang_stmt* yang_find_topnode ( yang_spec *  ysp,
char *  name 
)

Help function to check find 'top-node', eg first 'syntax' node in a spec A yang specification has modules as children which in turn can have syntax-nodes as children. This function goes through all the modules to look for syntax-nodes. Note that if a child to a module is a choice, the search is made recursively made to the choice's children.

static yang_stmt* yang_find_xpath_stmt ( yang_node *  yn,
char *  argument 
)
static

Find a child spec-node yang_stmt with matching argument for xpath

See also yang_find() but this looks only for the yang specification nodes with the following keyword: container, leaf, list, leaf-list That is, basic syntax nodes.

See Also
yang_find_syntax # Maybe this is the same as specnode?
clicon_dbget_xpath
xpath_vec
char* yang_key2str ( int  keyword)

Translate from RFC 6020 keywords to printable string. linear search,...

int yang_key_match ( yang_node *  yn,
char *  name 
)

Check if yang node yn has key-stmt as child which matches name

Parameters
[in]ynYang node with sub-statements (look for a key child)
[in]nameCheck if this name (eg "b") is a key in the yang key statement
Return values
-1Error
0No match
1Yes match
int yang_mandatory ( yang_stmt *  ys)

Return if this leaf is mandatory or not Note: one can cache this value in ys_cvec instead of functionally evaluating it.

Return values
1yang statement is leaf and it has a mandatory sub-stmt with value true
0The negation of conditions for return value 1.
int yang_parse ( clicon_handle  h,
const char *  yang_dir,
const char *  module,
const char *  revision,
yang_spec *  ysp 
)

Parse top yang module including all its sub-modules. Expand and populate yang tree

Parameters
hCLICON handle
yang_dirDirectory where all YANG module files reside
moduleName of main YANG module. More modules may be parsed if imported
revisionOptional module revision date
yspYang specification. Should ave been created by caller using yspec_new
Return values
0Everything OK
-1Error encountered The database symbols are inserted in alphabetical order. Find a yang module file, and then recursively parse all its imported modules. Calling order: yang_parse # Parse top-level yang module. Expand and populate yang tree yang_parse1 # Parse one yang module, go through its (sub)modules and parse them yang_parse2 # Find file from yang (sub)module yang_parse_file # Read yang file into a string yang_parse_str # Set up yacc parser and call it given a string clixon_yang_parseparse # Actual yang parsing using yacc
static yang_stmt* yang_parse1 ( clicon_handle  h,
const char *  yang_dir,
const char *  module,
const char *  revision,
yang_spec *  ysp 
)
static

Parse one yang module then go through (sub)modules and parse them recursively

Parameters
hCLICON handle
yang_dirDirectory where all YANG module files reside
moduleName of main YANG module. More modules may be parsed if imported
revisionOptional module revision date
yspYang specification. Should ave been created by caller using yspec_new
Return values
0Everything OK
-1Error encountered Find a yang module file, and then recursively parse all its imported modules. Calling order: yang_parse # Parse top-level yang module. Expand and populate yang tree yang_parse1 # Parse one yang module, go through its (sub)modules and parse them yang_parse2 # Find file from yang (sub)module yang_parse_file # Read yang file into a string yang_parse_str # Set up yacc parser and call it given a string clixon_yang_parseparse # Actual yang parsing using yacc
static yang_stmt* yang_parse2 ( clicon_handle  h,
const char *  yang_dir,
const char *  module,
const char *  revision,
yang_spec *  ysp 
)
static

Find and open yang file and then parse it

Parameters
hCLICON handle
yang_dirDirectory where all YANG module files reside
moduleName of main YANG module. More modules may be parsed if imported
revisionOptional module revision date
yspYang specification. Should ave been created by caller using yspec_new
Return values
0Everything OK
-1Error encountered module-or-submodule-name ['@' revision-date] ( '.yang' / '.yin' ) Calling order: yang_parse # Parse top-level yang module. Expand and populate yang tree yang_parse1 # Parse one yang module, go through its (sub)modules and parse them yang_parse2 # Find file from yang (sub)module yang_parse_file # Read yang file into a string yang_parse_str # Set up yacc parser and call it given a string clixon_yang_parseparse # Actual yang parsing using yacc
static yang_stmt* yang_parse_file ( clicon_handle  h,
FILE *  f,
const char *  name,
yang_spec *  ysp 
)
static

Read an opened file into a string and call yang string parsing

Similar to clicon_yang_str(), just read a file first (cloned from cligen)

Parameters
hCLICON handle
fOpen file handle
nameLog string, typically filename
yspYang specification. Should ave been created by caller using yspec_new
Return values
0Everything OK
-1Error encountered

The database symbols are inserted in alphabetical order. Calling order: yang_parse # Parse top-level yang module. Expand and populate yang tree yang_parse1 # Parse one yang module, go through its (sub)modules and parse them yang_parse2 # Find file from yang (sub)module yang_parse_file # Read yang file into a string yang_parse_str # Set up yacc parser and call it given a string clixon_yang_parseparse # Actual yang parsing using yacc

static int yang_parse_find_match ( clicon_handle  h,
const char *  yang_dir,
const char *  module,
cbuf *  fbuf 
)
static

No specific revision give. Match a yang file given dir and module

Parameters
[in]hCLICON handle
[in]yang_dirDirectory where all YANG module files reside
[in]moduleName of main YANG module.
[out]fbufBuffer containing filename
Return values
1Match founbd, Most recent entry returned in fbuf
0No matching entry found
-1Error
static yang_stmt* yang_parse_str ( clicon_handle  h,
char *  str,
const char *  name,
yang_spec *  yspec 
)
static

Parse a string containing a YANG spec into a parse-tree

Syntax parsing. A string is input and a syntax-tree is returned (or error). A variable record is also returned containing a list of (global) variable values. (cloned from cligen)

Parameters
hCLICON handle
strString of yang statements
nameLog string, typically filename
yspYang specification. Should ave been created by caller using yspec_new
Return values
0Everything OK
-1Error encountered Calling order: yang_parse # Parse top-level yang module. Expand and populate yang tree yang_parse1 # Parse one yang module, go through its (sub)modules and parse them yang_parse2 # Find file from yang (sub)module yang_parse_file # Read yang file into a string yang_parse_str # Set up yacc parser and call it given a string clixon_yang_parseparse # Actual yang parsing using yacc
int yang_print ( FILE *  f,
yang_node *  yn,
int  marginal 
)

Print yang specification to file

See Also
yang_print_cbuf
int yang_print_cbuf ( cbuf *  cb,
yang_node *  yn,
int  marginal 
)

Print yang specification to cligen buf

cbuf *cb = cbuf_new();
yang_print_cbuf(cb, yn, 0);
// output is in cbuf_buf(cb);
cbuf_free(cb);
See Also
yang_print
int yang_spec_main ( clicon_handle  h,
FILE *  f,
int  printspec 
)

Utility function for handling yang parsing and translation to key format

Parameters
hclicon handle
ffile to print to (if printspec enabled)
printspecprint database (YANG) specification as read from file
yang_node* yang_xpath ( yang_node *  yn,
char *  xpath 
)

Given an xpath (eg /a/b/c or a/b/c) find matching yang specification Note that xpath is defined for xml, and for instances of data, this is for specifications, sp expect some differences.

Parameters
[in]ynYang node tree
[in]xpathA limited xpath expression on the type a/b/c
Return values
NULLError, with clicon_err called
ysFirst yang node matching xpath
Note
: the identifiers in the xpath (eg a, b in a/b) can match the nodes defined in yang_xpath: container, leaf,list,leaf-list, modules, sub-modules Example: yn : module m { prefix b; container b { list c { key d; leaf d; }} } xpath = m/b/c, returns the list 'c'.
See Also
xpath_vec
clicon_dbget_xpath
yang_node* yang_xpath_abs ( yang_node *  yn,
char *  xpath 
)

Given an absolute xpath (eg /a/b/c) find matching yang specification

Parameters
[in]ynYang node
[in]xpathAbsolute xpath, ie /a/b
static yang_node* yang_xpath_vec ( yang_node *  yn,
char **  vec,
int  nvec 
)
static

All the work for yang_xpath. Ignore prefixes, see _abs

yang_stmt* yn_each ( yang_node *  yn,
yang_stmt *  ys 
)

Iterate through all yang statements from a yang node

Note that this is not optimized, one could use 'i' as index?

yang_stmt *ys = NULL;
while ((ys = yn_each(yn, ys)) != NULL) {
...ys...
}
int yn_insert ( yang_node *  yn_parent,
yang_stmt *  ys_child 
)

Insert yang statement as child of a parent yang_statement, last in list

Also add parent to child as up-pointer

static int yn_realloc ( yang_node *  yn)
static

Allocate larger yang statement vector adding empty field last

int ys_cp ( yang_stmt *  ynew,
yang_stmt *  yold 
)

Copy yang statement recursively from old to new

yang_stmt* ys_dup ( yang_stmt *  old)

Create a new yang node and copy the contents recursively from the original.

This may involve duplicating strings, etc. The new yang tree needs to be freed by ys_free(). The parent of new is NULL, it needs to be explicityl inserted somewhere

static int ys_flag_reset ( yang_stmt *  ys,
void *  arg 
)
static

Reset flag in complete tree, arg contains flag

int ys_free ( yang_stmt *  ys)

Free a tree of yang statements recursively

static int ys_free1 ( yang_stmt *  ys)
static

Free a single yang statement

static int ys_grouping_resolve ( yang_stmt *  ys,
char *  prefix,
char *  name,
yang_stmt **  ygrouping0 
)
static

Resolve a grouping name from a point in the yang tree

Return values
0OK, but ygrouping determines if a grouping was resolved or not
-1Error, with clicon_err called
yang_stmt* ys_module ( yang_stmt *  ys)

Find top module or sub-module. Note that ultimate top is yang spec

Parameters
[in]ysAny yang statement in a yang tree
Return values
ymodThe top module or sub-module
See Also
ys_spec
yang_stmt* ys_module_import ( yang_stmt *  ymod,
char *  prefix 
)

Given a module and a prefix, find the import statement fo that prefix Note, not the other module but the proxy import statement only

Parameters
[in]ytopyang module
yang_stmt* ys_new ( enum rfc_6020  keyw)
cg_var* ys_parse ( yang_stmt *  ys,
enum cv_type  cvtype 
)

Parse argument as CV and save result in yang cv variable

Note that some CV:s are parsed directly (eg fraction-digits) while others are parsed in third pass (ys_populate). The reason being that all information is not available in the first pass. Prefer to do stuff in ys_populate

int ys_parse_sub ( yang_stmt *  ys)

First round yang syntactic statement specific checks. No context checks.

Specific syntax checks and variable creation for stand-alone yang statements. That is, siblings, etc, may not be there. Complete checks are made in ys_populate instead.

The cv:s created in parse-tree as follows: fraction-digits : Create cv as uint8, check limits [1:8] (must be made in 1st pass)

See Also
ys_populate
static int ys_populate ( yang_stmt *  ys,
void *  arg 
)
static

Populate with cligen-variables, default values, etc. Sanity checks on complete tree.

We do this in 2nd pass after complete parsing to be sure to have a complete parse-tree See ys_parse_sub for first pass and what can be assumed After this pass, cv:s are set for LEAFs and LEAF-LISTs

static int ys_populate_identity ( yang_stmt *  ys,
void *  arg 
)
static

Sanity check yang type statement

static int ys_populate_leaf ( yang_stmt *  ys,
void *  arg 
)
static

Populate yang leafs after parsing. Create cv and fill it in.

Populate leaf in 2nd round of yang parsing, now that context is complete:

  1. Find type specification and set cv type accordingly
  2. Create the CV using cvtype and name it
  3. Check if default value. Here we parse the string in the default-stmt and add it to leafs cv.
  4. Check if leaf is part of list, if key exists mark leaf as key/unique XXX: extend type search
Parameters
[in]ysThe yang statement to populate.
[in]argA void argument not used
Return values
0OK
-1Error with clicon_err called
static int ys_populate_range ( yang_stmt *  ys,
void *  arg 
)
static

Populate range and length statements

Create cvec variables "range_min" and "range_max". Assume parent is type. Actually: min..max [| min..max]* where min,max is integer or keywords 'min' or 'max. We only allow one range, ie not 1..2|4..5

static int ys_populate_type ( yang_stmt *  ys,
void *  arg 
)
static

Sanity check yang type statement XXX: Replace with generic parent/child type-check

yang_spec* ys_spec ( yang_stmt *  ys)

Find top of tree, the yang specification

Parameters
[in]ysAny yang statement in a yang tree
Return values
yspecThe top yang specification
See Also
ys_module
int yspec_free ( yang_spec *  yspec)

Free a yang specification recursively

yang_spec* yspec_new ( void  )
char* ytype_id ( yang_stmt *  ys)
char* ytype_prefix ( yang_stmt *  ys)

Variable Documentation

const struct map_str2int ykmap[]
static