/******************************************************************** * FUNCTION check_manager_hello * * Verify that the same NETCONF protocol verion is supported * by the manager and this server * * INPUTS: * scb == session control block * val == value struct for the hello message to check * * RETURNS: * status *********************************************************************/ static status_t check_manager_hello (ses_cb_t *scb, val_value_t *val) { val_value_t *caps, *cap; /* look for the NETCONF base capability string */ caps = val_find_child(val, NC_MODULE, NCX_EL_CAPABILITIES); if (caps && caps->res == NO_ERR) { if (ncx_protocol_enabled(NCX_PROTO_NETCONF11)) { for (cap = val_find_child(caps, NC_MODULE, NCX_EL_CAPABILITY); cap != NULL; cap = val_find_next_child(caps, NC_MODULE, NCX_EL_CAPABILITY, cap)) { if (cap->res == NO_ERR) { if (!xml_strcmp(VAL_STR(cap), CAP_BASE_URN11)) { if (LOGDEBUG3) { log_debug3("\nagt_hello: set " "protocol to base:1.1"); } return ses_set_protocol(scb, NCX_PROTO_NETCONF11); } } } } if (ncx_protocol_enabled(NCX_PROTO_NETCONF10)) { for (cap = val_find_child(caps, NC_MODULE, NCX_EL_CAPABILITY); cap != NULL; cap = val_find_next_child(caps, NC_MODULE, NCX_EL_CAPABILITY, cap)) { if (cap->res == NO_ERR) { if (!xml_strcmp(VAL_STR(cap), CAP_BASE_URN)) { if (LOGDEBUG3) { log_debug3("\nagt_hello: set " "protocol to base:1.0"); } return ses_set_protocol(scb, NCX_PROTO_NETCONF10); } } } } } log_info("\nagt_hello: no NETCONF base:1.0 or base:1.1 URI found"); return ERR_NCX_MISSING_VAL_INST; } /* check_manager_hello */
/******************************************************************** * FUNCTION process_server_hello * * Process the NETCONF server <hello> contents * * 1) Protocol capabilities * 2) Module capabilities * 3) Unrecognized capabilities * * INPUTS: * scb == session control block to set * hello == value struct for the hello message to check * * OUTPUTS: * server caps in the scb->mgrcb is set * * RETURNS: * status *********************************************************************/ static status_t process_server_hello (ses_cb_t *scb, val_value_t *hello) { val_value_t *caps, *sidval, *cap; mgr_scb_t *mscb; boolean c1, c2; status_t res; mscb = mgr_ses_get_mscb(scb); /* make sure the capabilities element is present * This should not fail, since already parsed this far */ caps = val_find_child(hello, NC_MODULE, NCX_EL_CAPABILITIES); if (!caps || caps->res != NO_ERR) { log_error("\nError: no <capabilities> found in server <hello>"); return ERR_NCX_MISSING_VAL_INST; } /* make sure the session-id element is present * This should not fail, since already parsed this far */ sidval = val_find_child(hello, NC_MODULE, NCX_EL_SESSION_ID); if (!sidval || sidval->res != NO_ERR) { log_error("\nError: no <session-id> found in server <hello>"); return ERR_NCX_MISSING_VAL_INST; } else { mscb->agtsid = VAL_UINT(sidval); } /* go through the capability nodes and construct a caplist */ for (cap = val_find_child(caps, NC_MODULE, NCX_EL_CAPABILITY); cap != NULL; cap = val_find_next_child(caps, NC_MODULE, NCX_EL_CAPABILITY, cap)) { if (cap->res != NO_ERR) { continue; } res = cap_add_std_string(&mscb->caplist, VAL_STR(cap)); if (res == ERR_NCX_SKIPPED) { res = cap_add_module_string(&mscb->caplist, VAL_STR(cap)); if (res == ERR_NCX_SKIPPED) { /* * if (ncx_warning_enabled(ERR_NCX_RCV_UNKNOWN_CAP)) { * log_warn("\nWarning: received unknown capability '%s'", * VAL_STR(cap)); * } */ if (LOGDEBUG2) { log_debug2("\nmgr: Got enterprise capability %s", VAL_STR(cap)); } /* hack: check for juniper 1.0 server * change the useprefix mode to TRUE to get * <rpc> operations to work with this server */ if (!xml_strcmp(VAL_STR(cap), CAP_JUNOS)) { if (LOGDEBUG) { log_debug("\nUsing XML prefixes to work " "with Junos 1.0 server\n"); } ncx_set_useprefix(TRUE); } res = cap_add_ent(&mscb->caplist, VAL_STR(cap)); if (res != NO_ERR) { return res; } } } } /* check if the mandatory base protocol capability was set */ res = NO_ERR; c1 = cap_std_set(&mscb->caplist, CAP_STDID_V1); c2 = cap_std_set(&mscb->caplist, CAP_STDID_V11); if (c1 && c2) { if (LOGDEBUG2) { log_debug2("\nmgr_hello: server supports " "base:1.0 and base:1.1"); } if (ses_protocol_requested(scb, NCX_PROTO_NETCONF11)) { if (LOGDEBUG2) { log_debug2("\nmgr_hello: set protocol to base:1.1 " "for session '%d'", scb->sid); } ses_set_protocol(scb, NCX_PROTO_NETCONF11); } else if (ses_protocol_requested(scb, NCX_PROTO_NETCONF10)) { if (LOGDEBUG2) { log_debug2("\nmgr_hello: set protocol to base:1.0 " "for session '%d'", scb->sid); } ses_set_protocol(scb, NCX_PROTO_NETCONF10); } else { log_error("\nError: Internal: no protocols requested, " "dropping session '%d'", scb->sid); res = ERR_NCX_MISSING_VAL_INST; } } else if (c1) { if (LOGDEBUG2) { log_debug2("\nmgr_hello: server supports " "base:1.0 only"); } if (ses_protocol_requested(scb, NCX_PROTO_NETCONF10)) { if (LOGDEBUG2) { log_debug2("\nmgr_hello: set protocol to base:1.0 " "for session '%d'", scb->sid); } ses_set_protocol(scb, NCX_PROTO_NETCONF10); } else { log_error("\nError: Server supports base:1.0 only;" "\n Protocol 'netconf1.0' not enabled, " "dropping session '%d'", scb->sid); res = ERR_NCX_MISSING_VAL_INST; } } else if (c2) { if (LOGDEBUG2) { log_debug2("\nmgr_hello: server supports " "base:1.1 only"); } if (ses_protocol_requested(scb, NCX_PROTO_NETCONF11)) { if (LOGDEBUG2) { log_debug2("\nmgr_hello: set protocol to base:1.1 " "for session '%d'", scb->sid); } ses_set_protocol(scb, NCX_PROTO_NETCONF11); } else { log_error("\nError: Server supports base:1.1 only;" "\n Protocol 'netconf1.1' not enabled, " "dropping session '%d'", scb->sid); res = ERR_NCX_MISSING_VAL_INST; } } else { log_error("\nError: no support for base:1.0 " "or base:1.1 found in server <hello>;" "\n dropping session '%d'", scb->sid); return ERR_NCX_MISSING_VAL_INST; } /* set target type var in the manager session control block */ c1 = cap_std_set(&mscb->caplist, CAP_STDID_WRITE_RUNNING); c2 = cap_std_set(&mscb->caplist, CAP_STDID_CANDIDATE); if (c1 && c2) { mscb->targtyp = NCX_AGT_TARG_CAND_RUNNING; } else if (c1) { mscb->targtyp = NCX_AGT_TARG_RUNNING; } else if (c2) { mscb->targtyp = NCX_AGT_TARG_CANDIDATE; } else { mscb->targtyp = NCX_AGT_TARG_NONE; if (LOGINFO) { log_info("\nmgr_hello: no writable target found for" " session %u (a:%u)", scb->sid, mscb->agtsid); } } /* set the startup type in the mscb */ if (cap_std_set(&mscb->caplist, CAP_STDID_STARTUP)) { mscb->starttyp = NCX_AGT_START_DISTINCT; } else { mscb->starttyp = NCX_AGT_START_MIRROR; } return NO_ERR; } /* process_server_hello */