Blame src/extensions/yangdata.c

Packit 8fb591
/**
Packit 8fb591
 * @file yangdata.c
Packit 8fb591
 * @author Pavol Vican <vican.pavol@gmail.com>
Packit 8fb591
 * @brief libyang extension plugin - YANG DATA (RFC 8040)
Packit 8fb591
 *
Packit 8fb591
 * Copyright (c) 2018 CESNET, z.s.p.o.
Packit 8fb591
 *
Packit 8fb591
 * This source code is licensed under BSD 3-Clause License (the "License").
Packit 8fb591
 * You may not use this file except in compliance with the License.
Packit 8fb591
 * You may obtain a copy of the License at
Packit 8fb591
 *
Packit 8fb591
 *     https://opensource.org/licenses/BSD-3-Clause
Packit 8fb591
 */
Packit 8fb591
Packit 8fb591
#ifdef __GNUC__
Packit 8fb591
#  define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
Packit 8fb591
#else
Packit 8fb591
#  define UNUSED(x) UNUSED_ ## x
Packit 8fb591
#endif
Packit 8fb591
Packit 8fb591
#include <stdlib.h>
Packit 8fb591
#include "../extensions.h"
Packit 8fb591
Packit 8fb591
int check_node(struct lys_node *node);
Packit 8fb591
Packit 8fb591
/**
Packit 8fb591
 * @brief Callback to check that the yang-data can be instantiated inside the provided node
Packit 8fb591
 *
Packit 8fb591
 * @param[in] parent The parent of the instantiated extension.
Packit 8fb591
 * @param[in] parent_type The type of the structure provided as \p parent.
Packit 8fb591
 * @param[in] substmt_type libyang does not store all the extension instances in the structures where they are
Packit 8fb591
 *                         instantiated in the module. In some cases (see #LYEXT_SUBSTMT) they are stored in parent
Packit 8fb591
 *                         structure and marked with flag to know in which substatement of the parent the extension
Packit 8fb591
 *                         was originally instantiated.
Packit 8fb591
 * @return 0 - ok
Packit 8fb591
 *         1 - error
Packit 8fb591
 */
