
YumaPro yp-system API Guide¶
yp-system Introduction¶
This document contains a quick reference for the API callback interface for the yp-system component in the netconfd-pro server.
The netconfd-pro server supports an external vendor library that is loaded at boot-time by the server, similar to a SIL for a YANG module. This library code is run in the context of the main server process. It is used to hook vendor-specific functions into the server,.
The following tasks are supported by the yp-system library interface:
yp-system External Interface : Creating and using the general system SIL library
YP-HA Interface : Provide an external controller for changing the YP-HA server role
Access Control Model Interface : Provide an external access control system instead of NACM
SYSLOG Interface : Provide an external syslog interface instead of the Linux API
System Callback Functions : Provide server callbacks not specific to a single YANG module
The default system library is located in called libyp_system.so, and
it is located in the library path, such as
/usr/lib/yumapro/libyp_system.so
.
There is an example yp-system library in the 'libsystem' directory
of the YumaPro source tree. This file in the 'src' directory called
example-system.c
contains some stub code showing how this library
is used.
Copy and Setup the libsystem subtree¶
The default library created by building libsystem is libyp_system-example.so
.
This is not the correct filename, in order to prevent the real yp-server library
from being overwritten by the empty example library, if “make install” is run.
The 'libsystem' subtree should be copied to your own development area and modified.
#
# to make a real library, copy this directory contents
# to a new location and change yp-system-example to yp_system
# in the SUBDIR_NM macro below
#
# SUBDIR_NM=yp_system
#
SUBDIR_NM=yp_system-example
Change the string yp-system-example
to yp-system
in the
src/Makefile
in the copy of libsystem.
yp-system¶
The following API functions should be defined in all yp-library implementations:
yp_system_init_profile: Change default settings in the server profile defined in agt/agt.h
yp_system_init1: Phase 1 initialization function
yp_system_init2: Phase 2 initialization function
yp_system_cleanup: Server cleanup function
The following example shows example-system.h
contents from the
libsystem/src
directory:
#ifndef _H_example_system
#define _H_example_system
/*
* Copyright (c) 2012 - 2014, YumaWorks, Inc., All Rights Reserved.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _H_agt
#include "agt.h"
#endif
#ifndef _H_status
#include "status.h"
#endif
/* system init server profile callback
*
* Initialize the server profile if needed
*
* INPUTS:
* profile == server profile to change if needed
*/
extern void yp_system_init_profile (agt_profile_t *profile);
/* system init1 callback
* init1 system call
* this callback is invoked twice; before and after CLI processing
* INPUTS:
* pre_cli == TRUE if this call is before the CLI parameters
* have been read
* FALSE if this call is after the CLI parameters
* have been read
* RETURNS:
* status; error will abort startup
*/
extern status_t yp_system_init1 (boolean pre_cli);
/* system init2 callback
* init2 system call
* this callback is invoked twice; before and after
* load_running_config processing
*
* INPUTS:
* pre_load == TRUE if this call is before the running config
* has been loaded
* FALSE if this call is after the running config
* has been loaded
* RETURNS:
* status; error will abort startup
*/
extern status_t yp_system_init2 (boolean pre_load);
/* system cleanup callback
* this callback is invoked once during agt_cleanup
*/
extern void yp_system_cleanup (void);
#endif
yp_system_init_profile¶
This function is used to modify the defaults in the agt_profile_t Struct used by the server. This allows features and various behavior to be configured. Many of these settings have associated CLI/conf parameters that can change the default at run-time. Refer to the agt_profile_t Struct section for details on the contents of the Agent Profile structure.
-
typedef void (*agt_system_init_profile_fn_t)(agt_profile_t *profile)¶
system init server profile callback
Initialize the server profile if needed
- Param profile
server profile to change if needed
The contents of this function should set profile fields as needed.
Note that if the field has a CLI override parameter with a default value, then the YANG default for that parameter needs to be changed if the profile default is changed.
Example Profile Initialization Function
This example profile initialization function shows how to disable all the Yuma YANG modules:
void yp_system_init_profile (agt_profile_t *profile);
{
profile->agt_use_yuma_arp = false;
profile->agt_use_yuma_if = false;
profile->agt_use_yuma_mysession = false;
profile->agt_use_yuma_proc = false;
profile->agt_use_yuma_proc = false;
} /* yp_system_init_profile */
yp_system_init1¶
This function is used to initialize the server during phase 1 initialization.
This function is called twice during system initialization:
pre_cli = TRUE: Called before the CLI and conf file parameters have been processed
pre_cli = FALSE: Called after the CLI and conf file parameters have been processed
-
typedef status_t (*agt_system_init1_fn_t)(boolean pre_cli)¶
system init1 callback
init1 system call this callback is invoked twice; before and after CLI processing
- Param pre_cli
TRUE if this call is before the CLI parameters have been read
FALSE if this call is after the CLI parameters have been read
- Return
status; error will abort startup
This function should register system callback functions and setup the system.
The first time the function is called the pre_cli flag is true. This is before the CLI and config file parameters have been applied. The second time the function is called the pre_cli flag is false. This is after the CLI and config file parameters have been applied.
Example Phase 1 Initialization Function
This example phase 1 initialization function shows setup of external vendor logging and external access control model callbacks :
/* system init1 callback
* init1 system call
* this callback is invoked twice; before and after CLI processing
* INPUTS:
* pre_cli == TRUE if this call is before the CLI parameters
* have been read
* FALSE if this call is after the CLI parameters
* have been read
* RETURNS:
* status; error will abort startup
*/
status_t yp_system_init1 (boolean pre_cli)
{
if (pre_cli) {
// example -- register vendor callback to consume logging output.
log_vendor_extern_register_send_fn(log_vendor_send_fn);
} else {
// example -- external NACM callbacks
// load module for external module
// with ncxmod_load_module
// register the external ACM callbacks
// this will have no affect unless the
// yp_system_init_profile fn sets the
// agt_acm_model to AGT_ACM_MODEL_EXTERNAL
agt_acm_extern_register_callbacks(acm_extern_rpc,
acm_extern_notif,
acm_extern_write,
acm_extern_read);
}
return NO_ERR;
} /* yp_system_init1 */
yp_system_init2¶
This function is used to initialize the server during phase 2 initialization. This function is invoked after all phase 1 initialization has been successfully completed.
The first time the function is called the pre_load flag is true. This is before the running configuration has been initialized. The second time the function is called the pre_load flag is false. This is after the running configuration has been initialized with configuration from non-volatile storage and YANG defaults.
This function should initialize global callbacks based configuration settings.
-
typedef status_t (*agt_system_init2_fn_t)(boolean pre_load)¶
system init2 callback
init2 system call this callback is invoked twice; before and after load_running_config processing
- Param pre_load
TRUE if this call is before the running config has been loaded
FALSE if this call is after the running config has been loaded
- Return
status; error will abort startup
Example Phase 2 Initialization Function
This example phase 2 initialization function shows the general structure of the code for this function.
/* system init2 callback
* init2 system call
* this callback is invoked twice; before and after
* load_running_config processing
*
* INPUTS:
* pre_load == TRUE if this call is before the running config
* has been loaded
* FALSE if this call is after the running config
* has been loaded
* RETURNS:
* status; error will abort startup
*/
status_t yp_system_init2 (boolean pre_load)
{
log_debug("\nyp_system init2\n");
if (pre_load) {
;
} else {
;
}
return NO_ERR;
}
yp_system_cleanup¶
This function is used to cleanup the system when the server is shutting down or restarting.
-
typedef void (*agt_system_cleanup_fn_t)(void)¶
system cleanup callback
this callback is invoked once during agt_cleanup
Example Phase 2 Initialization Function
This example cleanup function shows the general structure of the code for this function.
/* system cleanup callback
* this callback is invoked once during agt_cleanup
*/
void yp_system_cleanup (void)
{
log_debug("\nyp_system cleanup\n");
/* put your cleanup function calls here */
} /* system cleanup callback */
YP-HA Interface¶
The High Availability features in the netconfd-pro server can be accessed from the yp-system library.
There are two functions that call be called from the “init1” or “init2” phases in the yp-system library initialization. They can also be called from an agt_timer callback function during system run time.
Normally when the server running with YP-HA enabled (--ha-enabled=true), the server will wait until it is told which HA role should be used (active or standby). The :--ha-initial-active CLI parameter can be used to hard-wire the YA role in the configuration. This should only be used for debugging. In production networks, the HA management system should signal all the HA role changes to the server.
agt_ha_role_t¶
The 'agt_ha_role_t' is an enumeration specifying the different YP-HA roles.
YP-HA Interface Functions¶
The YP-HA role can be set from internal API functions of from the DB-API subsystem interface, using the “yp-ha-role” message.
agt_yp_ha_get_role¶
The 'agt_yp_ha_get_role' function is used to retrieve the current YP-HA role used by the server.
-
agt_ha_role_t agt_yp_ha_get_role(void)¶
Get the YP-HA server role for this server.
- Returns
server role enum
agt_yp_ha_be_active¶
The 'agt_yp_ha_be_active' function is used to tell the server to be the active server in the YP-HA protocol.
-
status_t agt_yp_ha_be_active(void)¶
Put this server in YP-HA Active mode.
- Returns
status
agt_yp_ha_be_standby¶
The 'agt_yp_ha_be_standby' function is used to tell the server to be a standby server in the YP-HA protocol.
-
status_t agt_yp_ha_be_standby(const xmlChar *new_server_id)¶
Put this server in YP-HA Standby mode.
- Parameters
new_server_id -- server-id of the new active server
- Returns
status NO_ERR if this server able to enter YP-HA Standby mode
agt_yp_ha_be_none¶
The 'agt_yp_ha_be_none' function is used to tell the server to leave its current YP-HA role, go offline, and wait for a new YP-HA role to be set.
-
status_t agt_yp_ha_be_none(void)¶
Put this server in WAIT_ROLE state.
- Returns
status
DB-API <yp-ha-role> Event Message¶
The DB-API service has a new utility function to set the YP-HA role on the local server.
The <yp-ha-mode> message is sent from a subsystem to the main server. It has 2 variants. Either the “go-active” or the “go-standby” variant is sent.
container yp-ha-mode {
description
"Message type: subsys-event;
Purpose: send mode change event to the server
Expected Response Message: none";
choice action {
mandatory true;
leaf go-active {
type empty;
description "Become the YP-HA active server";
}
container go-standby {
description "Become a YP-HA standby server";
leaf new-active {
type string;
mandatory true;
description
"Server name of the active server to use";
}
}
}
} // container yp-ha-mode
Example message to set the YP-HA Active mode:
<?xml version="1.0" encoding="UTF-8"?>
<ycontrol xmlns="http://yumaworks.com/ns/yumaworks-ycontrol">
<message-id>2</message-id>
<message-type>subsys-event</message-type>
<server-id>ha-1</server-id>
<subsys-id>subsys1</subsys-id>
<service-id>db-api</service-id>
<payload>
<db-api xmlns="http://yumaworks.com/ns/yumaworks-db-api">
<yp-ha-mode>
<go-active/>
</yp-ha-mode>
</db-api>
</payload>
</ycontrol>
Access Control Model Interface¶
The netconfd-pro server supports 2 different access control models:
ietf: Use the ietf-netconf-acm.yang module defined in RFC 8341
external: an external data model provided by the vendor is used
If the 'external' mode is used, then ACM callback functions must be registered with yp-system API functions that the server needs to validate the following types of client access:
protocol operation requests
database read and write requests
notification delivery
Register ACM Callback Functions¶
The function 'agt_acm_extern_register_callbacks' in
agt/agt_acm_extern.h
is used by the external system code to register
its own callback functions to handle access control requests. These
functions are used by the system instead of its own access control cache
and data model.
If the external access control method is selected in the system initialization then these callback functions MUST be provided or all access requests will be granted by default!
-
void agt_acm_extern_register_callbacks(agt_acm_extern_rpc_fn_t rpcfn, agt_acm_extern_notif_fn_t notfn, agt_acm_extern_write_fn_t writefn, agt_acm_extern_read_fn_t readfn)¶
Register the external callbacks for ACM implementation.
A NULL callback means that type of access will always be granted!!!
- Parameters
rpcfn -- check-rpc function callback
notfn -- check-notification function callback
writefn -- check-val-write function callback
readfn -- check-val-write function callback
The following functions must be registered:
RPC Request Callback Function
Notification Send Callback Function
Database Write Request Callback Function
Database Read Request Callback Function
The following example "init1" function shows how this function might be used:
status_t yp_system_init1 (boolean pre_cli)
{
log_debug("\nyp_system init1\n");
if (pre_cli) {
;
} else {
// example -- external NACM callbacks
// load module for external module
// with ncxmod_load_module
// register the external ACM callbacks
// this will have no affect unless the
// yp_system_init_profile fn sets the
// agt_acm_model to AGT_ACM_MODEL_EXTERNAL
agt_acm_extern_register_callbacks(acm_extern_rpc,
acm_extern_notif,
acm_extern_write,
acm_extern_read);
}
return NO_ERR;
}
RPC Request¶
Checks if the user is allowed to invoke the specified YANG-defined protocol operation. The 'agt_acm_extern_rpc_fn_t' template is used for this callback.
-
typedef boolean (*agt_acm_extern_rpc_fn_t)(xml_msg_hdr_t *msg, const xmlChar *user, const obj_template_t *rpcobj)¶
Check if the specified user is allowed to invoke an RPC.
- Param msg
XML header in incoming message in progress
- Param user
user name string
- Param rpcobj
obj_template_t for the RPC method to check
- Return
TRUE if user allowed invoke this RPC; FALSE otherwise
This example RPC Request callback can be found in example-system.c:
static boolean
acm_extern_rpc (xml_msg_hdr_t *msg,
const xmlChar *user,
const obj_template_t *rpcobj)
{
(void)msg;
const xmlChar *modname = obj_get_mod_name(rpcobj);
const xmlChar *objname = obj_get_name(rpcobj);
log_debug("\nChecking RPC access for user %s to operation '%s:%s'",
user, modname, objname);
// check access here
log_debug("\nacm_extern_rpc: return OK\n");
return TRUE;
} /* acm_extern_rpc */
Notification Send¶
Checks if the user is allowed to receive the specified YANG-defined notification event. The 'agt_acm_extern_notif_fn_t' template is used for this callback.
-
typedef boolean (*agt_acm_extern_notif_fn_t)(const xmlChar *user, const obj_template_t *notifobj)¶
Check if the specified user is allowed to receive a notification event.
- Param user
user name string
- Param notifobj
obj_template_t for the notification event to check
- Return
TRUE if user allowed receive this notification event
FALSE otherwise
This example Notification Send callback can be found in example-system.c:
static boolean
acm_extern_notif (const xmlChar *user,
const obj_template_t *notifobj)
{
const xmlChar *modname = obj_get_mod_name(rpcobj);
const xmlChar *objname = obj_get_name(rpcobj);
log_debug("\nChecking Notification access for "
"user %s to event '%s:%s'",
user, modname, objname);
// check access here
log_debug("\nacm_extern_notif: return OK\n");
return TRUE;
} /* acm_extern_notif */
Database Write¶
Checks if the user is allowed to edit the specified YANG-defined data node. The 'agt_acm_extern_write_fn_t' template is used for this callback.
-
typedef boolean (*agt_acm_extern_write_fn_t)(xml_msg_hdr_t *msg, const xmlChar *user, const val_value_t *newval, const val_value_t *curval, op_editop_t editop)¶
Check if the specified user is allowed to access a value node.
The val->obj template will be checked against the val->editop requested access and the user's configured max-access
- Param msg
XML header from incoming message in progress
- Param newval
in progress to check
(may be NULL, if curval set)
- Param curval
in progress to check
(may be NULL, if newval set)
- Param val
val_value_t in progress to check
- Param editop
requested CRUD operation
- Return
TRUE if user allowed this level of access to the value node
This example Database Write callback can be found in example-system.c:
static boolean
acm_extern_write (xml_msg_hdr_t *msg,
const xmlChar *user,
const val_value_t *newval,
const val_value_t *curval,
op_editop_t editop)
{
(void)msg;
(void)user;
(void)newval;
(void)curval;
(void)editop;
log_debug("\nacm_extern_write: return OK\n");
return TRUE;
} /* acm_extern_write */
Database Read¶
Checks if the user is allowed to read the specified YANG-defined data node. The 'agt_acm_extern_read_fn_t' template is used for this callback.
-
typedef boolean (*agt_acm_extern_read_fn_t)(xml_msg_hdr_t *msg, const xmlChar *user, const val_value_t *val)¶
Check if the specified user is allowed to read a value node.
- Param msg
XML header from incoming message in progress
- Param user
user name string
- Param val
val_value_t in progress to check
- Return
TRUE if user allowed read access to the value node
This example Database Write callback can be found in example-system.c:
static boolean
acm_extern_read (xml_msg_hdr_t *msg,
const xmlChar *user,
const val_value_t *val)
{
(void)msg;
(void)user;
(void)val;
log_debug("\nacm_extern_read: return OK\n");
return TRUE;
} /* acm_extern_read */
Syslog Interface¶
The external syslog interface allows a vendor-specific syslog send function to be used instead of the Linux system syslog daemon. The yp_library user library code can be used to initialize an external syslog send function.
The external syslog send function must follow the C function templates
defined in ncx/log_vendor_extern.h
:
logfn_vendor_init1_t: Phase 1 initialization function
logfn_vendor_send_t: syslog send function
logfn_vendor_cleanup_t: Termination cleanup function
The 'example-system C and H files in the yp-system directory contains example usage of these callback functions.
When the vendor callback is invoked, the vendor code should translate the YumaPro application parameters into an "application" and/or "facility" equivalent appropriate to the vendor logging schema. Likewise, it should translate the YumaPro level parameters into a "message type/level" appropriate to its own requirements.
The following H files need to be included to use the functions in this section:
#include "log.h"
#include "log_vendor.h"
#include "log_vendor_extern.h"
logfn_vendor_send_t¶
This is the Logging Send function, called by the server when a SYSLOG message needs to be sent.
-
typedef void (*logfn_vendor_send_t)(log_debug_app_t app, log_debug_t level, const char *fstr, va_list args)¶
Vendor Logging Send Callback.
- Param app
YumaPro application (such as netconfd-pro or yangcli-pro) This info is already known to syslog via the connect.
- Param level
YumaPro log message level. This will be translated appropriately into a syslog equivalent
- Param fstr
start ptr to format string
- Param args
va_list
The following log send function can be found in example-system.c:
static void
log_vendor_send_fn (log_debug_app_t app,
log_debug_t level,
const char *fstr,
va_list args)
{
(void)app;
(void)level;
(void)fstr;
(void)args;
return;
}
System Callbacks¶
The callback functions described in this section are invoked as part of normal server operation.
They can be registered from the yp-system library module or a SIL module. Some internal functions are documented as well. These are needed by the system and multiple callbacks are not supported.
Refer to the file
/usr/share/yumapro/src/libsystem/src/example-system.c
for examples
of the callbacks in this section.
Note
System Callback code can be in a SIL library or the yp-system library.
API |
Description |
---|---|
cfg_reload_candidate_cb_t: Invoked each time the candidate datastore is reloaded from the running datastore, such as the <discard-changes> operation. |
|
ncx_load_cbfn_t: Invoked when a module is loaded into the server. |
|
ncx_unload_cbfn_t: Invoked when a module is unloaded from the server. |
|
agt_replay_fn_t: Invoked when a configuration replay procedure is started or finished. |
|
agt_nvload_fn_t: Invoked when the server needs to retrieve the configuration contents from non-volatile storage. |
|
agt_nvsave_fn_t: Invoked when the configuration needs to be saved to Non-Volatile storage. |
|
agt_timer_fn_t: Invoked periodically (1-shot or repeat) to do a short amount of work, and not block the running process. |
|
agt_cb_session_hook_t: Invoked when a session starts and ends. |
|
agt_cb_shutdown_t: Invoked when the server is about to restart or shutdown. |
|
agt_cb_command_complete_t: Invoked when the server has completed an RPC operation and the response has been generated to the client (may not have been sent yet). |
|
agt_acm_group_cbfn_t: Invoked when the server creates a new client session for NETCONF or RESTCONF sessions. It is used to retrieve a list of group names that should be used, as defined in RFC 8341 |
|
Invoked when a data node needs to be processed to process the value as it is being created. |
Candidate Reload Callback¶
The Candidate Reload callback is an internal system callback that is used to clear some cached validation data when the running configuration is loaded into to candidate datastore.
Note
This is an internal API and cannot be replaced. Do not use.
There can be one callback registered to be invoked each time the candidate datastore is reloaded from the running datastore, such as the <discard-changes> operation, or anytime the candidate is filled in from <startup>, <running>, or inline configuration.
If the server is run with the :writable-running capability the callback will not be available since the <candidate> datastore is not present when the capability is used. The --target CLI parameter is used to control this behavior.
Module Load Callback¶
The Module Load callback is a user/system callback that is invoked when a YANG module is loaded into the server. This callback is only invoked for main modules, not submodules.
The following function template definition is used for Module Load callback functions:
-
typedef void (*ncx_load_cbfn_t)(ncx_module_t *mod)¶
user function callback template when a module is loaded into the system
ncx_load_cbfn_t
Run an instrumentation-defined function for a 'module-loaded' event
- Param mod
module that was added to the registry
The 'mod' pointer represents a module control block structure that is defined in the
netconf/src/ncx/ncxtypes.h
.This control block is a representation of one module or submodule during and after parsing.
It provides access to the module specific information, such as module name, revision, prefix, and other module specific information.
Note: do not alter any fields in this structure
Module Load Callback Initialization and Cleanup¶
The 'ncx_set_load_callback' function is used to declare the Module Load callback. The registration can be done during the Initialization Phase 2 after the running configuration has been loaded from the startup file. It can actually be done at any time, as needed.
-
status_t ncx_set_load_callback(ncx_load_cbfn_t cbfn)¶
Set the callback function for a load-module event.
- Parameters
cbfn -- callback function to use
- Returns
status
Example registration function usage:
static status_t interfaces_init2 (void)
{
// ...
/* register load module callback */
res = ncx_set_load_callback(add_module_callback);
if (res != NO_ERR) {
return res;
}
// ...
}
The 'ncx_clear_load_callback' function is used to unload the Module Load callback.
-
void ncx_clear_load_callback(ncx_load_cbfn_t cbfn)¶
Clear the callback function for a load-module event.
- Parameters
cbfn -- callback function to use
Example un-register function usage:
void interfaces_cleanup (void)
{
// ...
ncx_clear_load_callback(add_module_callback);
...
}
Module Load Callback Function Example¶
The 'load_module_callback' function is used to to record a backptr for each module or imported module that is encountered during the <load> operation.
static void load_module_callback (ncx_module_t *mod)
{
ncx_backptr_t *backptr = ncx_new_backptr(mod);
if (backptr == NULL) {
log_error("\nError: malloc backptr failed");
return;
}
dlq_enque(backptr, &added_moduleQ);
} /* load_module_callback */
The 'do_load_module' function is located in agt/agt_ncx_load.c
.
It is used to load a module at runtime.
It does the following operations:
registers the callback
saves backptrs during the module load
reads the saved backptrs after the module load
unregisters the callback
cleans up the saved backptrs
static status_t
do_module_load (ses_cb_t *scb,
rpc_msg_t *msg,
const xmlChar *modname,
const xmlChar *revision,
ncx_module_t **retmod)
{
boolean callback_loaded = FALSE;
ncx_module_t *mod = NULL;
boolean already_loaded =
ncx_find_module(modname, revision) ? TRUE : FALSE;
*retmod = NULL;
/* save all the loaded modules including imported modules */
status_t res = ncx_set_load_callback(load_module_callback);
if (res == NO_ERR) {
callback_loaded = TRUE;
} else {
return res;
}
#ifdef STATIC_SERVER
res = ncxmod_load_module(modname,
revision,
agt_get_savedevQ(),
&mod);
#else
res = agt_load_sil_code(modname,
revision,
TRUE,
AGT_SILTYP_MODULE,
FALSE);
if (res == ERR_NCX_SKIPPED) {
log_warn("\nWarning: SIL code for module '%s' not found",
modname);
res = ncxmod_load_module(modname,
revision,
agt_get_savedevQ(),
&mod);
if (res == NO_ERR && mod) {
ncx_set_mod_unloadable(mod);
}
}
#endif // STATIC_SERVER
/* reget the module; it should be found if status == NO_ERR */
if (res == NO_ERR) {
mod = ncx_find_module(modname, revision);
if (mod) {
/* use the list in added_moduleQ not just this 1 module
* this tracks the imports loaded dynamically as well
* as the main module loaded by the <load> operation
*/
res = process_loaded_modules(scb, msg, NULL);
} else {
res = ERR_NCX_OPERATION_FAILED;
}
}
if (callback_loaded) {
ncx_clear_load_callback(load_module_callback);
}
/* done with the added_moduleQ; just used to process modules
* not to save the list of loaded modules (load_moduleQ)
*/
ncx_clean_backptrQ(&added_moduleQ);
if (res == NO_ERR) {
SET_MOD_SIL_LOADED(mod);
*retmod = mod;
if (!already_loaded) {
/* add to the load_moduleQ */
add_loaded_module(modname);
}
}
return res;
} /* do_module_load */
The following functions may be used to obtain required information from the loaded module:
ncx_get_modname() - Get the main module name
ncx_get_mod_nsid() - Get the main module namespace ID
ncx_get_modversion() - Get the module version
ncx_get_modnamespace() - Get the module namespace URI
-
const xmlChar *ncx_get_modname(const ncx_module_t *mod)¶
Get the main module name.
- Parameters
mod -- module or submodule to get main module name
- Returns
main module name or NULL if error
-
xmlns_id_t ncx_get_mod_nsid(const ncx_module_t *mod)¶
Get the main module namespace ID.
- Parameters
mod -- module or submodule to get main module namespace ID
- Returns
namespace id number
-
const xmlChar *ncx_get_modversion(const ncx_module_t *mod)¶
Get the [sub]module version.
- Parameters
mod -- module or submodule to get module version
- Returns
module version or NULL if error
-
const xmlChar *ncx_get_modnamespace(const ncx_module_t *mod)¶
Get the module namespace URI.
- Parameters
mod -- module or submodule to get module namespace
- Returns
module namespace or NULL if error
Module Unload Callback¶
The Module Unload callback is a user/system callback that is invoked when a YANG module is unloaded from the server. This callback is only invoked for main modules, not submodules.
The following function template definition is used for Module Unload callback functions:
-
typedef void (*ncx_unload_cbfn_t)(ncx_module_t *mod)¶
user function callback template when a module is unloaded from the system
ncx_unload_cbfn_t
Run an instrumentation-defined function for a 'module-loaded' event
- Param mod
module that is being removed
The 'mod' pointer represents a module control block structure that is defined in the
netconf/src/ncx/ncxtypes.h
.This control block is a representation of one module or submodule during and after parsing.
It provides access to the module specific information, such as module name, revision, prefix, and other module specific information.
Note: do not alter any fields in this structure
Module Unload Callback Initialization and Cleanup¶
The 'ncx_set_unload_callback' function is used to declare the Module Unload callback. The registration can be done during the Initialization Phase 2 after the running configuration has been loaded from the startup file. It can actually be done at any time, as needed.
-
status_t ncx_set_unload_callback(ncx_unload_cbfn_t cbfn)¶
Set the callback function for an unload-module event.
- Parameters
cbfn -- callback function to use
- Returns
status
Example Module Unload register usage:
static status_t interfaces_init2 (void)
{
// ...
/* register unload module callback */
res = ncx_set_unload_callback(remove_module_callback);
if (res != NO_ERR) {
return res;
}
// ...
}
The 'ncx_clear_unload_callback' function is used to unload the Module Unload callback.
-
void ncx_clear_unload_callback(ncx_unload_cbfn_t cbfn)¶
Clear the callback function for an unload-module event.
- Parameters
cbfn -- callback function to use
Example Module Unload un-register usage:
void interfaces_cleanup (void)
{
// ...
ncx_clear_unload_callback(remove_module_callback);
// ...
}
Module Unload Callback Function Example¶
In this example, the callback code will find a val_value_t tree, based on the information from 'mod' pointer, and remove it from the static data list.
/********************************************************************
* FUNCTION remove_module
*
* Remove a module entry from the static modules list
*
* INPUTS:
* mod == module to remove
*
********************************************************************/
static void
remove_module (ncx_module_t *mod)
{
xmlns_id_t nsid = val_get_nsid(mymodules_val);
val_value_t *module = val_get_first_child(mymodules_val);
for (; module; module = val_get_next_child(module)) {
val_value_t *checkval =
val_find_child_fast(module, nsid, (const xmlChar *)"name");
/* check the module name, if it match, remove the module from the list */
if (checkval) {
if (xml_strcmp(VAL_STR(checkval), ncx_get_modname(mod))) {
continue;
}
} else {
continue; // error
}
/* check the module revision, if it match, remove the module from the list */
if (ncx_get_modversion(mod)) {
checkval =
val_find_child_fast(module, nsid, (const xmlChar *)"revision");
if (checkval) {
if (xml_strcmp(VAL_STR(checkval), ncx_get_modversion(mod))) {
continue;
}
} else {
continue; // error!
}
}
val_remove_child(module);
val_free_value(module);
return;
}
} /* remove_module */
Config Replay Callback¶
The Config Replay callback is a user callback that is invoked when the replay configuration procedure is started and finished.
Only one callback function can be registered.
Refer to the Configuration Replay section for complete details on triggering a Configuration Replay procedure.
The following function template definition is used for Config Replay callback functions:
-
typedef void (*agt_replay_fn_t)(boolean is_start)¶
replay callback (agt_replay_fn_t)
this callback is invoked when a configuration replay is started or finished, which has been triggered by a call to agt_request_replay()
- Param is_start
TRUE if start; FALSE if finish
Config Replay Callback Initialization and Cleanup¶
The 'agt_register_replay_callback' function is used to register this callback.
-
void agt_register_replay_callback(agt_replay_fn_t cbfn)¶
Register a callback function for a replay config event.
- Parameters
cbfn -- replay function to use (==NULL to clear)
Example Config Replay register usage:
static status_t interfaces_init2 (void)
{
// ...
/* register config replay callback */
res = agt_register_replay_callback(replay_callback);
if (res != NO_ERR) {
return res;
}
// ...
}
There is no unregister function for this callback. The server will cleanup the system automatically during shutdown.
Config Replay Callback Example¶
static void replay_callback (boolean is_start)
{
if (is_start) {
log_debug("\nConfig Replay is starting");
} else {
log_debug("\nConfig Replay is ending");
}
}
NV-Load Callback¶
The NV-Load callback function is a user callback that is invoked when the running configuration needs to be read from non-volatile storage.
This callback is used to provide the server with an XML file instead of the default from the --config CLI parameter.
The server will invoke this callback to get the file name and file encoding of the startup configuration file.
Only XML encoding is supported at this time.
Only one callback can be registered.
The
check_load_external_config
function inagt/agt.c
will check this callback during the <load-config> operation.This callback will not be used if the --no-nvstore CLI parameter is used.
Note
If the callback returns NO_ERR
and *filespec is empty then
the server will use the factory configuration.
The following function template definition is used for the NV-Load callback function:
-
typedef status_t (*agt_nvload_fn_t)(ncx_display_mode_t *encoding, xmlChar **filespec)¶
nvload callback
this callback is invoked when some config needs to be read from non-volatile storage
- Param encoding
address of encoding for the config
- Param filespec
address of filespec containing the config that was loaded
- Retval *encoding
set to the enum for the encoding used in the config
- Retval *filespec
malloced filespec containing the config that was loaded
== NULL if loading the factory default config
- Return
status; error indicates NV-load failed somehow If return NO_ERR and *filespec == NULL then use the factory config
NV-Load Callback Initialization and Cleanup¶
The 'agt_register_local_nv_handler' function is used to declare the NV-Load callback. The registration can be done during the Initialization Phase 2, after the running configuration has been loaded from the startup file.
-
status_t agt_register_local_nv_handler(agt_nvload_fn_t load_fn, agt_nvsave_fn_t store_fn)¶
Register a set of nvstore and nvload callback functions to handle the non-volatile storage of the configuration.
- Parameters
load_fn -- NV-load callback function
store_fn -- NV-save callback function
- Returns
status
static status_t interfaces_init2 (void)
{
// ...
/* register NV-storage handler to load/save config
* uncomment following to enable
*/
res = agt_register_local_nv_handler(nvload_callback,
nvsave_callback);
if (res != NO_ERR) {
return res;
}
// ...
}
There is no unregister function for this callback. The cleanup will be done automatically by the server.
NV-Load Callback Function Example¶
/********************************************************************
* FUNCTION nvload_callback
*
* this callback is invoked when some config needs to be read
* from non-volatile storage
*
* INPUTS:
* encoding == address of encoding for the config
* filespec == address of filespec containing the config that was loaded
*
* OUTPUTS:
* *encoding == set to the enum for the encoding used in the config
* *filespec == malloced filespec containing the config that was loaded
*
* RETURNS:
* status; error indicates NV-load failed somehow
* If return NO_ERR and *filespec == NULL then use the factory config
*
*********************************************************************/
static status_t
nvload_callback (ncx_display_mode_t *encoding,
xmlChar **filespec)
{
log_debug("\nEnter nvload_callback ");
*filespec = NULL;
*encoding = NCX_DISPLAY_MODE_XML;
status_t res = NO_ERR;
if (ncxmod_test_filespec(EXAMPLE_CONFIG_SPEC)) {
/* file exists so copy the filespec */
*filespec = xml_strdup(EXAMPLE_CONFIG_SPEC);
if (*filespec == NULL) {
res = ERR_INTERNAL_MEM;
}
}
return res;
} /* nvload_callback */
The following function is used in the example to search for the specified filespec:
-
boolean ncxmod_test_filespec(const xmlChar *filespec)¶
Check the exact filespec to see if it a file.
- Parameters
filespec -- file spec to check
- Returns
TRUE if valid readable file; FALSE otherwise
NV-Save Callback¶
The NV-Save callback function is a user callback that is invoked when the running configuration needs to be saved to non-volatile storage.
This callback is used to provide the system with an XML file to save, instead of the default from the --config CLI parameter.
The server will invoke this callback to pass the file name and file encoding of the configuration file to save.
Only XML encoding is supported at this time.
Only one callback can be registered.
The
agt_check_save_external_config
function inagt/agt.c
will check this callback during the "save-config" procedure.
The following function template definition is used for NV-Save callback functions:
-
typedef status_t (*agt_nvsave_fn_t)(ncx_display_mode_t encoding, const xmlChar *filespec)¶
brief nvsave callback
this callback is invoked when some config needs to be saved to non-volatile storage
- Param encoding
encoding format for the config (xml only allowed value)
- Param filespec
filespec containing the config to save
- Return
status; error indicates NV-save failed somehow
NV-Save Callback Initialization and Cleanup¶
This callback is regered at the same time as the NV Load callback using the 'agt_register_local_nv_handler' function.
There is no cleanup function for this callback. The cleanup will be done automatically by the server.
Refer to the NV-Load Callback Initialization and Cleanup section for details.
NV-Save Callback Function Example¶
The following example can be found in example-system.c
.
#define EXAMPLE_CONFIG_SPEC (const xmlChar *)"/tmp/example-config.xml"
/********************************************************************
* FUNCTION example_nvsave
*
* Nvsave callback is invoked when some config needs to be saved
* to non-volatile storage
*
* INPUTS:
* encoding == encoding format for the config (xml only allowed value)
* filespec == filespec containing the config to save
*
* RETURNS:
* status; error indicates NV-save failed somehow
*
*********************************************************************/
static status_t
example_nvsave (ncx_display_mode_t encoding,
const xmlChar *filespec)
{
status_t res = NO_ERR;
if (filespec == NULL || *filespec == 0) {
res = ERR_NCX_INVALID_VALUE;
} else if (encoding != NCX_DISPLAY_MODE_XML) {
res = ERR_NCX_INVALID_VALUE;
} else {
res = ncxmod_copy_text_file(filespec, EXAMPLE_CONFIG_SPEC);
}
return res;
} /* example_nvsave */
Periodic Timer Service¶
Some SIL code may need to be called at periodic intervals to check system status, update counters, and/or perhaps send notifications.
The file agt/agt_timer.h
contains the timer access function
declarations.
This section provides a brief overview of the SIL timer service.
Timer Callback Function¶
The timer callback function is expected to do a short amount of work, and not block the running process. The function returns zero for a normal exit, and -1 if there was an error and the timer should be destroyed.
The 'agt_timer_fn_t' template in agt/agt_timer.h
is used to define
the SIL timer callback function prototype. This typedef defines the
callback function template expected by the server for use with the timer
service:
-
typedef int (*agt_timer_fn_t)(uint32 timer_id, void *cookie)¶
timer callback function
Provided the the SIL code registering the timer. It is expected to process the timer expired event.
- Param timer_id
timer identifier
- Param cookie
context pointer, such as a session control block, passed to agt_timer_set function (may be NULL)
- Return
0 normal exit
-1 error exit, delete timer upon return
Timer Access Functions¶
A SIL timer can be set up as a periodic timer or a one-time event.
The timer interval (in seconds) and the SIL timer callback function are provided when the timer is created. A timer can also be restarted if it is running, and the time interval can be changed as well.
The following table highlights the SIL timer access functions in
agt/agt_timer.h
:
SIL Timer Access Functions
agt_timer_create |
Create a SIL timer. |
agt_timer_restart |
Restart a SIL timer |
agt_timer_delete |
Delete a SIL timer |
-
status_t agt_timer_create(uint32 seconds, boolean is_periodic, agt_timer_fn_t timer_fn, void *cookie, uint32 *ret_timer_id)¶
Malloc and start a new timer control block.
Main User API - FOr SIL only at this time
- Parameters
seconds -- number of seconds to wait between polls
is_periodic --
TRUE if periodic timer
FALSE if a 1-event timer
timer_fn -- address of callback function to invoke when the timer poll event occurs
cookie -- address of user cookie to pass to the timer_fn ret_timer_id address of return timer ID
ret_timer_id -- address of return timer ID
- Return values
*ret_timer_id -- timer ID for the allocated timer, if the return value is NO_ERR
- Returns
NO_ERR if all okay, the minimum spare requests will be malloced
-
status_t agt_timer_restart(uint32 timer_id, uint32 seconds)¶
Restart a timer with a new timeout value.
If this is a periodic timer, then the interval will be changed to the new value. Otherwise a 1-shot timer will just be reset to the new value
- Parameters
timer_id -- timer ID to reset
seconds -- new timeout value
- Returns
status, NO_ERR if all okay,
-
void agt_timer_delete(uint32 timer_id)¶
Remove and delete a timer control block.
Periodic timers need to be deleted to be stopped 1-shot timers will be deleted automatically after they expire and the callback is invoked
- Parameters
timer_id -- timer ID to destroy
Example Timer Callback Function¶
The following example from toaster.c simply completes the toast when the timer expires and calls the auto-generated 'toastDone' send notification function:
/********************************************************************
* FUNCTION toaster_timer_fn
*
* Added timeout function for toaster function
*
* INPUTS:
* see agt/agt_timer.h
*
* RETURNS:
* 0 for OK; -1 to kill periodic timer
********************************************************************/
static int
toaster_timer_fn (uint32 timer_id,
void *cookie)
{
(void)timer_id;
(void)cookie;
/* toast is finished */
toaster_toasting = FALSE;
toaster_timer_id = 0;
if (LOGDEBUG2) {
log_debug2("\ntoast is finished");
}
y_toaster_toastDone_send((const xmlChar *)"done");
return 0;
} /* toaster_timer_fn */
Session Hook Callback¶
The Session Hook callback function is a user callback that is invoked when a session starts and ends.
This callback is invoked before any data structures and components have been cleaned up and their data destroyed. It can be used to perform session end or start tasks that are not related to a specific YANG module.
Max Callbacks: No limit (except available heap memory)
File:
agt/agt\_cb.h
The following function template definition is used for Session Hook callback functions:
-
typedef void (*agt_cb_session_hook_t)(ncx_ses_event_t ses_event, const ses_cb_t *scb)¶
Typedef of the agt_cb_session_hook_t callback.
The Session Hook callback is invoked when a session starts and ends. Use ses.h macros like SES_MY_USERNAME(scb) to get data like client username. Max Callbacks: No limit (except available heap memory)
- Param ses_event
session event type
- Param scb
session control block for the session event
Session Hook Callback Initialization and Cleanup¶
The 'agt_cb_session_hook_register' function is used to declare the Session Hook callback. The registration can be done during the Initialization Phase, before or after the running configuration has been loaded from the startup file.
-
status_t agt_cb_session_hook_register(agt_cb_session_hook_t cbfn)¶
Register a Session Hook callback.
Max Callbacks: No limit (except available heap memory)
- Parameters
cbfn -- address of callback function to use
- Returns
the status of the operation.
Initialization function with the Session Hook callback registration may look as follows:
status_t
y_yumaworks_server_init (const xmlChar *modname,
const xmlChar *revision)
{
status_t res = NO_ERR;
// ... load module, etc.
/* Register a Session Hook callback */
res = agt_cb_session_hook_register(session_hook_callback);
return res;
}
The 'agt_cb_session_hook_unregister' function is used to cleanup this callback.
-
void agt_cb_session_hook_unregister(agt_cb_session_hook_t cbfn)¶
Unregister a Session Hook callback.
This function unregisters a Session Hook callback.
- Parameters
cbfn -- address of callback function to use
The following example code illustrates how the Session Hook callback can be cleaned up.
void y_yumaworks_server_cleanup (void)
{
// ...
/* Unregister a Session Hook callback. */
agt_cb_session_hook_unregister(session_hook_callback);
// ...
}
Session Hook Callback Function Example¶
In the following example we are going to register Session Hook callbacks. In the callback function we are going to check if a session that is getting started is a RESTCONF session and the input encoding is XML and then will generate specific logging information for the current session. Refer to the attached YANG module and its SIL code for a complete example.
/********************************************************************
* FUNCTION session_hook_callback
*
* The Session Hook callback is invoked when a session starts
* and ends.
*
* INPUTS:
* ses_event == session event type
* scb == session control block for the session event
*
* RETURNS:
* status
********************************************************************/
static void
session_hook_callback (ncx_ses_event_t ses_event,
const ses_cb_t *scb)
{
if (LOGDEBUG) {
log_debug("\n\nEnter Session Hook callback for %s@%s",
SES_MY_USERNAME(scb) ? SES_MY_USERNAME(scb) : NCX_EL_NOBODY,
SES_PEERADDR(scb) ? SES_PEERADDR(scb) : NCX_EL_LOCALHOST);
}
/* Perform specific tasks when the session is ended or started
* and only if the current session protocol is RESTCONF
* and the session has an input that is encoded in XML
*/
ncx_display_mode_t input_mode = SES_IN_ENCODING(scb);
if (input_mode == NCX_DISPLAY_MODE_XML) {
if (SES_PROTOCOL(scb) == NCX_PROTO_RESTCONF) {
if (ses_event == NCX_SES_EVENT_START) {
if (LOGDEBUG) {
log_debug("\n ++++ Session Start ++++");
}
} else if (ses_event == NCX_SES_EVENT_END) {
if (LOGDEBUG) {
log_debug("\n ---- Session END ----");
}
}
}
}
return;
} /* session_hook_callback */
Shutdown Callback¶
The Shutdown callback function is a user callback that is invoked when the server is about to restart or shutdown.
This callback is invoked before any data structures and components have been cleaned up and their data destroyed. It can be used to perform on-exit tasks that are not related to a specific YANG module.
Max Callbacks: No limit (except available heap memory)
The following function template definition is used for Shutdown callback functions:
-
typedef void (*agt_cb_shutdown_t)(void)¶
Typedef of the agt_cb_shutdown_t callback.
The Shutdown callback is the user/system callback that is invoked at the start of a normal agt_cleanup A normal shutdown or restart is in progress. This callback is not invoked if the server crashes.
Max Callbacks: No limit (except available heap memory)
Shutdown Callback Initialization and Cleanup¶
The 'agt_cb_shutdown_register' function is used to declare the Shutdown callback. The registration can be done during the Initialization Phase 2, before or after the running configuration has been loaded from the startup file.
-
status_t agt_cb_shutdown_register(agt_cb_shutdown_t cbfn)¶
Register a Shutdown callback.
Max Callbacks: No limit (except available heap memory)
- Parameters
cbfn -- address of callback function to use
- Returns
the status of the operation.
Example Initialization function with the Shutdown callback registration:
static status_t server_init (void)
{
// ..
res = agt_cb_shutdown_register(server_shutdown_cb);
// ..
}
There is no cleanup function for this callback. The cleanup will be done automatically by the server.
Shutdown Callback Function Example¶
The following example code shows a Shutdown callback:
static void server_shutdown_cb (void)
{
// do some platform-specific cleanup
}
Command Complete Callback¶
The Command Complete callback function is a user callback that is invoked when the server has completed an RPC operation and the response has been generated to the client (may not have been sent yet). This callback can be used instead of a command-specific Post-RPC-Reply callback function.
Max Callbacks: No limit (except available heap memory)
The following function template definition is used for Command Complete callback functions:
-
typedef void (*agt_cb_command_complete_t)(ses_cb_t *scb, rpc_msg_t *msg, const xmlChar *command_modname, const xmlChar *command_name)¶
Typedef of the agt_command_complete_cb_t callback.
The Command Complete callback is the user/system callback that is invoked after each client command is executed for the NETCONF or RESTCONF protocols.
The Command Complete is typically used for retrieval operations (get, get-config, get-bulk) to release resources used during GET2 callbacks invoked during the operation.
Max Callbacks: No limit (except available heap memory)
- Param scb
session control block making the request
- Param msg
incoming rpc_msg_t in progress
- Param command_modname
YANG module name of command that is completed
- Param command_name
YANG RPC object name of command that is completed
Command Complete Callback Initialization and Cleanup¶
The 'agt_cb_command_complete_register' function is used to declare the Command Complete callback. The registration can be done during the Initialization Phase 2, before or after the running configuration has been loaded from the startup file.
-
status_t agt_cb_command_complete_register(agt_cb_command_complete_t cbfn)¶
Register a Command Complete callback.
Max Callbacks: No limit (except available heap memory)
- Parameters
cbfn -- address of callback function to use
- Returns
the status of the operation.
Example Initialization function for the Command Complete callback:
static status_t my_init (void)
{
status_t res = NO_ERR;
// … load module, etc.
res = agt_cb_command_complete_register(example_command_complete_cbfn);
// ...
}
The 'agt_cb_command_complete_unregister' function can be used to remove this callback. This is optional. The server will cleanup automatically on shutdown.
-
void agt_cb_command_complete_unregister(agt_cb_command_complete_t cbfn)¶
Unregister a Command Complete callback.
This function unregisters a Command Complete callback.
- Parameters
cbfn -- address of callback function to use
Example Cleanup function for the Command Complete callback:
static void my_cleanup (void)
{
// ...
agt_cb_command_complete_unregister(example_command_complete_cbfn);
// ...
}
Command Complete Callback Function Example¶
The following example code shows a Command Complete callback:
/*******************************************************************
* FUNCTION example_command_complete_cbfn
*
* The Command Complete callback is the user/system callback
* that is invoked after each client command is executed
* for the NETCONF or RESTCONF protocols.
*
* The Command Complete is typically used for retrieval
* operations (get, get-config, get-bulk) to release resources
* used during GET2 callbacks invoked during the operation.
*
* Max Callbacks: No limit (except available heap memory)
*
* INPUTS:
* scb == session control block making the request
* msg == incoming rpc_msg_t in progress
* command_modname == YANG module name of command that is completed
* command_name == YANG RPC object name of command that is completed
*
* OUTPUTS:
* none
*
* RETURNS:
* none
*******************************************************************/
static void
example_command_complete_cbfn (ses_cb_t *scb,
rpc_msg_t *msg,
const xmlChar *command_modname,
const xmlChar *command_name)
{
(void)command_modname;
if (!xml_strcmp(command_name, (const xmlChar *)"get") ||
!xml_strcmp(command_name, (const xmlChar *)"get-config") ||
!xml_strcmp(command_name, (const xmlChar *)"get-bulk")) {
/* cleanup our internal get cache data
* example_clean_get2_cache(scb, msg);
*/
}
}
NACM External Groups Callback¶
The NACM External Groups callback function is a user callback that is invoked when the server creates a new client session for NETCONF or RESTCONF sessions. It is used to retrieve a list of group names that should be used for the specified username, just for that session. These group names are added to any NACM configured groups in the ietf-netconf-acm YANG module.
Max Callbacks: 1
File:
agt/agt_acm_ietf.h
The following function template definition is used for NACM External Groups callback functions:
-
typedef status_t (*agt_acm_group_cbfn_t)(const xmlChar *username, xmlChar **retgroups)¶
typedef for NACM External Groups callback function
Get the list of group names for this username These groups are added to the usergroup cache for the session
- Param username
return the list of group names that this username is a member
- Param retgroups
address of return malloced string
- Retval *retgroups
is set to a malloced string that will be parsed.
It contains a whitespace delimited list of group named ' group1 group2 group3'
The caller will free this string with m__free- Return
status: if an error occurs the session will only use NACM groups
NACM External Groups Callback Initialization and Cleanup¶
The 'agt_acm_ietf_register_group_cbfn' function is used to declare the NACM External Group callback. The registration can be done during the Initialization Phase 2, before or after the running configuration has been loaded from the startup file.
-
void agt_acm_ietf_register_group_cbfn(agt_acm_group_cbfn_t cbfn)¶
Register a get-external-groups callback function.
This will be invoked at the start of each session as the acm_cache is created for a session
- Parameters
cbfn -- callnack function to register
Example Initialization function for the NACM External Group callback:
static status_t my_init (void)
{
status_t res = NO_ERR;
// … load module, etc.
/* example -- Register a NACM External Groups Callback */
agt_acm_ietf_register_group_cbfn(nacm_external_group_cbfn);
return res;
}
There is no unregister function for this callback. The server will cleanup automatically on shutdown.
NACM External Groups Callback Function Example¶
The following example code shows a NACM External Group callback:
/********************************************************************
* FUNCTION nacm_external_group_cbfn
*
* Get the list of group names for this username
* These groups are added to the usergroup cache for the session
* INPUTS:
* username: return the list of group names that this username
* is a member
* retgroups == address of return malloced string
* OUTPUTS:
* *retgroups is set to a malloced string that will be parsed.
* It contains a whitespace delimited list of group named
* ' group1 group2 group3'
* The caller will free this string with m__free
* RETURNS:
* status: if an error occurs the session will only use NACM groups
*********************************************************************/
static status_t
nacm_external_group_cbfn (const xmlChar *username,
xmlChar **retgroups)
{
if (retgroups == NULL) {
return ERR_NCX_INVALID_VALUE;
}
(void)username;
/* MUST use a function that allocates memory with m__getMem
* Will be freed by the caller with m__free macro
*/
*retgroups = xml_strdup("group1 group2 group5");
if (*retgroups == NULL) {
return ERR_INTERNAL_MEM;
}
return NO_ERR;
}
User Defined Data Types Callbacks¶
User defined data types are supported with callback functions that apply to all YANG leaf or leaf-list nodes using a specific data type.
There are 3 types of callbacks supported to allow customization of YANG data types:
validate: custom validation function, used when a data node is set
canonical: convert a value to canonical format, used when a data node is set
compare: compare 2 values of the same data type, used when a data node is set
There are several standard YANG data types that are supported with
built-in canonical functions, which can be found in
ncx/ipaddr_typ.c
(if sources are available). The server will
automatically check for validate and canonical callbacks when a data
node is parsed from XML or JSON input. The automatic canonical check can
be disabled using the --with-canonical CLI parameter.
User Defined Data Types Callback Initialization and Cleanup¶
A user defined type is registered with the 'typ_userdef_register' function.
This must be done after the YANG module containing the typedef statement has been loaded.
Only top-level typedefs are supported.
Typedefs within groupings or nested within containers or lists are not supported.
-
status_t typ_userdef_register(const xmlChar *modname, const xmlChar *typname, typ_validate_fn_t validate_fn, typ_canonical_fn_t canonical_fn, typ_compare_fn_t compare_fn, void *cookie)¶
Register the callback functions for a user defined type.
At least one callback needs to be set in order for this userdef type to have any affect
- Parameters
modname -- module name defining the type
typname -- name of the type
validate_fn -- validate callback (may be NULL)
canonical_fn -- canonical callback (may be NULL)
compare_fn -- compare callback (may be NULL)
cookie -- cookie to pass to callback function
- Returns
status
Example Registration function:
/* ietf-inet-types:ipv6-address */
status_t res =
typ_userdef_register(NCXMOD_IETF_INET_TYPES,
(const xmlChar *)"ipv6-address",
NULL, // validate_fn
ipv6_address_canonical_fn,
NULL, // compare_fn
NULL); // cookie
if (res != NO_ERR) {
return res;
}
typ_validate_fn_t¶
The validate callback is used for special custom validation of values conforming to a YANG data type.
-
typedef status_t (*typ_validate_fn_t)(typ_def_t *typdef, val_value_t *val, void *cookie)¶
userdef validate callback function user validation callback for a userdef type
- Param typdef
type definition for the user defined type
- Param inval
input value to convert
- Param cookie
cookie value passed to register function
- Return
the validation status
This function returns NO_ERR
even if it does not do any validation.
It returns an error code if validation fails.
Example Validate Callback function:
/********************************************************************
* FUNCTION admin_validate_fn
*
* validate callback for an administrative string
*
* INPUTS:
* typdef == type definition for the user defined type
* val == input value to validate
* cookie == cookie value passed to register function
* RETURNS:
* status
*/
static status_t
admin_validate_fn (typ_def_t *typdef,
val_value_t *val,
void *cookie)
{
(void)typdef;
(void)cookie;
if (VAL_TYPE(val) != NCX_BT_STRING) {
return ERR_NCX_OPERATION_FAILED;
}
const xmlChar *valstr = val->v.str;
if (valstr == NULL) {
return NO_ERR;
}
/* check if the string passes admin format checks */
if (check_admin_string_ok(valstr)) {
return NO_ERR;
}
return ERR_NCX_INVALID_VALUE;
} /* admin_validate_fn */
typ_canonical_fn_t¶
The canonical callback is used to convert a data node value to the canonical format for the data type. This is important for list key leafs, or else different representations of the same value (E.g. ipv6-address) will be treated as separate list entries.
This function returns NO_ERR
even if it does not do any conversion
to canonical format.
It returns an error code if some error occurs and conversion to canonical format fails.
-
typedef status_t (*typ_canonical_fn_t)(typ_def_t *typdef, val_value_t *val, void *cookie)¶
userdef canonical callback function convert the inval to the canonical format for the type
- Param typdef
type definition for the user defined type
- Param val
input value to convert
- Param cookie
cookie value passed to register function
- Retval val
can be converted to canonical format
- Return
status
Example Canonical Callback function:
/********************************************************************
* FUNCTION lowercase_canonical_fn
*
* <generic convert to lowercase>
* canonical callback for a domain name string
* convert the inval to the canonical format for the type
*
* INPUTS:
* typdef == type definition for the user defined type
* val == input value to convert
* cookie == cookie value passed to register function
* OUTPUTS:
* val == can be changed to canonical format
* RETURNS:
* status
*/
static status_t
lowercase_canonical_fn (typ_def_t *typdef,
val_value_t *val,
void *cookie)
{
(void)typdef;
(void)cookie;
if (VAL_TYPE(val) != NCX_BT_STRING) {
return ERR_NCX_OPERATION_FAILED;
}
xmlChar *valstr = VAL_STRING(val);
if (valstr == NULL) {
return NO_ERR;
}
/* convert the string to lowercase in place */
xmlChar *p = valstr;
while (*p) {
*p = (xmlChar)tolower((int)*p);
}
return NO_ERR;
} /* lowercase_canonical_fn */
typ_compare_fn_t¶
The compare callback is used to compare two values of the same data type. It is used in the val_compare functions. The standard compare function will skipped if this callback is present for the data type. This function is only needed if the standard compare function for the data type is not correct for some reason (E.g: a vendor-specific structured string).
This function returns NO_ERR
if the comparison is done and no need
to do the standard compare.
This function returns ERR_NCX_SKIPPED
if the comparison is not done
so the standard compare function needs to be invoked.
This function returns some error code if an error occurs while
attempting the comparison (E.g. ERR_INTERNAL_MEM
if a malloc fails)
-
typedef status_t (*typ_compare_fn_t)(const typ_def_t *typdef, const val_value_t *val1, const val_value_t *val2, void *cookie, int *retval)¶
userdef compare callback function compare 2 val_value_t nodes of the same user defined type
- Param typdef
type definition for the user defined type
- Param val1
input value 1 to comapre
- Param val2
input value 2 to comapre
- Param cookie
cookie value passed to register function
- Param retval
address of return compare value
- Retval *retval
return compare value
- Return
status (ERR_NCX_SKIPPED if no compare done)
Example Compare Callback function:
/********************************************************************
* compare 2 val_value_t nodes of the same user defined type
* INPUTS:
* typdef == type definition for the user defined type
* val1 == input value 1 to compare
* val2 == input value 2 to compare
* cookie == cookie value passed to register function
* retval == address of return compare value
* OUTPUTS:
* *retval == return compare value
* RETURNS:
* status (ERR_NCX_SKIPPED if no compare done)
*/
static status_t
admin_compare_fn (typ_def_t *typdef,
const val_value_t *val1,
const val_value_t *val2,
void *cookie,
int *retval)
{
(void)typdef;
(void)cookie;
if (VAL_TYPE(val1) != NCX_BT_STRING) {
return ERR_NCX_OPERATION_FAILED;
}
if (VAL_TYPE(val12) != NCX_BT_STRING) {
return ERR_NCX_OPERATION_FAILED;
}
const xmlChar *val1str = VAL_STRING(val1);
if (val1str == NULL) {
return ERR_NCX_SKIPPED;
}
const xmlChar *val2str = VAL_STRING(val2);
if (val2str == NULL) {
return ERR_NCX_SKIPPED;
}
/* compare as case-insensitive strings */
int ret = strcasecmp(const char *)val1str, (const char *)val2str);
*retval = ret;
return NO_ERR;
} /* admin_compare_fn */
agt_profile_t Struct¶
The following structure is used to represent the 'agt_profile':
-
struct agt_profile_t¶
Multiple instances are not supported.
The yp-server library has an API to override the default profile settings.
hardwire some of the server profile parameters because they are needed before the NCX engine is running They cannot be changed after boot-time. This data structure is sent from the main server to each subsystem, when the YControl initialization is done
!!! Keep the profile data in this struct in synch with !!! the agt_profile container in yumaworks-agt-profile.yang
the order of the fields below must exactly match the names and bit number assignments in the follwing files:
agt/agt_sil_profile.c
sil-sa/sil_sa_profile.c Both files must be changed together to keep the bit numbers aligned
Public Members
-
ncx_agttarg_t agt_targ¶
BEGIN DATA SENT TO SUBSYSTEMS; target type (candidate or running)
-
ncx_agtstart_t agt_start¶
startup type enum (distinct or mirror)
-
log_debug_t agt_log_level¶
requested log-level
-
log_debug_t agt_syslog_log_level¶
requested SYSLOG log-level
-
log_debug_t agt_pthread_log_level¶
requested PTHREADS log level
-
boolean agt_session_sync_mutex¶
session sync mutex flag
-
boolean agt_log_acm_reads¶
log NACM read requests
-
boolean agt_log_acm_writes¶
log NACM write requests
-
boolean agt_validate_all¶
validate all flag
-
boolean agt_has_startup¶
has startup flag for with-startup
-
boolean agt_usestartup¶
track no-startup flag
-
boolean agt_factorystartup¶
track factory-startup flag
-
boolean agt_startup_error¶
startup-error parameter: stop, continue enums only
-
boolean agt_running_error¶
running-error parameter: stop, continue enums only
-
boolean agt_logappend¶
log-append parameter
-
boolean agt_xmlorder¶
use strict XML order flag
-
boolean agt_list_deleteall_ok¶
allow delete-all and remove-all operations on a list
-
boolean agt_leaflist_deleteall_ok¶
allow delete-all and remove-all operations on a leaf-list
-
boolean agt_stream_output¶
stream message output: d:true; no CLI support yet
-
boolean agt_delete_empty_npcontainers¶
delete empty config=true NP containers: d: false
-
boolean agt_notif_sequence_id¶
d: false
-
boolean agt_yuma_system_notifs¶
d: false
-
boolean agt_ietf_system_notifs¶
d: true
-
boolean agt_yumaworks_system¶
d: true
-
boolean agt_yumaworks_templates¶
d: true
-
boolean agt_support_save¶
d: true (needs WITH_SUPPORT_SAVE=1)
-
boolean agt_term_msg¶
d: true for <term-msg> notification
-
boolean agt_alt_names¶
Yuma REST-API urlselect extra parameters.
-
boolean agt_wildcards¶
Allow wildcards in filters.
-
ncx_name_match_t agt_match_names¶
match names behavior; needs to be EXACT for YANG
-
agt_transaction_model_t agt_transaction_model¶
TBD private transaction model.
-
const xmlChar *agt_accesscontrol¶
access control model
-
const xmlChar *agt_conffile¶
config file: default: /etc/yumapro/netconfd-pro.conf
-
const xmlChar *agt_confdir¶
config dir: default: /etc/yumapro/netconfd-pro.d
-
const xmlChar *agt_logfile¶
main logfile
-
const xmlChar *agt_startup¶
startup filespec
-
const xmlChar *agt_startup_factory_file¶
factory startup filespec
-
const xmlChar *agt_defaultStyle¶
default-style for with-defaults
-
const xmlChar *agt_extern_libspec¶
superuser name (allowed to be NULL) moved to agt.c agt_superuserQ Q of ncx_backptr_t to malloced string from CLI parameters
extern library spec
-
const xmlChar *agt_backup_dir¶
backup dir location
-
const xmlChar *agt_server_id¶
assigned server ID
-
uint32 agt_eventlog_size¶
eventlog-size set to 0 to disable replay
-
uint32 agt_maxburst¶
maxburst parameter
-
uint32 agt_hello_timeout¶
hello-timeout parameter
-
uint32 agt_idle_timeout¶
idle-timeout parameter
-
uint32 agt_linesize¶
line size for logging
-
int32 agt_indent¶
indent parameter
-
int32 agt_message_indent¶
message-indent parameter
-
boolean agt_usevalidate¶
with-validate parameter
-
boolean agt_useurl¶
with-url parameter
-
boolean agt_use_ccommit¶
enable confirmed-comiit
-
boolean agt_use_yangapi¶
enable YANG-API protocol (obsolete: ignored)
-
boolean agt_use_restconf¶
enable RESTCONF protocol
-
boolean agt_use_cli¶
enable yp-shell
-
boolean agt_use_netconf¶
enable NETCONF protocol
-
boolean agt_use_local_transport¶
use local transport flag
-
boolean agt_use_notifications¶
enable notifications
-
boolean agt_system_sorted¶
enable system-sorted (obsolete: sorted by val_child algorithms)
-
boolean agt_lax_namespaces¶
lax namespace usage: will try to match element name
-
agt_acm_model_t agt_acm_model¶
NACM or external ACM model.
-
ncx_withdefaults_t agt_defaultStyleEnum¶
default with-defaults enum
-
agt_acmode_t agt_accesscontrol_enum¶
access control enum
-
uint16 agt_max_sessions¶
max sessions (total)
-
uint16 agt_max_cli_sessions¶
max CLI sessions
-
uint16 agt_subsys_timeout¶
subsystem timeout in seconds
-
uint16 agt_ports[AGT_MAX_PORTS]¶
these port numbers are for the NETCONF-over-SSH protocol
-
uint16 agt_coap_port¶
the CoAP port number used only if WITH_COAP and agt_use_coap set
-
uint16 agt_coap_dtls_port¶
Coap over DTLS port (not implemented)
-
const xmlChar *agt_coap_address¶
Coap over DTLS address (not implemented)
-
const xmlChar *agt_yangapi_server_url¶
YANG-API server URL (obsolete)
-
const xmlChar *agt_restconf_server_url¶
RESTCONF server URL.
-
boolean agt_use_yuma_proc¶
load yuma-proc module
-
boolean agt_use_yuma_arp¶
load yuma-arp module
-
boolean agt_use_yuma_if¶
load yuma-if module
-
boolean agt_use_yuma_mysession¶
load yuma-mysession module
-
boolean agt_use_yumaworks_event_filter¶
load yumaworks-event-filter module
-
boolean agt_use_yuma_system¶
load yuma-system module
-
boolean agt_use_rollback_on_error¶
Use rollback-on-error.
All datastore transactions are all-or-none so this parameter is essentially ignored
-
boolean agt_use_ycontrol¶
enable YControl protocol
-
boolean agt_sil_skip_load¶
skip the SIL callbacks for load-config Useful if the authoritative database is really the external system.
All edits coming from DB-API or loaded from the startup-cfg.xml are already applied to the system via the other database
-
boolean agt_log_event_drops¶
log event drops
-
boolean agt_sil_missing_error¶
treat missing SIL libraries as an error, not warning
-
boolean agt_sil_skip_keys¶
do not invoke the SIL callback for a key leaf
-
boolean agt_use_rollback_failed_backup¶
save running config for a commit, in case the rollback fails
-
boolean agt_allow_tcp_socket¶
allow a TCP socket instead of an AF_LOCAL socket for connections
-
boolean agt_use_tcp_socket¶
use a TCP socket instead of an AF_LOCAL socket for connections
-
const xmlChar *agt_subsys_info_file¶
location of subsys info file
-
boolean agt_save_owners¶
flag to save owner strings in the database
-
boolean agt_json_leaf_list_1line¶
flag to print JSON leaf-list value on 1 line
-
boolean agt_save_config_system¶
flag to skip generation of the startup XML file when a save_config is done by the server.
Used with the external config mode where the external system database is already up to date so the XML file is not used Default is false. Set in yp_system_init_profile.
-
uint8 agt_withdef_enabled¶
bitmask of the with-defaults enumerations that should be enabled in the server
-
uint32 agt_watcher_interval¶
Specifies the number of seconds the YPWatcher process will sleep before checking if the netconfd-pro process has died.
Ignored if no-watcher CLI parameter was used
-
boolean agt_audit_log_candidate¶
If true, then transactions to the candidate datastore will be recorded in the audit log.
If false, then transactions to the candidate datastore will not be recorded in the audit log.";
-
boolean agt_sil_validate_candidate¶
If true, the server will invoke the VALIDATE phase for SIL and SIL-SA callbacks when each edit is made to the candidate datastore.
-
boolean agt_restconf_strict_headers¶
If 'true' the server will only accept requests with normative Accept header entries specified in the draft.
-
boolean agt_autodelete_pdu_error¶
If 'true' the server will treat edit-config auto-delete because of false when-stmts as an error instead of silent delete.
-
uint32 agt_sil_getbulk_max¶
Specifies the maximum number of getbulk entries to request from a GET2 callback.
This value will be used in the get2cb 'max_entries' field. The value 0 is used to indicate there is no max and the GET2 callback can return as many getbulk entries as desired. This is the default for leaf-list GET2 callbacks
-
const xmlChar *agt_crypt_hash_prefix¶
specifies the string that will be pre-pended to the password before calling crypt_r to generate the hash for the crypt-hash leaf passed with $0$cleartext
-
uint8 agt_min_passwd_len¶
minimum password length when setting crypt-hash variables
-
boolean agt_with_netconf¶
If 'true' then the corresponding protocol will be enabled.
Otherwise, the protocol will not be enabled. The incoming connection will be droped if the protocol is disabled. NETCONF is usually enabled
-
boolean agt_with_restconf¶
enable RESTCONF sessions
-
boolean agt_with_yang_api¶
enable YANG-API sessions (obsolete)
-
boolean agt_with_yp_shell¶
enable yp-shell sessions
-
boolean agt_with_yp_coap¶
enable YP-CoAP sessions (not supported)
-
boolean agt_with_yp_coap_dtls¶
enable YP-CoAP DTLS sessions (not supported)
-
boolean agt_with_netconf_tls¶
enable NETCONF over TLS sessions
-
log_debug_t agt_audit_log_console_level¶
log console level
-
log_debug_t agt_audit_log_level¶
audit log level
-
boolean agt_ha_enabled¶
enable YP-HA
-
boolean agt_ha_sil_standby¶
call SIL code in standby mode
-
uint16 agt_ha_port¶
port number is default 8088
-
const xmlChar *agt_ha_server_key¶
server-key to keep HA pools separate
-
const xmlChar *agt_ha_initial_active¶
active server to use if standby
-
boolean agt_simple_json_names¶
use simple JSON names instead of YANG JSON names
-
boolean agt_create_empty_npcontainers¶
LAST DATA SENT TO SUBSYSTEMS create empty NP containers d: true.
-
boolean agt_with_warnings¶
this field indicates if agt_record_warning will be allowed to set the error-severity field to warning
-
boolean agt_library_mode¶
this field indicates the server is operating in library mode It will look for YANG modules but only load them into its library.
-
boolean agt_with_config_id¶
this field indicates if the :config-id capability is enabled or not.
This is an enterprise URI and at least 1 opensource tool complains it is not a valid YANG module URI
-
boolean agt_no_nvstore¶
this field indicates that the server should not load or save using the normal APIs during transaction management.
The 'start' choice will be ignored (e.g., no-startup)) and the server will not attempt to load a startup-cfg.xml file. Transactions will not be saved to NV-storage at all. Any external NV-storage callbacks will be ignored.
Use this mode if NV-load and NV-storage are handled internally and not via the startup-cfg.xml file.
-
boolean agt_with_yang11_hello¶
this field indicates whether the NETCONF hello message should conform to the standard and leave out YANG 1.1 modules.
-
boolean agt_with_callhome¶
this field indicates that the IETF Callhome feature is enabled if true and WITH_CALLHOME is built into the image, then the server will attempt to connect to the callhome client servers specified in the callhome config (ietf-server module TBD)
-
uint16 agt_callhome_retry_interval¶
this field specifies the number of seconds to wait after a connect attempt to the callhome server has failed.
-
uint16 agt_callhome_retry_max¶
this field specifies the number of retry attempts the server should attempt to the callhome server before giving up.
The value 0 indicates the server should never give up.
-
const xmlChar *agt_sshd_path¶
set the sshd exectuable path for callhome default is /usr/sbin/sshd only set by vendor in agt_init1 phase
-
const xmlChar *agt_subsys_path¶
set the netconf subsystem for sshd exectuable path for callhome default is /usr/sbin/netconf-subsystem-pro only set by vendor in agt_init1 phase
-
const xmlChar *agt_sshd_config¶
set the sshd_config file to use for sshd exectuable for callhome default is $HOME/.yumapro/ch_sshd_config.
<ch-server-name> only set by vendor in agt_init1 phase
-
boolean agt_with_ocpattern¶
this flag enables/disables the special OpenConfig usage of the YANG pattern-statement.
If true then modules named openconfig-* will be checked as POSIX patterns, not YANG XSD patterns
-
boolean agt_fileloc_fhs¶
this flag enables FHS file locations for server data files
-
boolean agt_no_audit_log¶
this flag indicates the no-audit-log CLI parameter
-
ncx_msg_encoding_t agt_restconf_default_encoding¶
this enum indicates the restconf-default-encoding CLI parameter
-
boolean agt_startup_fallback¶
this flag indicates the startup-error parm is set to fallback
-
boolean agt_running_fallback¶
this flag indicates the running-error parm is set to fallback
-
boolean agt_with_snmp¶
this flag indicates that the snmp agent should be enabled
-
ncx_snmp_agt_role_t agt_snmp_agent_role¶
identify the SNMP agent native mode master|subagent
-
uint16 agt_snmp_subagent_priority¶
identify the SNMP subagent priority, what priority will be used for OID callbacks registration
-
boolean agt_useurl_tftp¶
the libcurl variables
with-url-tftp
-
boolean agt_useurl_ftp¶
with-url-ftp
-
boolean agt_sil_delete_children_first¶
sil-delete-children-first CLI parameter
-
boolean agt_trim_whitespace¶
trim-whitespace CLI parameter
-
const xmlChar *agt_netconf_tls_address¶
netconf-tls-address parameter
-
const xmlChar *agt_netconf_tls_certificate¶
netconf-tls-cerificate parameter
-
const xmlChar *agt_netconf_tls_key¶
netconf-tls-key parameter
-
uint16 agt_netconf_tls_port¶
netconf-tls-port parameter
-
const xmlChar *agt_netconf_tls_trust_store¶
netconf-tls-trust-store parameter
-
boolean agt_insecure_ok¶
insecure-ok parameter
-
const xmlChar *agt_cert_default_user¶
cert-default-user parameter
-
const xmlChar *agt_errmsg_lang¶
errmsg-lang parameter
-
boolean agt_startup_prune_ok¶
startup-prune-ok parameter
-
boolean agt_startup_create_ok¶
no CLI parameter!! set to TRUE! change in yp-system library or agt_profile.c
-
boolean agt_with_canonical¶
with-canonical parameter
-
boolean agt_with_modtags¶
with-modtags parameter
-
boolean agt_sil_invoke_for_defaults¶
sil-invoke-for-defaults parameter
-
boolean agt_with_gnmi¶
this flag indicates that the gNMI support should be enabled
-
boolean agt_ypserver_mode¶
this flag indicates the server is rnning as yp-controller and not netconfd-pro
-
boolean agt_sil_prio_reverse_for_deletes¶
sil-prio-reverse-for-deletes parameter
-
uint32 agt_audit_log_events¶
audit-log-events to control audit log content
-
boolean agt_sil_root_check_first¶
sil-root-check-first to do root check in edit-config before the SIL validate callbacks are invoked the old (only) behavior is 'false'
-
boolean agt_sil_wait_sa¶
No CLI parameter!! Set to TRUE in agt_profile.c the load-config will wait if agt_ncx_load_any_waiting() is true and this parameter is also true.
-
boolean agt_with_maint_mode¶
allow maintenance mode to be used
-
boolean agt_callhome_reconnect¶
CLI parameter callhome-reconnect.
-
boolean agt_sil_test_get_when¶
enable config=false when-stmt checking for GET1 and GET2 callback functions; if false then the callback is expected to check the when-stmt itself and return ERR_NCX_NO_INSTANCE if the when-stmts for the node are false; default is true
-
boolean agt_yuma_time_filter¶
use the yuma-time-filter module
-
boolean agt_yumaworks_getbulk¶
use the yumaworks-getbulk module
-
boolean agt_yumaworks_ids¶
use the yumaworks-ids module
-
boolean agt_use_db_lock¶
db-lock used only if WITH_YCONTROL=1 and CLI set
-
int32 agt_max_strlen¶
max-strlen parameter
-
boolean agt_with_yumaworks_callhome¶
with-yumaworks-callhome
-
boolean agt_with_yumaworks_config_change¶
with-yumaworks-config-change
-
boolean agt_with_yumaworks_event_stream¶
with-yumaworks-event-stream
-
agt_crl_mode_t agt_crl_mode¶
tls-crl-mode parameter
-
boolean agt_crl_missing_ok¶
tls-crl-missing-ok parameter
-
boolean agt_with_nmda¶
with-nmda
-
boolean agt_startup_skip_validation¶
startup-skip-validation
-
boolean agt_cvt_subtree_filter¶
convert-subtree-filterparameter
-
boolean agt_import_version_bestmatch¶
import-version-bestmatch parameter
-
boolean agt_with_yang_patch_running¶
with-yang-patch-running parameter
-
uint16 agt_push_min_period¶
push-min-period parameter
-
uint16 agt_push_min_dampening¶
push-min-dampening parameter
-
uint32 agt_push_max_periodic¶
push-max-periodic parameter
-
uint32 agt_push_max_operational¶
push-max-operational parameter
-
uint32 agt_push_simop_period¶
push-simop-period parameter
-
boolean agt_push_simop_enabled¶
push-simop-enabled parameter
-
boolean agt_push_simop_patch_update¶
push-simop-patch-update parameter
-
boolean agt_wait_datastore_ready¶
wait-datastore-ready parameter
-
boolean agt_return_status¶
return exit code or zero
-
boolean agt_use_yumaworks_cert_usermap¶
load yumaworks-cert-usermap module
-
boolean agt_remove_schema_aug_leafs¶
this flag indicates the deprecated schema list leafs added from yumaworks-system should be removed.
The nodes are not removed from the YANG module, but the server will not send these optional leafs in any response to a client. Fixes ODL bug which rejects session if an augmenting node is found in this list
-
obj_testflags_t agt_rootflags¶
root commit descendant test flags
-
boolean agt_load_done¶
server load-config done flag
-
boolean agt_load_validate_errors¶
server load-config had errors flag
-
boolean agt_load_rootcheck_errors¶
server load-config root-check had errors flag
-
boolean agt_load_top_rootcheck_errors¶
server load-config had top root-check errors flag
-
boolean agt_load_apply_errors¶
server load-config had apply phase errors flag
-
boolean agt_load_factory_fallback¶
server load-config allowed to use factory-fallback flag
-
boolean agt_load_def_startup_factory¶
server load-config factory flag
-
dlq_hdr_t agt_savedevQ¶
Q of malloced ncx_save_deviations_t.
-
dlq_hdr_t agt_commit_testQ¶
Q of malloced agt_commit_test_t.
-
xmlChar *agt_startup_txid_file¶
cached location of startup transaction ID file
-
xmlChar *agt_socket_address¶
strdup of socket-address CLI parameter
-
uint16 agt_socket_port¶
listen on this TCP port if TCP socket is enabled
-
xmlChar *agt_conf_dirspec¶
malloced string indicating the confdir pathspec in use
-
boolean agt_confdir_skipped¶
-
agt_ha_role_t agt_ha_role¶
saved HA role
-
boolean agt_defer_load¶
saved defer load config flag
-
boolean agt_with_grpc¶
this flag indicates that the gRPC support should be enabled
Datastore Fields¶
Field Name |
CLI Override |
Default |
---|---|---|
agt_autodelete_pdu_error |
true |
|
agt_create_empty_npcontainers |
true |
|
agt_backup_dir |
none |
$HOME/.yumapro/backups |
agt_defaultStyle |
explicit |
|
agt_defaultStyleEnum |
NCX_WITHDEF_EXPLICIT |
|
agt_no_nvstore |
not present |
|
agt_running_error |
false |
|
agt_save_config_system |
none |
false |
agt_sil_validate_candidate |
true |
|
agt_sil_skip_load |
false |
|
agt_start |
NCX_AGT_START_MIRROR |
|
agt_startup_error |
false |
|
agt_system_sorted |
true |
|
agt_targ |
NCX_AGT_TARG_CANDIDATE |
Logging Fields¶
Field Name |
CLI Override |
Default |
---|---|---|
agt_audit_log_candidate |
:ref:` --audit-log-candidate` |
true |
agt_audit_log_console_level |
LOG_DEBUG_DEBUG |
|
agt_audit_log_level |
LOG_DEBUG_INFO |
|
agt_logfile |
none |
|
agt_logappend |
none |
|
agt_log_acm_reads |
none |
false |
agt_log_acm_writes |
none |
true |
agt_log_level |
LOG_DEBUG_INFO |
|
agt_pthread_log_level |
LOG_DEBUG_INFO |
|
agt_syslog_log_level |
LOG_DEBUG_INFO |
Notification Fields¶
Field Name |
CLI Override |
Default |
---|---|---|
agt_eventlog_size |
1000 |
|
agt_maxburst |
10 |
|
agt_notif_sequence_id |
none |
false |
agt_ietf_system_notifs |
true |
|
agt_use_notifications |
true |
|
agt_yuma_system_notifs |
false |
|
agt_log_event_drops |
false |
Access Control Fields¶
Field Name |
CLI Override |
Default |
---|---|---|
agt_accesscontrol |
enforcing |
|
agt_acm_model |
none |
AGT_ACM_MODEL_IETF_NACM |
agt_superuserQ |
none |
|
agt_crypt_hash_prefix |
none |
$6$ |
agt_min_password_len |
none |
8 |
Protocol Capability and YANG Module Fields¶
Field Name |
CLI Override |
Default |
---|---|---|
agt_with_netconf |
true |
|
agt_with_restconf |
true |
|
agt_with_yang_api |
false |
|
agt_with_yp_shell |
true |
|
agt_useurl |
true |
|
agt_usevalidate |
true |
|
agt_use_ccommit |
none |
true |
agt_use_cli |
none |
true if compiled WITH_CLI=1 |
agt_use_local_transport |
none |
true if compiled DEBUG=1 |
agt_use_netconf |
none |
true |
agt_use_yangapi |
none |
true if compiled WITH_YANGAPI=1 |
agt_use_yuma_arp |
none |
true if compiled WITH_YUMA_ARP=1 |
agt_use_yuma_if |
none |
true if compiled WITH_YUMA_INTERFACES=1 |
agt_use_yuma_mysession |
--module=yuma-mysession |
false |
agt_use_yuma_proc |
none |
true if compiled WITH_YUMA_PROC=1 |
agt_use_yumaworks_event_filter |
true |
|
agt_yumaworks_system |
true |
|
agt_withdef_enabled |
none |
all bits enabled (15) |
General Fields¶
Field Name |
CLI Override |
Default |
---|---|---|
agt_alt_names |
true |
|
agt_conffile |
/etc/yumapro/netconfd-pro.conf |
|
agt_hello_timeout |
600 |
|
agt_idle_timeout |
3600 |
|
agt_indent |
1 |
|
agt_lax_namespaces |
none |
true |
agt_linesize |
none |
72 |
agt_match_names |
NCX_MATCH_EXACT |
|
agt_max_sessions |
8 |
|
agt_sil_getbulk_max |
10 |
|
agt_simple_json_names |
false |
|
agt_message_indent |
-1 |
|
agt_ports |
830 |
|
agt_restconf_server_url |
||
agt_restconf_strict_accept |
false |
|
agt_sil_missing_error |
false |
|
agt_stream_output |
none |
true |
agt_wildcards |
false |
|
agt_with_config_id |
true |
|
agt_with_warnings |
false |
|
agt_xmlorder |
false |
|
agt_yangapi_server_url |
||
agt_library_mode |
false |
High Availability Specific Fields¶
Field Name |
CLI Override |
Default |
---|---|---|
agt_ha_enabled |
false |
|
agt_ha_sil_standby |
false |
|
agt_ha_port |
8088 |
|
agt_ha_server_key |
none |
|
agt_ha_initial_active |
none |
example-system.c¶
The following example code can be found in the libsystem/src directory.
/*
* Copyright (c) 2012 - 2020, YumaWorks, Inc., All Rights Reserved.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* FILE: example-system.c
Example External System Library
*********************************************************************
* *
* I N C L U D E F I L E S *
* *
*********************************************************************/
#include <assert.h>
#include <stdlib.h>
#include <xmlstring.h>
#include "procdefs.h"
#include "agt.h"
#include "agt_acm.h"
#include "agt_acm_ietf.h"
#include "agt_acm_extern.h"
#include "agt_util.h"
#include "agt_cfg.h"
#include "agt_cb.h"
#include "agt_hook_util.h"
#include "dlq.h"
#include "example-system.h"
#include "log.h"
#include "log_vendor.h"
#include "log_vendor_extern.h"
#include "ncx.h"
#include "ncxconst.h"
#include "ncxmod.h"
#include "ncxtypes.h"
#include "obj.h"
#include "ses.h"
#include "status.h"
#include "typ_userdef.h"
#include "val.h"
#include "val_util.h"
#include "xml_util.h"
/********************************************************************
* *
* C O N S T A N T S *
* *
*********************************************************************/
/* this flag is used to enable the NACM external group examples */
// #define ADD_NACM_GROUP 1
/* this flag is used to enable the Session Hook callback examples */
// #define ADD_SESSION_HOOK 1
/* this flag is used to enable the canonical callback for an IPv6
* address examples
*/
// #define ADD_IPV6_FN 1
/* this flag is used to enable the External ACM Hooks examples */
// #define ADD_ACM_EXTERN 1
/* this flag is used to enable Vendor log functions examples */
// #define ADD_VENDOR_LOG 1
/* this flag is used to enable External NV-Storage Handler Hooks examples */
// #define ADD_NV_STORE_HOOK 1
/* this flag is used to enable Transaction Management Hooks examples */
// #define ADD_TRANS_HOOK 1
/* this flag is used to enable YANG Object Template Callback examples */
// #define ADD_YANG_OBJ_TEMP 1
/* this flag is used to enable YANG Extension Handler Callback examples */
// #define ADD_YANG_EXTEN 1
/* this flag is used to enable RPC Command Complete examples */
// #define ADD_RPC_COMPLETE 1
/* this flag is used to enable the user-type callback examples */
//#define ADD_USER_TYPE 1
#define USERTYPE_MODULE (const xmlChar *)"iana-crypt-hash"
#define USERTYPE_TYPE (const xmlChar *)"crypt-hash"
/********************************************************************
* *
* F U N C T I O N S *
* *
*********************************************************************/
/**************** Example Callback for an IPv6 address *******************/
#ifdef ADD_IPV6_FN
/********************************************************************
* FUNCTION my_ipv6_fn
*
* Canonical callback for an IPv6 address.
* Convert the inval to the canonical format for the type
*
* INPUTS:
* typdef == type definition for the user defined type
* val == input value to convert
* cookie == cookie value passed to register function
*
* OUTPUTS:
* val == can be changed to canonical format
*
* RETURNS:
* status
*
*********************************************************************/
static status_t
my_ipv6_fn (typ_def_t *typdef,
val_value_t *val,
void *cookie)
{
(void)typdef;
(void)cookie;
log_debug("\nmy_ipv6_fn called ******************************");
return NO_ERR;
} /* my_ipv6_fn */
#endif // ADD_IPV6_FN
#ifdef ADD_USER_TYPE
/********************************************************************
* FUNCTION dummy1_canonical_fn
*
* Canonical callback for a data type.
* Convert the inval to the canonical format for the type (not really)
*
* INPUTS:
* typdef == type definition for the user defined type
* val == input value to convert
* cookie == cookie value passed to register function
*
* OUTPUTS:
* val == can be changed to canonical format
*
* RETURNS:
* status
*
*********************************************************************/
static status_t
dummy1_canonical_fn (typ_def_t *typdef,
val_value_t *val,
void *cookie)
{
(void)typdef;
(void)cookie;
log_debug("\ndummy1_canonical(%s) called *****", VAL_NAME(val));
/* real function would change the value to canonical format */
return NO_ERR;
} /* dummy1_canonical_fn */
/********************************************************************
* FUNCTION dummy1_compare_fn
*
* Compare callback for a data type.
*
* INPUTS:
* typdef == type definition for the user defined type
* val1 == input value 1 to comapre
* val2 == input value 2 to comapre
* cookie == cookie value passed to register function
* retval == address of return compare value
* OUTPUTS:
* *retval == return compare value
* RETURNS:
* status (ERR_NCX_SKIPPED if no compare done)
*/
static status_t
dummy1_compare_fn (const typ_def_t *typdef,
const val_value_t *val1,
const val_value_t *val2,
void *cookie,
int *retval)
{
(void)typdef;
(void)cookie;
log_debug("\ndummy1_compare(%s) called *****", VAL_NAME(val1));
/* This must be a real compare function!
* just use the default compare function
* real function would compare the 2 values with different function
*/
*retval = val_compare(val1, val2);
return NO_ERR;
} /* dummy1_compare_fn */
/********************************************************************
* FUNCTION dummy1_validate_fn
* user validation callback for a userdef type
* Invoked when the input data is checked for field validation
* such as xml_parse. Applies to RPC input and datastore nodes
* INPUTS:
* typdef == type definition for the user defined type
* inval == input value to convert
* cookie == cookie value passed to register function
* RETURNS:
* the validation status
*/
static status_t
dummy1_validate_fn (typ_def_t *typdef,
val_value_t *val,
void *cookie)
{
(void)typdef;
(void)cookie;
log_debug("\ndummy1_validate(%s) called *****", VAL_NAME(val));
/* real function would test the value */
return NO_ERR;
} /* dummy1_validate_fn */
#endif // ADD_USER_TYPE
/**************** Example External ACM Hooks *******************/
#ifdef ADD_ACM_EXTERN
/********************************************************************
* FUNCTION acm_extern_rpc
*
* Check if the specified user is allowed to invoke an RPC
*
* INPUTS:
* msg == XML header in incoming message in progress
* user == user name string
* rpcobj == obj_template_t for the RPC method to check
*
* RETURNS:
* TRUE if user allowed invoke this RPC; FALSE otherwise
*
*********************************************************************/
static boolean
acm_extern_rpc (xml_msg_hdr_t *msg,
const xmlChar *user,
const obj_template_t *rpcobj)
{
(void)msg;
const xmlChar *modname = obj_get_mod_name(rpcobj);
const xmlChar *objname = obj_get_name(rpcobj);
log_debug("\nChecking RPC access for user %s to operation '%s:%s'",
user, modname, objname);
// check access here
log_debug("\nacm_extern_rpc: return OK\n");
return TRUE;
} /* acm_extern_rpc */
/********************************************************************
* FUNCTION acm_extern_notif
*
* Check if the specified user is allowed to receive
* a notification event
*
* INPUTS:
* user == user name string
* notifobj == obj_template_t for the notification event to check
*
* RETURNS:
* TRUE if user allowed receive this notification event;
* FALSE otherwise
*********************************************************************/
static boolean
acm_extern_notif (const xmlChar *user,
const obj_template_t *notifobj)
{
const xmlChar *modname = obj_get_mod_name(rpcobj);
const xmlChar *objname = obj_get_name(rpcobj);
log_debug("\nChecking Notification access for "
"user %s to event '%s:%s'",
user, modname, objname);
// check access here
log_debug("\nacm_extern_notif: return OK\n");
return TRUE;
} /* acm_extern_notif */
/********************************************************************
* FUNCTION acm_extern_write_fn
*
* Check if the specified user is allowed to access a value node
* The val->obj template will be checked against the val->editop
* requested access and the user's configured max-access
*
* INPUTS:
* msg == XML header from incoming message in progress
* newval == val_value_t in progress to check
* (may be NULL, if curval set)
* curval == val_value_t in progress to check
* (may be NULL, if newval set)
* val == val_value_t in progress to check
* editop == requested CRUD operation
*
* RETURNS:
* TRUE if user allowed this level of access to the value node
*********************************************************************/
static boolean
acm_extern_write (xml_msg_hdr_t *msg,
const xmlChar *user,
const val_value_t *newval,
const val_value_t *curval,
op_editop_t editop)
{
(void)msg;
(void)user;
(void)newval;
(void)curval;
(void)editop;
log_debug("\nacm_extern_write: return OK\n");
return TRUE;
} /* acm_extern_write */
/********************************************************************
* FUNCTION acm_extern_read_fn
*
* Check if the specified user is allowed to read a value node
*
* INPUTS:
* msg == XML header from incoming message in progress
* user == user name string
* val == val_value_t in progress to check
*
* RETURNS:
* TRUE if user allowed read access to the value node
*********************************************************************/
static boolean
acm_extern_read (xml_msg_hdr_t *msg,
const xmlChar *user,
const val_value_t *val)
{
(void)msg;
(void)user;
(void)val;
log_debug("\nacm_extern_read: return OK\n");
return TRUE;
} /* acm_extern_read */
#endif // ADD_ACM_EXTERN
/**************** Example External NACM Group Hook *******************/
#ifdef ADD_NACM_GROUP
/********************************************************************
* FUNCTION nacm_external_group_cbfn
*
* Get the list of group names for this username
* These groups are added to the usergroup cache for the session
* INPUTS:
* username: return the list of group names that this username
* is a member
* retgroups == address of return malloced string
* OUTPUTS:
* *retgroups is set to a malloced string that will be parsed.
* It contains a whitespace delimited list of group named
* ' group1 group2 group3'
* The caller will free this string with m__free
* RETURNS:
* status: if an error occurs the session will only use NACM groups
*********************************************************************/
static status_t
nacm_external_group_cbfn (const xmlChar *username,
xmlChar **retgroups)
{
if (retgroups == NULL) {
return ERR_NCX_INVALID_VALUE;
}
(void)username;
/* MUST use a function that allocates memory with m__getMem
* Will be freed by the caller with m__free macro
*/
*retgroups = xml_strdup("group1 group2 group5");
if (*retgroups == NULL) {
return ERR_INTERNAL_MEM;
}
return NO_ERR;
} /* nacm_external_group_cbfn */
#endif // ADD_NACM_GROUP
/************** Example External Log Vendor Hooks ***************/
#ifdef ADD_VENDOR_LOG
/********************************************************************
* FUNCTION log_vendor_send_fn
*
* Vendor function to consume log output (mandatory)
*
* INPUTS:
* app == "Facility" (Yangcli or Netconfd)
* level == Logging level (error, warn, info, debug, ..., debug4)
* fstr == format string (like printf)
* args == variable argument list
*
* RETURNS:
* void
*********************************************************************/
static void
log_vendor_send_fn (log_debug_app_t app,
log_debug_t level,
const char *fstr,
va_list args)
{
(void)app;
(void)level;
(void)fstr;
(void)args;
return;
} /* log_vendor_send_fn */
#endif // ADD_VENDOR_LOG
/*********** Example External NV-Storage Handler Hooks **********/
#ifdef ADD_NV_STORE_HOOK
#define EXAMPLE_CONFIG_SPEC (const xmlChar *)"/tmp/example-config.xml"
/********************************************************************
* FUNCTION example_nvsave
*
* Nvsave callback is invoked when some config needs to be saved
* to non-volatile storage
*
* INPUTS:
* encoding == encoding format for the config (xml only allowed value)
* filespec == filespec containing the config to save
*
* RETURNS:
* status; error indicates NV-save failed somehow
*
*********************************************************************/
static status_t
example_nvsave (ncx_display_mode_t encoding,
const xmlChar *filespec)
{
status_t res = NO_ERR;
if (filespec == NULL || *filespec == 0) {
res = ERR_NCX_INVALID_VALUE;
} else if (encoding != NCX_DISPLAY_MODE_XML) {
res = ERR_NCX_INVALID_VALUE;
} else {
res = ncxmod_copy_text_file(filespec, EXAMPLE_CONFIG_SPEC);
}
return res;
} /* example_nvsave */
/********************************************************************
* FUNCTION example_nvload
*
* Nvload callback invoked when some config needs to be read
* from non-volatile storage
*
* INPUTS:
* encoding == address of encoding for the config
* filespec == address of filespec containing the config that was loaded
*
* OUTPUTS:
* *encoding == set to the enum for the encoding used in the config
* *filespec == malloced filespec containing the config that was loaded
*
* RETURNS:
* status; error indicates NV-load failed somehow
* If return NO_ERR and *filespec == NULL then use the factory config
*
*********************************************************************/
static status_t
example_nvload (ncx_display_mode_t *encoding,
xmlChar **filespec)
{
log_debug("\nEnter example_nvload");
*filespec = NULL;
*encoding = NCX_DISPLAY_MODE_XML;
status_t res = NO_ERR;
if (ncxmod_test_filespec(EXAMPLE_CONFIG_SPEC)) {
/* file exists so copy the filespec */
*filespec = xml_strdup(EXAMPLE_CONFIG_SPEC);
if (*filespec == NULL) {
res = ERR_INTERNAL_MEM;
}
}
return res;
} /* example_nvload */
#endif // ADD_NV_STORE_HOOK
/*********** Example Transaction Management Hooks **********/
#ifdef ADD_TRANS_HOOK
/********************************************************************
* FUNCTION example_transaction_start
*
* The Start Transaction function is the user/system
* callback that is invoked before any changes to the
* candidate database will be committed.
*
* INPUTS:
* txcb == transaction control block in progress
*
* RETURNS:
* status
*
*********************************************************************/
static status_t
example_transaction_start (agt_cfg_transaction_t *txcb)
{
(void)txcb;
log_debug("\nEnter transaction_start example");
return NO_ERR;
} /* example_transaction_start */
/********************************************************************
* FUNCTION example_transaction_complete
*
* The Transaction Complete function is the
* user/system callback that is invoked after
* the transactions has been processed.
*
* INPUTS:
* txcb == transaction control block in progress
*
* RETURNS:
* none
*
*********************************************************************/
static void
example_transaction_complete (agt_cfg_transaction_t *txcb)
{
(void)txcb;
log_debug("\nEnter transaction_complete example");
return;
} /* example_transaction_complete */
#endif // ADD_TRANS_HOOK
/*********** Example YANG Object Template Callback **********/
#ifdef ADD_YANG_OBJ_TEMP
#define FL_ACME_1 0x1
/********************************************************************
* FUNCTION example_transaction_complete
*
* User function callback template when a YANG object is
* parsed by yang_obj.c. This API is invoked at the
* end of the resolve phase if the status is NO_ERR
* It is skipped if the object has errors detected at the time
*
* Callback is invoked to check extensions in an obj_template_t
* representing YANG data nodes
*
* Assume YANG module foo exists with extension acme1
*
* module foo {
* prefix f;
* ...
* extension acme1 { ... }
*
*
* The extension is used inside object definitions. e.g:
*
* leaf X {
* f:acme1;
* type string;
* }
*
* Assume there is a vendor bit defined for the user flags field
* ncx_yang_obj_cbfn_t
*
* Run an instrumentation-defined function
* for a 'object parsed' event
*
* INPUTS:
* mod == module that is being parsed now
* obj == object being parsed
*
*********************************************************************/
static void
example_obj_template_cbfn (ncx_module_t *mod,
struct obj_template_t_ *obj)
{
/* optional: use the module to check cetain module names to
* pre-filter the callback
*/
(void)mod;
/* get the appinfoQ for the object */
dlq_hdr_t *appinfoQ = obj_get_appinfoQ(obj);
if (appinfoQ == NULL) {
return; // error!
}
/* check the object template appinfoQ to see if the vendor
* extensions are present
*/
ncx_appinfo_t *appinfo =
ncx_find_appinfo(appinfoQ,
(const xmlChar *)"f",
(const xmlChar *)"acme1");
if (appinfo) {
OBJ_USER_FLAGS(obj) |= FL_ACME_1;
}
} /* example_obj_template_cbfn */
#endif // ADD_YANG_OBJ_TEMP
/*********** Example YANG Extension Handler Callback **********/
#ifdef ADD_YANG_EXTEN
/********************************************************************
* FUNCTION example_ext_cbfn
*
* One YANG Extension Handler Callback
*
* Callback is invoked to check a specific extension in an
* obj_template_t, typ_template_t, typ_def_t
*
* Assume the same YANG module foo exists with extension acme1
*
* The example callback does the same task as the
* example_obj_template_cbfn, using the per-callback approach
*
* Handle the parsing and processing of an external statement
* using the associated YANG extension statement
*
* This callback is invoked when the external statement is
* first encountered. The current token is the argument string
* if any or the identifier token if none.
* The next token is expected to be a semi-colon or a left brace
* The callback is expected to parse the closing semi-colon or
* entire sub-section including starting brace
*
* INPUTS:
* rawpcb == parser control block in progress (cast as void *)
* mod == module being processed
* tkc == token chain of module tokens parse in progress
* ext == extension definition record (allows a handler to
* process multiple extension types)
* cookie == cbfn_cookie from the extension 'ext'
* arg == argument string used in the external statement (if any)
* node_type == type of node being processed; direct parent
* statement of the external statement using the extension
* If NULL, then the parent statement is the module itself,
* and 'mod' should be used as the 'node' pointer
* node == pointer to node indicated by node_type
* OUTPUTS:
*
* RETURNS:
* status of processing
*
*********************************************************************/
static status_t
example_ext_cbfn (void *rawpcb, // struct yang_pcb_t_ *pcb
ncx_module_t *mod,
tk_chain_t *tkc,
struct ext_template_t_ *ext,
void *cookie,
const xmlChar *arg,
ncx_node_t node_type,
void *node)
{
(void)rawpcb;
(void)mod;
(void)tkc;
(void)ext;
(void)cookie;
(void)arg;
/* ignore this extension in all contexts except object template */
if (node_type != NCX_NT_OBJ) {
return NO_ERR;
}
/* get the object template */
obj_template_t *obj = (obj_template_t *)node;
/* set the acme1 bit */
OBJ_USER_FLAGS(obj) |= FL_ACME_1;
return NO_ERR;
} /* example_ext_cbfn */
#endif // ADD_YANG_EXTEN
/*********** Example RPC Command Complete Callback **********/
#ifdef ADD_RPC_COMPLETE
/********************************************************************
* FUNCTION example_command_complete_cbfn
*
* One RPC Command Complete Handler Callback
*
* The Command Complete callback is the user/system callback
* that is invoked after each client command is executed
* for the NETCONF or RESTCONF protocols.
*
* The Command Complete is typically used for retrieval
* operations (get, get-config, get-bulk) to release resources
* used during GET2 callbacks invoked during the operation.
*
* Max Callbacks: limited by memory only
*
* INPUTS:
* scb == session control block making the request
* msg == incoming rpc_msg_t in progress
* command_modname == YANG module name of command that is completed
* command_name == YANG RPC object name of command that is completed
*
* OUTPUTS:
* none
*
* RETURNS:
* none
*
*********************************************************************/
static void
example_command_complete_cbfn (ses_cb_t *scb,
rpc_msg_t *msg,
const xmlChar *command_modname,
const xmlChar *command_name)
{
(void)command_modname;
if (!xml_strcmp(command_name, (const xmlChar *)"get") ||
!xml_strcmp(command_name, (const xmlChar *)"get-config") ||
!xml_strcmp(command_name, (const xmlChar *)"get-bulk")) {
/* cleanup our internal get cache data
* example_clean_get2_cache(scb, msg);
*/
}
} /* example_command_complete_cbfn */
#endif // ADD_RPC_COMPLETE
/*********** Example Session Hook Callback **********/
#ifdef ADD_SESSION_HOOK
/********************************************************************
* FUNCTION example_session_hook
*
* The Session Hook callback is invoked when a session starts
* and ends.
* Use ses.h macros like SES_USERNAME(scb) to get
* data like client username
* Max Callbacks: No limit (except available heap memory)
*
* INPUTS:
* ses_event == session event type
* scb == session control block for the session event
*
* OUTPUTS:
* none
*
* RETURNS:
* none
*
*********************************************************************/
static void
example_session_hook (ncx_ses_event_t ses_event,
const ses_cb_t *scb)
{
assert(scb);
/* event name is either session-start or session-end */
const xmlChar *event_name = ncx_get_ses_event_str(ses_event);
/* peer_addr should be set */
const xmlChar *peer_addr = SES_PEERADDR(scb);
if (peer_addr == NULL) {
peer_addr = NCX_EL_LOCALHOST;
}
/* user_name should be set */
const xmlChar *user_name = SES_MY_USERNAME(scb);
if (user_name == NULL) {
user_name = NCX_EL_NOBODY;
}
/* protocol name should be set */
ncx_protocol_t protocol = ses_get_protocol(scb);
const xmlChar *protocol_name = ncx_get_protocol_name(protocol);
if (protocol_name == NULL) {
protocol_name = NCX_EL_NONE;
}
log_info("\nGot %s event from host %s, user %s, protocol %s\n",
event_name, peer_addr, user_name, protocol_name);
} /* example_session_hook */
#endif // ADD_SESSION_HOOK
/**************** Required System Library Hooks *******************/
/********************************************************************
* FUNCTION yp_system_init_profile
*
* system init server profile callback
*
* Initialize the server profile if needed
*
* INPUTS:
* profile == server profile to change if needed
*
*********************************************************************/
void
yp_system_init_profile (agt_profile_t *profile)
{
(void) profile;
log_debug("\nyp_system init profile\n");
/* example: use an external ACM module */
//profile->agt_acm_model = AGT_ACM_MODEL_EXTERNAL;
/* example: set the with-defaults also-supported bits
* from agt/agt.h:
* bitmask of the with-defaults enumerations that should be
* enabled in the server
* explicit: bit0
* trim: bit1
* report-all: bit2
* report-all-tagged: bit3
*
* uint8 agt_withdef_enabled;
*
* The basic-mode (agt_defaultStyle and agt_defaultStyleEnum)
* will be added by the server automatically, so a value of 0
* will not enable any 'also-supported' retrieval modes
* for the 'with-defaults' leaf
*/
//profile->agt_withdef_enabled = bit1 | bit3;
/* add to enable callhome reconnect after a close-session */
//profile->agt_callhome_reconnect = TRUE;
} /* yp_system_init_profile */
/********************************************************************
* FUNCTION yp_system_init1
*
* init1 system call
* this callback is invoked twice; before and after CLI processing
*
* INPUTS:
* pre_cli == TRUE if this call is before the CLI parameters
* have been read
* FALSE if this call is after the CLI parameters
* have been read
* RETURNS:
* status
*
*********************************************************************/
status_t yp_system_init1 (boolean pre_cli)
{
status_t res = NO_ERR;
log_debug("\nyp_system init1 (%s)\n",
pre_cli ? "pre-CLI" : "post-CLI");
if (pre_cli) {
#ifdef ADD_VENDOR_LOG
// example -- register vendor callback to consume logging output.
/* Note that output will not be re-directed to the vendor stream
* until AFTER --log-vendor is parsed by CLI processing or log_vendor
* is parsed by config file processing.
* Uncomment the following 2 lines to enable!!
*/
log_vendor_extern_register_send_fn(log_vendor_send_fn);
#endif // ADD_VENDOR_LOG
} else {
#ifdef ADD_ACM_EXTERN
/* example -- external NACM callbacks
* load module for external module
* with ncxmod_load_module
* register the external ACM callbacks
* this will have no affect unless the
* yp_system_init_profile fn sets the
* agt_acm_model to AGT_ACM_MODEL_EXTERNAL
*/
agt_acm_extern_register_callbacks(acm_extern_rpc,
acm_extern_notif,
acm_extern_write,
acm_extern_read);
#endif // ADD_ACM_EXTERN
#ifdef ADD_NV_STORE_HOOK
/* example -- register NV-storage handler to load/save config */
res = agt_register_local_nv_handler(example_nvload,
example_nvsave);
if (res != NO_ERR) {
return res;
}
#endif // ADD_NV_STORE_HOOK
#ifdef ADD_YANG_OBJ_TEMP
/* example -- Register a YANG Object Template Callback */
res = ncx_set_yang_obj_callback(example_obj_template_cbfn);
if (res != NO_ERR) {
return res;
}
#endif // ADD_YANG_OBJ_TEMP
#ifdef ADD_YANG_EXTEN
/* example -- Register an Extension Handler Callback */
res = ext_register_cbfn((const xmlChar *)"acme-ext",
(const xmlChar *)"acme1",
example_ext_cbfn,
NULL); // cookie
if (res != NO_ERR) {
return res;
}
#endif // ADD_YANG_EXTEN
#ifdef ADD_IPV6_FN
/* Example: register a type-specific callback
* In real usage at least 1 of the 3 callback functions
* must be set
*/
res = typ_userdef_register(NCXMOD_IETF_INET_TYPES,
(const xmlChar *)"ipv6-address-no-zone",
NULL, // validate_fn
my_ipv6_fn, // canonical_fn
NULL, // compare_fn
NULL); // cookie
if (res != NO_ERR) {
return res;
}
#endif // ADD_IPV6_FN
#ifdef ADD_USER_TYPE
/* Example: register a type-specific callback
* Show all 3 callbacks being used
*/
res = typ_userdef_register(USERTYPE_MODULE,
USERTYPE_TYPE,
dummy1_validate_fn,
dummy1_canonical_fn,
dummy1_compare_fn,
NULL); // cookie
if (res != NO_ERR) {
return res;
}
#endif // ADD_USER_TPYE
#ifdef ADD_SESSION_HOOK
/* Example: register a Session Hook callback
* uncomment following to enable
*/
res = agt_cb_session_hook_register(example_session_hook);
#endif // ADD_SESSION_HOOK
}
return res;
} /* yp_system_init1 */
/********************************************************************
* FUNCTION yp_system_init2
*
* init2 system call
* this callback is invoked twice; before and after
* load_running_config processing
*
* INPUTS:
* pre_load == TRUE if this call is before the running config
* has been loaded
* FALSE if this call is after the running config
* has been loaded
* RETURNS:
* status
*
*********************************************************************/
status_t
yp_system_init2 (boolean pre_load)
{
log_debug("\nyp_system init2 (%s)\n",
pre_load ? "pre-load-config" : "post-load-config");
if (pre_load) {
#ifdef ADD_NACM_GROUP
/* example -- Register a NACM External Groups Callback
* uncomment following to enable
*/
agt_acm_ietf_register_group_cbfn(nacm_external_group_cbfn);
#endif // ADD_NACM_GROUP
#ifdef ADD_RPC_COMPLETE
/* initialize a Command Complete callback */
res = agt_cb_command_complete_register(example_command_complete_cbfn);
#endif // ADD_RPC_COMPLETE
#ifdef ADD_TRANS_HOOK
/* example -- Register a Transaction Start callback */
res = agt_cb_trans_start_register(example_transaction_start);
/* example -- Register a Transaction Complete callback */
res = agt_cb_trans_complete_register(example_transaction_complete);
#endif // ADD_TRANS_HOOK
} else {
;
}
return NO_ERR;
} /* yp_system_init2 */
/********************************************************************
* FUNCTION yp_system_cleanup
*
* System cleanup callback
* this callback is invoked once during agt_cleanup
*
* INPUTS:
* none
*
* RETURNS:
* none
*
*********************************************************************/
void yp_system_cleanup (void)
{
log_debug("\nyp_system cleanup\n");
#ifdef ADD_SESSION_HOOK
/* Example: Unregister a Session Hook callback.
* This is optional; will get deleted at shutdown
* uncomment following to enable
*/
agt_cb_session_hook_unregister(example_session_hook);
#endif // ADD_SESSION_HOOK
#ifdef ADD_TRANS_HOOK
/* example -- Unregister a Transaction Start callback */
agt_cb_trans_start_unregister(example_transaction_start);
/* example -- Unregister a Transaction Complete callback */
agt_cb_trans_complete_unregister(example_transaction_complete);
#endif // ADD_TRANS_HOOK
} /* yp_system_cleanup */
/* END example-system.c */