Consider this simplified example, that represents GET2 callback for the node type of “choice”.
... choice type { case interface { // active case leaf interface { type if:interface-ref; } } case case-network { leaf next-hop-host { type inet:ip-address; } } } ...
The following C API code exemplifies a simple GET2 callback function for the data model, which returns the name of the active case and child terminal nodes in the active case when it is requested.
/******************************************************************** * FUNCTION get2_choice_type * * Path: /type * * INPUTS: * scb == session control block making the request * msg == incoming XML message header * get2cb == get2 control block for this callback request * * OUTPUTS: * return_valQ is filled with malloced val_value_t nodes * the a backptr to a constant string containing the case * name that is active * * RETURNS: * status: * NO_ERR if executed OK and found OK * ERR_NCX_NO_INSTANCE warning if no instance found * ********************************************************************/ static status_t get2_choice_type (ses_cb_t *scb, xml_msg_hdr_t *msg, getcb_get2_t *get2cb) { (void)scb; (void)msg; status_t res = NO_ERR; /* check the callback mode type */ getcb_mode_t cbmode = GETCB_GET2_CBMODE(get2cb); switch (cbmode) { case GETCB_GET_VALUE: break; case GETCB_GETNEXT_VALUE: return ERR_NCX_NO_INSTANCE; default: return SET_ERROR(ERR_INTERNAL_VAL); } /* get the active case * callback based on instances in the system * It may be NULL if no active case */ const xmlChar *active_case_modname = NULL; const xmlChar *active_case = (const xmlChar *)"interface"; /* Set the active case to the specified object */ res = getcb_set_active_case(get2cb, active_case_modname, active_case); if (active_case == NULL) { return res; } /* get the template for the active case */ obj_template_t *choice_obj = GETCB_GET2_OBJ(get2cb); if (choice_obj == NULL) { return ERR_NCX_NOT_FOUND; } obj_template_t *case_obj = obj_find_child(choice_obj, active_case_modname, active_case); if (case_obj == NULL) { return ERR_NCX_NOT_FOUND; } /* return all the leaf and leaf-list instances that are child nodes * of the active case. */ val_value_t *chval = NULL; if (!xml_strcmp(active_case, (const xmlChar *)"interface")) { /* pretend leaf 'interface' is present */ chval = agt_make_leaf2(case_obj, active_case_modname, (const xmlChar *)"interface", (const xmlChar *)"ethernet1/1/1", &res); if (chval) { getcb_add_return_val(get2cb, chval); } else { return res; } } else { res = SET_ERROR(ERR_INTERNAL_VAL); } return res; } /* get2_choice_type */
NOTE:
Note that any leaf or leaf-list nodes that are in nested “choice” element within the active case are not returned. These are considered complex objects and the caller will ask for nested choice, list, and container nodes in a separate call .
To ensure that the GET2 callback is working as expected an application can retrieve running configuration and device state information as follows:
<?xml version="1.0" encoding="UTF-8"?> <rpc message-id="3" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <get> <filter type="subtree"> <interface xmlns="http://yumaworks.com/ns/interfaces" /> </filter> </get> </rpc>
The server may reply with:
<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <interface xmlns="http://yumaworks.com/ns/interfaces">ethernet1/1/1 </interface> </rpc-reply>