Packit 8fb591
int yang_data_position(const void * UNUSED(parent), LYEXT_PAR parent_type, LYEXT_SUBSTMT UNUSED(substmt_type))
Packit 8fb591
{
Packit 8fb591
    /* yang-data can appear only at the top level of a YANG module or submodule */
Packit 8fb591
    if (parent_type == LYEXT_PAR_MODULE) {
Packit 8fb591
        return 0;
Packit 8fb591
    } else {
Packit 8fb591
        return 1;
Packit 8fb591
    }
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
/* return values - 0 - OK
Packit 8fb591
 *                 1 - Something wrong
Packit 8fb591
 *                -1 - Absolute wrong
Packit 8fb591
 */
Packit 8fb591
int check_choice(struct lys_node *root) {
Packit 8fb591
    struct lys_node *node, *next;
Packit 8fb591
    int result = 1, tmp_result;
Packit 8fb591
Packit 8fb591
    LY_TREE_FOR_SAFE(root->child, next, node) {
Packit 8fb591
        tmp_result = (node->nodetype == LYS_CASE) ? check_node(node->child) : check_node(node);
Packit 8fb591
        if (tmp_result == -1) {
Packit 8fb591
            return -1;
Packit 8fb591
        } else if (tmp_result == 0) {
Packit 8fb591
            result = 0;
Packit 8fb591
        }
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    return result;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
/* return values - 0 - OK
Packit 8fb591
 *                 1 - Something wrong
Packit 8fb591
 *                -1 - Absolute wrong
Packit 8fb591
 */
Packit 8fb591
int check_node(struct lys_node *node) {
Packit 8fb591
Packit 8fb591
    int result = 0;
Packit 8fb591
Packit 8fb591
    if (node == NULL) {
Packit 8fb591
        return 1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    /* check nodes and find only one container */
Packit 8fb591
    if (node->nodetype == LYS_CHOICE) {
Packit 8fb591
        result = check_choice(node);
Packit 8fb591
    } else if (node->nodetype == LYS_USES) {
Packit 8fb591
        result = check_node(((struct lys_node_uses*)node)->grp->child);
Packit 8fb591
    } else if (node->nodetype != LYS_CONTAINER || (node->next != NULL || node->prev != node)) {
Packit 8fb591
        result = -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    return result;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
Packit 8fb591
void remove_iffeature(struct lys_iffeature **iffeature, uint8_t *iffeature_size, struct ly_ctx *ctx) {
Packit 8fb591
Packit 8fb591
    lys_iffeature_free(ctx, *iffeature, *iffeature_size, 0, NULL);
Packit 8fb591
    *iffeature_size = 0;
Packit 8fb591
    *iffeature = NULL;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
void remove_iffeature_type(struct lys_type *type, struct ly_ctx *ctx) {
Packit 8fb591
    unsigned int i;
Packit 8fb591
Packit 8fb591
    if (type->base == LY_TYPE_ENUM) {
Packit 8fb591
        for (i = 0; i < type->info.enums.count; ++i) {
Packit 8fb591
            remove_iffeature(&type->info.enums.enm[i].iffeature, &type->info.enums.enm[i].iffeature_size, ctx);
Packit 8fb591
        }
Packit 8fb591
    } else if (type->base == LY_TYPE_BITS) {
Packit 8fb591
        for (i = 0; i < type->info.bits.count; ++i) {
Packit 8fb591
            remove_iffeature(&type->info.bits.bit[i].iffeature, &type->info.bits.bit[i].iffeature_size, ctx);
Packit 8fb591
        }
Packit 8fb591
    }
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
/* fix schema - ignore config flag, iffeature */
Packit 8fb591
void fix_schema(struct lys_node *root, struct ly_ctx *ctx) {
Packit 8fb591
    struct lys_node *node, *next;
Packit 8fb591
    struct lys_node_container *cont;
Packit 8fb591
    struct lys_node_rpc_action *action;
Packit 8fb591
    struct lys_node_grp *grp;
Packit 8fb591
    struct lys_node_uses *uses;
Packit 8fb591
    int i;
Packit 8fb591
Packit 8fb591
    LY_TREE_DFS_BEGIN(root, next, node) {
Packit 8fb591
        /* ignore config flag */
Packit 8fb591
        node->flags = node->flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET));
Packit 8fb591
        remove_iffeature(&node->iffeature, &node->iffeature_size, ctx);
Packit 8fb591
        switch (node->nodetype) {
Packit 8fb591
            case LYS_CONTAINER:
Packit 8fb591
                cont = (struct lys_node_container *)node;
Packit 8fb591
                for (i = 0; i < cont->tpdf_size; ++i) {
Packit 8fb591
                    remove_iffeature_type(&cont->tpdf[i].type, ctx);
Packit 8fb591
                }
Packit 8fb591
                break;
Packit 8fb591
            case LYS_LEAF:
Packit 8fb591
                remove_iffeature_type(&((struct lys_node_leaf *)node)->type, ctx);
Packit 8fb591
                break;
Packit 8fb591
            case LYS_LEAFLIST:
Packit 8fb591
                remove_iffeature_type(&((struct lys_node_leaflist *)node)->type, ctx);
Packit 8fb591
                break;
Packit 8fb591
            case LYS_ACTION:
Packit 8fb591
            case LYS_NOTIF:
Packit 8fb591
                action = (struct lys_node_rpc_action *)node;
Packit 8fb591
                for (i = 0; i < action->tpdf_size; ++i) {
Packit 8fb591
                    remove_iffeature_type(&action->tpdf[i].type, ctx);
Packit 8fb591
                }
Packit 8fb591
                break;
Packit 8fb591
            case LYS_GROUPING:
Packit 8fb591
                grp = (struct lys_node_grp *)node;
Packit 8fb591
                for (i = 0; i < grp->tpdf_size; ++i) {
Packit 8fb591
                    remove_iffeature_type(&grp->tpdf[i].type, ctx);
Packit 8fb591
                }
Packit 8fb591
                break;
Packit 8fb591
            case LYS_USES:
Packit 8fb591
                uses = (struct lys_node_uses *)node;
Packit 8fb591
                for (i = 0; i < uses->augment_size; ++i) {
Packit 8fb591
                    remove_iffeature(&uses->augment[i].iffeature, &uses->augment[i].iffeature_size, ctx);
Packit 8fb591
                    fix_schema(uses->augment[i].child, ctx);
Packit 8fb591
                }
Packit 8fb591
                for (i = 0; i < uses->refine_size; ++i) {
Packit 8fb591
                    remove_iffeature(&uses->refine[i].iffeature, &uses->refine[i].iffeature_size, ctx);
Packit 8fb591
                }
Packit 8fb591
                break;
Packit 8fb591
            default:
Packit 8fb591
                break;
Packit 8fb591
        }
Packit 8fb591
        LY_TREE_DFS_END(root, next, node)
Packit 8fb591
    }
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
int yang_data_result(struct lys_ext_instance *ext) {
Packit 8fb591
    struct lys_node **root;
Packit 8fb591
Packit 8fb591
    root = lys_ext_complex_get_substmt(LY_STMT_CONTAINER, (struct lys_ext_instance_complex *)ext, NULL);
Packit 8fb591
    if (!root || !(*root) || (*root)->next != NULL || check_node(*root)) {
Packit 8fb591
        return 1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    fix_schema(*root, ext->def->module->ctx);
Packit 8fb591
    return 0;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
struct lyext_substmt yang_data_substmt[] = {
Packit 8fb591
    {LY_STMT_USES,        0, LY_STMT_CARD_OPT},
Packit 8fb591
    {LY_STMT_CONTAINER,   0, LY_STMT_CARD_OPT},
Packit 8fb591
    {LY_STMT_CHOICE,      0, LY_STMT_CARD_OPT},
Packit 8fb591
    {0, 0, 0} /* terminating item */
Packit 8fb591
};
Packit 8fb591
Packit 8fb591
/**
Packit 8fb591
 * @brief Plugin for the RFC 8040 restconf extension
Packit 8fb591
 */
Packit 8fb591
struct lyext_plugin_complex yang_data = {
Packit 8fb591
    .type = LYEXT_COMPLEX,
Packit 8fb591
    .flags = 0,
Packit 8fb591
    .check_position = &yang_data_position,
Packit 8fb591
    .check_result = &yang_data_result,
Packit 8fb591
    .check_inherit = NULL,
Packit 8fb591
    .valid_data = NULL,
Packit 8fb591
    /* specification of allowed substatements of the extension instance */
Packit 8fb591
    .substmt = yang_data_substmt,
Packit 8fb591
Packit 8fb591
    /* final size of the extension instance structure with the space for storing the substatements */
Packit 8fb591
    .instance_size = (sizeof(struct lys_ext_instance_complex) - 1) + 2 * sizeof(void*)
Packit 8fb591
};
Packit 8fb591
Packit 8fb591
/**
Packit 8fb591
 * @brief list of all extension plugins implemented here
Packit 8fb591
 *
Packit 8fb591
 * MANDATORY object for all libyang extension plugins, the name must match the <name>.so
Packit 8fb591
 */
Packit 8fb591
struct lyext_plugin_list yangdata[] = {
Packit 8fb591
    {"ietf-restconf", "2017-01-26", "yang-data", (struct lyext_plugin*)&yang_data},
Packit 8fb591
    {NULL, NULL, NULL, NULL} /* terminating item */
Packit 8fb591
};