/******************************************************************** * FUNCTION rpc_new_msg * * Malloc and initialize a new rpc_msg_t struct * * INPUTS: * none * RETURNS: * pointer to struct or NULL or memory error *********************************************************************/ rpc_msg_t * rpc_new_msg (void) { rpc_msg_t *msg; msg = m__getObj(rpc_msg_t); if (!msg) { return NULL; } memset(msg, 0x0, sizeof(rpc_msg_t)); xml_msg_init_hdr(&msg->mhdr); dlq_createSQue(&msg->rpc_dataQ); msg->rpc_input = val_new_value(); if (!msg->rpc_input) { rpc_free_msg(msg); return NULL; } msg->rpc_top_editop = OP_EDITOP_MERGE; return msg; } /* rpc_new_msg */
/******************************************************************** * FUNCTION mgr_rpc_new_request * * Malloc and initialize a new mgr_rpc_req_t struct * * INPUTS: * scb == session control block * * RETURNS: * pointer to struct or NULL or memory error *********************************************************************/ mgr_rpc_req_t * mgr_rpc_new_request (ses_cb_t *scb) { mgr_scb_t *mscb; mgr_rpc_req_t *req; char numbuff[NCX_MAX_NUMLEN]; req = m__getObj(mgr_rpc_req_t); if (!req) { return NULL; } memset(req, 0x0, sizeof(mgr_rpc_req_t)); mscb = mgr_ses_get_mscb(scb); sprintf(numbuff, "%u", mscb->next_id); if (mscb->next_id >= MGR_MAX_REQUEST_ID) { mscb->next_id = 0; } else { mscb->next_id++; } req->msg_id = xml_strdup((const xmlChar *)numbuff); if (req->msg_id) { xml_msg_init_hdr(&req->mhdr); xml_init_attrs(&req->attrs); } else { m__free(req); req = NULL; } return req; } /* mgr_rpc_new_request */
/******************************************************************** * FUNCTION mgr_hello_send * * Send the manager <hello> message to the server on the * specified session * * INPUTS: * scb == session control block * * RETURNS: * status *********************************************************************/ status_t mgr_hello_send (ses_cb_t *scb) { val_value_t *mycaps; xml_msg_hdr_t msg; status_t res; xml_attrs_t attrs; boolean anyout; xmlns_id_t nc_id; #ifdef DEBUG if (!scb) { return SET_ERROR(ERR_INTERNAL_PTR); } #endif #ifdef MGR_HELLO_DEBUG if (LOGDEBUG2) { log_debug2("\nmgr sending hello on session %d", scb->sid); } #endif res = NO_ERR; anyout = FALSE; xml_msg_init_hdr(&msg); xml_init_attrs(&attrs); nc_id = xmlns_nc_id(); /* get my client caps, custom made for this session */ mycaps = mgr_cap_get_ses_capsval(scb); if (!mycaps) { res = SET_ERROR(ERR_INTERNAL_PTR); } /* setup the prefix map with the NETCONF namespace */ if (res == NO_ERR) { res = xml_msg_build_prefix_map(&msg, &attrs, TRUE, FALSE); } /* send the <?xml?> directive */ if (res == NO_ERR) { res = ses_start_msg(scb); } /* start the hello element */ if (res == NO_ERR) { anyout = TRUE; xml_wr_begin_elem_ex(scb, &msg, 0, nc_id, NCX_EL_HELLO, &attrs, ATTRQ, 0, START); } /* send the capabilities list */ if (res == NO_ERR) { xml_wr_full_val(scb, &msg, mycaps, NCX_DEF_INDENT); } /* finish the hello element */ if (res == NO_ERR) { xml_wr_end_elem(scb, &msg, nc_id, NCX_EL_HELLO, 0); } /* finish the message */ if (anyout) { ses_finish_msg(scb); } xml_clean_attrs(&attrs); xml_msg_clean_hdr(&msg); if (mycaps != NULL) { val_free_value(mycaps); } return res; } /* mgr_hello_send */
/******************************************************************** * FUNCTION mgr_hello_dispatch * * Handle an incoming <hello> message from the client * * INPUTS: * scb == session control block * top == top element descriptor *********************************************************************/ void mgr_hello_dispatch (ses_cb_t *scb, xml_node_t *top) { val_value_t *val; ncx_module_t *mod; obj_template_t *obj; mgr_scb_t *mscb; xml_msg_hdr_t msg; status_t res; #ifdef DEBUG if (!scb || !top) { SET_ERROR(ERR_INTERNAL_PTR); return; } #endif #ifdef MGR_HELLO_DEBUG if (LOGDEBUG) { log_debug("\nmgr_hello got node"); } if (LOGDEBUG2) { xml_dump_node(top); } #endif mscb = mgr_ses_get_mscb(scb); /* only process this message in hello wait state */ if (scb->state != SES_ST_HELLO_WAIT) { /* TBD: stats update */ if (LOGINFO) { log_info("\nmgr_hello dropped, wrong state for session %d", scb->sid); } return; } /* init local vars */ res = NO_ERR; val = NULL; obj = NULL; xml_msg_init_hdr(&msg); /* get a value struct to hold the server hello msg */ val = val_new_value(); if (!val) { res = ERR_INTERNAL_MEM; } /* get the type definition from the registry */ if (res == NO_ERR) { mod = ncx_find_module(NC_MODULE, NULL); if (mod) { obj = ncx_find_object(mod, MGR_SERVER_HELLO_OBJ); } if (!obj) { /* netconf module should have loaded this definition */ res = SET_ERROR(ERR_INTERNAL_PTR); } } /* parse an server hello message */ if (res == NO_ERR) { res = mgr_val_parse(scb, obj, top, val); } /* examine the server capability list * and it matches the server protocol version */ if (res == NO_ERR) { res = process_server_hello(scb, val); } /* report first error and close session */ if (res != NO_ERR) { if (LOGINFO) { log_info("\nmgr_connect error (%s)\n dropping session %u (a:%u)", get_error_string(res), scb->sid, mscb->agtsid, res); } } else { scb->state = SES_ST_IDLE; if (LOGDEBUG) { log_debug("\nmgr_hello manager hello ok"); } } if (val) { val_free_value(val); } } /* mgr_hello_dispatch */
/******************************************************************** * FUNCTION agt_hello_send * * Send the server <hello> message to the manager on the * specified session * * INPUTS: * scb == session control block * * RETURNS: * status *********************************************************************/ status_t agt_hello_send (ses_cb_t *scb) { assert( scb && "scb is NULL!" ); status_t res = NO_ERR; boolean anyout = FALSE; xmlns_id_t nc_id = xmlns_nc_id(); xml_msg_hdr_t msg; xml_msg_init_hdr(&msg); xml_attrs_t attrs; xml_init_attrs(&attrs); /* start the hello timeout */ (void)time(&scb->hello_time); /* get the server caps */ val_value_t *mycaps = agt_cap_get_capsval(); if (!mycaps) { res = SET_ERROR(ERR_INTERNAL_PTR); } /* setup the prefix map with the NETCONF and NCX namepsaces */ if (res == NO_ERR) { res = xml_msg_build_prefix_map(&msg, &attrs, TRUE, FALSE); } /* send the <?xml?> directive */ if (res == NO_ERR) { res = ses_start_msg(scb); } boolean mode_started = FALSE; if (res == NO_ERR) { ses_start_msg_mode(scb); mode_started = TRUE; } int32 msg_indent = ses_message_indent_count(scb); /* start the hello element */ if (res == NO_ERR) { anyout = TRUE; xml_wr_begin_elem_ex(scb, &msg, 0, nc_id, NCX_EL_HELLO, &attrs, TRUE, max(msg_indent, 0), FALSE); } /* send the capabilities list */ if (res == NO_ERR) { xml_wr_full_val(scb, &msg, mycaps, msg_indent); } /* send the session ID */ if (res == NO_ERR) { xml_wr_begin_elem(scb, &msg, nc_id, nc_id, NCX_EL_SESSION_ID, msg_indent); } if (res == NO_ERR) { xmlChar numbuff[NCX_MAX_NUMLEN]; snprintf((char *)numbuff, sizeof(numbuff), "%d", scb->sid); ses_putstr(scb, numbuff); } if (res == NO_ERR) { xml_wr_end_elem(scb, &msg, nc_id, NCX_EL_SESSION_ID, -1); } /* finish the hello element */ if (res == NO_ERR) { xml_wr_end_elem(scb, &msg, nc_id, NCX_EL_HELLO, max(msg_indent, 0)); } /* finish the message */ if (anyout) { ses_finish_msg(scb); } if (mode_started) { ses_stop_msg_mode(scb); } xml_clean_attrs(&attrs); xml_msg_clean_hdr(&msg); return res; } /* agt_hello_send */
/******************************************************************** * FUNCTION agt_hello_dispatch * * Handle an incoming <hello> message from the client * * INPUTS: * scb == session control block * top == top element descriptor *********************************************************************/ void agt_hello_dispatch (ses_cb_t *scb, xml_node_t *top) { assert( scb && "scb is NULL!" ); assert( top && "top is NULL!" ); if (LOGDEBUG2) { log_debug2("\nagt_hello: got node"); if (LOGDEBUG3) { xml_dump_node(top); } } /* only process this message in hello wait state */ if (scb->state != SES_ST_HELLO_WAIT) { log_info("\nagt_hello dropped, wrong state " "(%d) for session %d", scb->state, scb->sid); mytotals->inBadHellos++; mytotals->droppedSessions++; agt_ses_request_close(scb, scb->sid, SES_TR_BAD_HELLO); return; } /* init local vars */ status_t res = NO_ERR; obj_template_t *obj = NULL; xml_msg_hdr_t msg; xml_msg_init_hdr(&msg); /* get a value struct to hold the client hello msg */ val_value_t *val = val_new_value(); if (!val) { res = ERR_INTERNAL_MEM; } /* get the type definition from the registry */ if (res == NO_ERR) { ncx_module_t *mod = ncx_find_module(NC_MODULE, NULL); if (mod) { obj = ncx_find_object(mod, CLIENT_HELLO_CON); } if (!obj) { /* netconf module should have loaded this definition */ res = SET_ERROR(ERR_INTERNAL_PTR); } } /* parse a manager hello message */ if (res == NO_ERR) { res = agt_val_parse_nc(scb, &msg, obj, top, NCX_DC_STATE, val); } /* check that the NETCONF base capability is included * and it matches the server protocol version */ if (res == NO_ERR) { res = check_manager_hello(scb, val); } /* report first error and close session */ if (res != NO_ERR) { if (LOGINFO) { log_info("\nagt_connect error (%s), dropping session %d", get_error_string(res), scb->sid); } mytotals->inBadHellos++; mytotals->droppedSessions++; agt_ses_request_close(scb, scb->sid, SES_TR_BAD_HELLO); } else { scb->state = SES_ST_IDLE; scb->active = TRUE; /* start the timer for the first rpc request */ (void)time(&scb->last_rpc_time); if (LOGDEBUG) { log_debug("\nSession %d for %s@%s now active", scb->sid, scb->username, scb->peeraddr); if (ses_get_protocol(scb) == NCX_PROTO_NETCONF11) { log_debug_append(" (base:1.1)"); } else { log_debug_append(" (base:1.0)"); } } } if (val) { val_free_value(val); } } /* agt_hello_dispatch */
/******************************************************************** * FUNCTION mgr_rpc_send_request * * Send an <rpc> request to the agent on the specified session * non-blocking send, reply function will be called when * one is received or a timeout occurs * * INPUTS: * scb == session control block * req == request to send * rpyfn == reply callback function * * RETURNS: * status *********************************************************************/ status_t mgr_rpc_send_request (ses_cb_t *scb, mgr_rpc_req_t *req, mgr_rpc_cbfn_t rpyfn) { xml_msg_hdr_t msg; xml_attr_t *attr; status_t res; boolean anyout; xmlns_id_t nc_id; #ifdef DEBUG if (!scb || !req || !rpyfn) { return SET_ERROR(ERR_INTERNAL_PTR); } #endif #ifdef MGR_HELLO_DEBUG log_debug2("\nmgr sending RPC request %s on session %d", req->msg_id, scb->sid); #endif anyout = FALSE; xml_msg_init_hdr(&msg); nc_id = xmlns_nc_id(); /* make sure the message-id attribute is not already present */ attr = xml_find_attr_q(&req->attrs, 0, NCX_EL_MESSAGE_ID); if (attr) { dlq_remove(attr); xml_free_attr(attr); } /* setup the prefix map with the NETCONF (and maybe NCX) namespace */ res = xml_msg_build_prefix_map(&msg, &req->attrs, FALSE, (req->data->nsid == xmlns_ncx_id())); /* add the message-id attribute */ if (res == NO_ERR) { res = xml_add_attr(&req->attrs, 0, NCX_EL_MESSAGE_ID, req->msg_id); } /* set perf timestamp in case response timing active */ gettimeofday(&req->perfstarttime, NULL); /* send the <?xml?> directive */ if (res == NO_ERR) { res = ses_start_msg(scb); } /* start the <rpc> element */ if (res == NO_ERR) { anyout = TRUE; xml_wr_begin_elem_ex(scb, &msg, 0, nc_id, NCX_EL_RPC, &req->attrs, ATTRQ, 0, START); } /* send the method and parameters */ if (res == NO_ERR) { xml_wr_full_val(scb, &msg, req->data, NCX_DEF_INDENT); } /* finish the <rpc> element */ if (res == NO_ERR) { xml_wr_end_elem(scb, &msg, nc_id, NCX_EL_RPC, 0); } /* finish the message */ if (anyout) { ses_finish_msg(scb); } if (res == NO_ERR) { req->replycb = rpyfn; add_request(scb, req); } xml_msg_clean_hdr(&msg); return res; } /* mgr_rpc_send_request */