blob: c958e0d52dfbcfb25902d3db591f0e0d33167973 [file] [log] [blame]
/**
* @file nacm.c
* @author Radek Krejci <rkrejci@cesnet.cz>
* @brief libyang extension plugin - NACM (RFC 6536)
*
* Copyright (c) 2016-2017 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#ifdef __GNUC__
# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
#else
# define UNUSED(x) UNUSED_ ## x
#endif
#include <stdlib.h>
#include "../extensions.h"
/**
* @brief Callback to check that the NACM extension can be instantiated inside the provided node
*
* @param[in] parent The parent of the instantiated extension.
* @param[in] parent_type The type of the structure provided as \p parent.
* @param[in] substmt_type libyang does not store all the extension instances in the structures where they are
* instantiated in the module. In some cases (see #LYEXT_SUBSTMT) they are stored in parent
* structure and marked with flag to know in which substatement of the parent the extension
* was originally instantiated.
* @return 0 - ok
* 1 - error
*/
int nacm_position(const void *parent, LYEXT_PAR parent_type, LYEXT_SUBSTMT UNUSED(substmt_type))
{
if (parent_type != LYEXT_PAR_NODE) {
return 1;
}
if (((struct lys_node*)parent)->nodetype &
(LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE | LYS_ANYDATA | LYS_AUGMENT | LYS_CASE |
LYS_USES | LYS_RPC | LYS_ACTION | LYS_NOTIF )) {
return 0;
} else {
return 1;
}
}
/**
* @brief Callback to decide whether the extension will be inherited into the provided schema node. The extension
* instance is always from some of the node's parents.
*
* @param[in] ext Extension instance to be inherited.
* @param[in] node Schema node where the node is supposed to be inherited.
* @return 0 - yes
* 1 - no (do not process the node's children)
* 2 - no, but continue with children
*/
int nacm_inherit(struct lys_ext_instance *UNUSED(ext), struct lys_node *node)
{
/* libyang already checks if there is explicit instance of the extension already present,
* in such a case the extension is never inherited and we don't need to check it here */
/* inherit into all the schema nodes that can be instantiated in data trees */
if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_ACTION | LYS_NOTIF )) {
return 0;
} else {
return 2;
}
}
/**
* @brief Callback to check that the extension instance is correct - have
* the valid argument, cardinality, etc.
*
* In NACM case, we are checking only the cardinality.
*
* @param[in] ext Extension instance to be checked.
* @return 0 - ok
* 1 - error
*/
int
nacm_cardinality(struct lys_ext_instance *ext)
{
struct lys_ext_instance **extlist;
uint8_t extsize, i, c;
char *path;
if (ext->flags & LYEXT_OPT_PLUGIN1) {
/* already checked */
ext->flags &= ~LYEXT_OPT_PLUGIN1;
return 0;
}
extlist = ((struct lys_node *)ext->parent)->ext;
extsize = ((struct lys_node *)ext->parent)->ext_size;
for (i = c = 0; i < extsize; i++) {
if (extlist[i]->def == ext->def) {
/* note, that it is not necessary to check also ext->insubstmt since
* nacm_position() ensures that NACM's extension instances are placed only
* in schema nodes */
if (extlist[i] != ext) {
/* do not mark the instance being checked */
extlist[i]->flags |= LYEXT_OPT_PLUGIN1;
}
c++;
}
}
if (c > 1) {
path = lys_path((struct lys_node *)(ext->parent), LYS_PATH_FIRST_PREFIX);
LYEXT_LOG(ext->module->ctx, LY_LLERR, "NACM", "Extension nacm:%s can appear only once, but %d instances found in %s.",
ext->def->name, c, path);
free(path);
return 1;
} else {
return 0;
}
}
/**
* @brief Plugin for the NACM's default-deny-write extension
*/
struct lyext_plugin nacm_deny_write = {
.type = LYEXT_FLAG,
.flags = LYEXT_OPT_INHERIT,
.check_position = &nacm_position,
.check_result = &nacm_cardinality,
.check_inherit = &nacm_inherit
};
/**
* @brief Plugin for the NACM's default-deny-all extension
*/
struct lyext_plugin nacm_deny_all = {
.type = LYEXT_FLAG,
.flags = LYEXT_OPT_INHERIT,
.check_position = &nacm_position,
.check_result = &nacm_cardinality,
.check_inherit = &nacm_inherit
};
/**
* @brief list of all extension plugins implemented here
*
* MANDATORY object for all libyang extension plugins, the name must match the <name>.so
*/
struct lyext_plugin_list nacm[] = {
{"ietf-netconf-acm", "2012-02-22", "default-deny-write", &nacm_deny_write},
{"ietf-netconf-acm", "2012-02-22", "default-deny-all", &nacm_deny_all},
{NULL, NULL, NULL, NULL} /* terminating item */
};