int handle_subagent_set_response(int op, netsnmp_session * session, int reqid, netsnmp_pdu *pdu, void *magic) { netsnmp_session *retsess; struct agent_netsnmp_set_info *asi; if (op != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE || magic == NULL) { return 1; } DEBUGMSGTL(("agentx/subagent", "handling agentx subagent set response (mode=%d,req=0x%x," "trans=0x%x,sess=0x%x)\n", pdu->command, pdu->reqid,pdu->transid, pdu->sessid)); pdu = snmp_clone_pdu(pdu); asi = (struct agent_netsnmp_set_info *) magic; retsess = asi->sess; asi->errstat = pdu->errstat; if (asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE1) { /* * reloop for RESERVE2 mode, an internal only agent mode */ /* * XXX: check exception statuses of reserve1 first */ if (!pdu->errstat) { asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_RESERVE2; snmp_async_send(agentx_callback_sess, pdu, handle_subagent_set_response, asi); DEBUGMSGTL(("agentx/subagent", " going from RESERVE1 -> RESERVE2\n")); return 1; } } else { if (asi->mode == SNMP_MSG_INTERNAL_SET_FREE || asi->mode == SNMP_MSG_INTERNAL_SET_UNDO || asi->mode == SNMP_MSG_INTERNAL_SET_COMMIT) { free_set_vars(retsess, pdu); } snmp_free_varbind(pdu->variables); pdu->variables = NULL; /* the variables were added by us */ } netsnmp_assert(retsess != NULL); pdu->command = AGENTX_MSG_RESPONSE; pdu->version = retsess->version; if (!snmp_send(retsess, pdu)) { snmp_free_pdu(pdu); } DEBUGMSGTL(("agentx/subagent", " FINISHED\n")); return 1; }
/* * send_trap_to_sess: sends a trap to a session but assumes that the * pdu is constructed correctly for the session type. */ void send_trap_to_sess(netsnmp_session * sess, netsnmp_pdu *template_pdu) { netsnmp_pdu *pdu; int result; int len; if (!sess || !template_pdu) return; DEBUGMSGTL(("trap", "sending trap type=%d, version=%ld\n", template_pdu->command, sess->version)); #ifndef NETSNMP_DISABLE_SNMPV1 if (sess->version == SNMP_VERSION_1 && (template_pdu->command != SNMP_MSG_TRAP)) return; /* Skip v1 sinks for v2 only traps */ if (sess->version != SNMP_VERSION_1 && (template_pdu->command == SNMP_MSG_TRAP)) return; /* Skip v2+ sinks for v1 only traps */ #endif template_pdu->version = sess->version; pdu = snmp_clone_pdu(template_pdu); pdu->sessid = sess->sessid; /* AgentX only ? */ if ( template_pdu->command == SNMP_MSG_INFORM #ifdef USING_AGENTX_PROTOCOL_MODULE || template_pdu->command == AGENTX_MSG_NOTIFY #endif ) { result = snmp_async_send(sess, pdu, &handle_inform_response, NULL); } else { if ((sess->version == SNMP_VERSION_3) && (pdu->command == SNMP_MSG_TRAP2) && (sess->securityEngineIDLen == 0)) { u_char tmp[SPRINT_MAX_LEN]; len = snmpv3_get_engineID(tmp, sizeof(tmp)); memdup(&pdu->securityEngineID, tmp, len); pdu->securityEngineIDLen = len; } result = snmp_send(sess, pdu); } if (result == 0) { snmp_sess_perror("snmpd: send_trap", sess); snmp_free_pdu(pdu); } else { snmp_increment_statistic(STAT_SNMPOUTTRAPS); snmp_increment_statistic(STAT_SNMPOUTPKTS); } }
static int send_pdu(netsnmp_session *ss, netsnmp_pdu *pdu, int kind, int link_id) { int status; netsnmp_callback cb; cb = kind == SNMP_LINK_UP ? link_up_cb : link_down_cb; status = snmp_async_send(ss, pdu, cb, (void *) link_id); if (status == 0) { snmp_log(LOG_ERR, "Failed to send async request.\n"); snmp_free_pdu(pdu); } return status; }
/* * send_trap_to_sess: sends a trap to a session but assumes that the * pdu is constructed correctly for the session type. */ void send_trap_to_sess(netsnmp_session * sess, netsnmp_pdu *template_pdu) { netsnmp_pdu *pdu; int result; if (!sess || !template_pdu) return; DEBUGMSGTL(("trap", "sending trap type=%d, version=%d\n", template_pdu->command, sess->version)); #ifndef DISABLE_SNMPV1 if (sess->version == SNMP_VERSION_1 && (template_pdu->command != SNMP_MSG_TRAP)) return; /* Skip v1 sinks for v2 only traps */ #endif template_pdu->version = sess->version; pdu = snmp_clone_pdu(template_pdu); pdu->sessid = sess->sessid; /* AgentX only ? */ if ( template_pdu->command == SNMP_MSG_INFORM #ifdef USING_AGENTX_PROTOCOL_MODULE || template_pdu->command == AGENTX_MSG_NOTIFY #endif ) { result = snmp_async_send(sess, pdu, &handle_inform_response, NULL); } else { result = snmp_send(sess, pdu); } if (result == 0) { snmp_sess_perror("snmpd: send_trap", sess); snmp_free_pdu(pdu); } else { snmp_increment_statistic(STAT_SNMPOUTTRAPS); snmp_increment_statistic(STAT_SNMPOUTPKTS); } }
int handle_next_pass(struct agent_snmp_session *asp) { int status; struct snmp_pdu *pdu = asp->pdu; struct request_list *req_p, *next_req; if ( asp->outstanding_requests != NULL ) return SNMP_ERR_NOERROR; status = handle_var_list( asp ); if ( asp->outstanding_requests != NULL ) { if ( status == SNMP_ERR_NOERROR ) { /* Send out any subagent requests */ for ( req_p = asp->outstanding_requests ; req_p != NULL ; req_p = req_p->next_request ) { snmp_async_send( req_p->session, req_p->pdu, req_p->callback, req_p->cb_data ); } asp->pdu = snmp_clone_pdu( pdu ); asp->pdu->variables = pdu->variables; pdu->variables = NULL; } else { /* discard outstanding requests */ for ( req_p = asp->outstanding_requests ; req_p != NULL ; req_p = next_req ) { next_req = req_p->next_request; free( req_p ); } asp->outstanding_requests = NULL; } } return status; }
/* * * AgentX State diagram. [mode] = internal mode it's mapped from: * * TESTSET -success-> COMMIT -success-> CLEANUP * [RESERVE1] [ACTION] [COMMIT] * | | * | \--failure-> UNDO * | [UNDO] * | * --failure-> CLEANUP * [FREE] */ int agentx_master_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_session *ax_session = (netsnmp_session *) handler->myvoid; netsnmp_request_info *request = requests; netsnmp_pdu *pdu; void *cb_data; int result; DEBUGMSGTL(("agentx/master", "agentx master handler starting, mode = 0x%02x\n", reqinfo->mode)); if (!ax_session) { netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR); return SNMP_ERR_NOERROR; } /* * build a new pdu based on the pdu type coming in */ switch (reqinfo->mode) { case MODE_GET: pdu = snmp_pdu_create(AGENTX_MSG_GET); break; case MODE_GETNEXT: pdu = snmp_pdu_create(AGENTX_MSG_GETNEXT); break; case MODE_GETBULK: /* WWWXXX */ pdu = snmp_pdu_create(AGENTX_MSG_GETNEXT); break; case MODE_SET_RESERVE1: pdu = snmp_pdu_create(AGENTX_MSG_TESTSET); break; case MODE_SET_RESERVE2: /* * don't do anything here for AgentX. Assume all is fine * and go on since AgentX only has one test phase. */ return SNMP_ERR_NOERROR; case MODE_SET_ACTION: pdu = snmp_pdu_create(AGENTX_MSG_COMMITSET); break; case MODE_SET_UNDO: pdu = snmp_pdu_create(AGENTX_MSG_UNDOSET); break; case MODE_SET_COMMIT: case MODE_SET_FREE: pdu = snmp_pdu_create(AGENTX_MSG_CLEANUPSET); break; default: snmp_log(LOG_WARNING, "unsupported mode for agentx/master called\n"); return SNMP_ERR_NOERROR; } if (!pdu) { netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR); return SNMP_ERR_NOERROR; } pdu->version = AGENTX_VERSION_1; pdu->reqid = snmp_get_next_transid(); pdu->transid = reqinfo->asp->pdu->transid; pdu->sessid = ax_session->subsession->sessid; if (reginfo->contextName) { pdu->community = (u_char *) strdup(reginfo->contextName); pdu->community_len = strlen(reginfo->contextName); pdu->flags |= AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT; } if (ax_session->subsession->flags & AGENTX_MSG_FLAG_NETWORK_BYTE_ORDER) pdu->flags |= AGENTX_MSG_FLAG_NETWORK_BYTE_ORDER; while (request) { size_t nlen = request->requestvb->name_length; oid *nptr = request->requestvb->name; DEBUGMSGTL(("agentx/master","request for variable (")); DEBUGMSGOID(("agentx/master", nptr, nlen)); DEBUGMSG(("agentx/master", ")\n")); /* * loop through all the requests and create agentx ones out of them */ if (reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK) { if (snmp_oid_compare(nptr, nlen, request->subtree->start_a, request->subtree->start_len) < 0) { DEBUGMSGTL(("agentx/master","inexact request preceeding region (")); DEBUGMSGOID(("agentx/master", request->subtree->start_a, request->subtree->start_len)); DEBUGMSG(("agentx/master", ")\n")); nptr = request->subtree->start_a; nlen = request->subtree->start_len; request->inclusive = 1; } if (request->inclusive) { DEBUGMSGTL(("agentx/master", "INCLUSIVE varbind ")); DEBUGMSGOID(("agentx/master", nptr, nlen)); DEBUGMSG(("agentx/master", " scoped to ")); DEBUGMSGOID(("agentx/master", request->range_end, request->range_end_len)); DEBUGMSG(("agentx/master", "\n")); snmp_pdu_add_variable(pdu, nptr, nlen, ASN_PRIV_INCL_RANGE, (u_char *) request->range_end, request->range_end_len * sizeof(oid)); request->inclusive = 0; } else { DEBUGMSGTL(("agentx/master", "EXCLUSIVE varbind ")); DEBUGMSGOID(("agentx/master", nptr, nlen)); DEBUGMSG(("agentx/master", " scoped to ")); DEBUGMSGOID(("agentx/master", request->range_end, request->range_end_len)); DEBUGMSG(("agentx/master", "\n")); snmp_pdu_add_variable(pdu, nptr, nlen, ASN_PRIV_EXCL_RANGE, (u_char *) request->range_end, request->range_end_len * sizeof(oid)); } } else { snmp_pdu_add_variable(pdu, request->requestvb->name, request->requestvb->name_length, request->requestvb->type, request->requestvb->val.string, request->requestvb->val_len); } /* * mark the request as delayed */ if (pdu->command != AGENTX_MSG_CLEANUPSET) request->delegated = REQUEST_IS_DELEGATED; else request->delegated = REQUEST_IS_NOT_DELEGATED; /* * next... */ request = request->next; } /* * When the master sends a CleanupSet PDU, it will never get a response * back from the subagent. So we shouldn't allocate the * netsnmp_delegated_cache structure in this case. */ if (pdu->command != AGENTX_MSG_CLEANUPSET) cb_data = netsnmp_create_delegated_cache(handler, reginfo, reqinfo, requests, (void *) ax_session); else cb_data = NULL; /* * send the requests out. */ DEBUGMSGTL(("agentx", "sending pdu (req=0x%x,trans=0x%x,sess=0x%x)\n", (unsigned)pdu->reqid, (unsigned)pdu->transid, (unsigned)pdu->sessid)); result = snmp_async_send(ax_session, pdu, agentx_got_response, cb_data); if (result == 0) { snmp_free_pdu(pdu); } return SNMP_ERR_NOERROR; }
/* * Configure special parameters on the session. * Currently takes the parameter configured and changes it if something * was configured. It becomes "-c" if the community string from the pdu * is placed on the session. */ int proxy_fill_in_session(netsnmp_mib_handler *handler, netsnmp_agent_request_info *reqinfo, void **configured) { netsnmp_session *session; struct simple_proxy *sp; sp = (struct simple_proxy *) handler->myvoid; if (!sp) { return 0; } session = sp->sess; if (!session) { return 0; } #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C) #if defined(DISABLE_SNMPV1) if (session->version == SNMP_VERSION_2c) { #else #if defined(DISABLE_SNMPV2C) if (session->version == SNMP_VERSION_1) { #else if (session->version == SNMP_VERSION_1 || session->version == SNMP_VERSION_2c) { #endif #endif /* * Check if session has community string defined for it. * If not, need to extract community string from the pdu. * Copy to session and set 'configured' to indicate this. */ if (session->community_len == 0) { DEBUGMSGTL(("proxy", "session has no community string\n")); if (reqinfo->asp == NULL || reqinfo->asp->pdu == NULL || reqinfo->asp->pdu->community_len == 0) { return 0; } *configured = malloc(strlen("-c") + 1); strcpy(*configured, "-c"); DEBUGMSGTL(("proxy", "pdu has community string\n")); session->community_len = reqinfo->asp->pdu->community_len; session->community = malloc(session->community_len + 1); strncpy((char *)session->community, (const char *)reqinfo->asp->pdu->community, session->community_len); } } #endif return 1; } /* * Free any specially configured parameters used on the session. */ void proxy_free_filled_in_session_args(netsnmp_session *session, void **configured) { /* Only do comparisions, etc., if something was configured */ if (*configured == NULL) { return; } /* If used community string from pdu, release it from session now */ if (strcmp((const char *)(*configured), "-c") == 0) { free(session->community); session->community = NULL; session->community_len = 0; } free((u_char *)(*configured)); *configured = NULL; } void init_proxy(void) { snmpd_register_config_handler("proxy", proxy_parse_config, proxy_free_config, "[snmpcmd args] host oid [remoteoid]"); } void shutdown_proxy(void) { proxy_free_config(); } int proxy_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_pdu *pdu; struct simple_proxy *sp; oid *ourname; size_t ourlength; netsnmp_request_info *request = requests; u_char *configured = NULL; DEBUGMSGTL(("proxy", "proxy handler starting, mode = %d\n", reqinfo->mode)); switch (reqinfo->mode) { case MODE_GET: case MODE_GETNEXT: case MODE_GETBULK: /* WWWXXX */ pdu = snmp_pdu_create(reqinfo->mode); break; case MODE_SET_ACTION: pdu = snmp_pdu_create(SNMP_MSG_SET); break; case MODE_SET_UNDO: /* * If we set successfully (status == NOERROR), * we can't back out again, so need to report the fact. * If we failed to set successfully, then we're fine. */ for (request = requests; request; request=request->next) { if (request->status == SNMP_ERR_NOERROR) { netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_UNDOFAILED); return SNMP_ERR_UNDOFAILED; } } return SNMP_ERR_NOERROR; case MODE_SET_RESERVE1: case MODE_SET_RESERVE2: case MODE_SET_FREE: case MODE_SET_COMMIT: /* * Nothing to do in this pass */ return SNMP_ERR_NOERROR; default: snmp_log(LOG_WARNING, "unsupported mode for proxy called (%d)\n", reqinfo->mode); return SNMP_ERR_NOERROR; } sp = (struct simple_proxy *) handler->myvoid; if (!pdu || !sp) { netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR); return SNMP_ERR_NOERROR; } while (request) { ourname = request->requestvb->name; ourlength = request->requestvb->name_length; if (sp->base_len > 0) { if ((ourlength - sp->name_len + sp->base_len) > MAX_OID_LEN) { /* * too large */ snmp_log(LOG_ERR, "proxy oid request length is too long\n"); return SNMP_ERR_NOERROR; } /* * suffix appended? */ DEBUGMSGTL(("proxy", "length=%d, base_len=%d, name_len=%d\n", ourlength, sp->base_len, sp->name_len)); if (ourlength > (int) sp->name_len) memcpy(&(sp->base[sp->base_len]), &(ourname[sp->name_len]), sizeof(oid) * (ourlength - sp->name_len)); ourlength = ourlength - sp->name_len + sp->base_len; ourname = sp->base; } snmp_pdu_add_variable(pdu, ourname, ourlength, request->requestvb->type, request->requestvb->val.string, request->requestvb->val_len); request->delegated = 1; request = request->next; } /* * Customize session parameters based on request information */ if (!proxy_fill_in_session(handler, reqinfo, (void **)&configured)) { netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR); return SNMP_ERR_NOERROR; } /* * send the request out */ DEBUGMSGTL(("proxy", "sending pdu\n")); snmp_async_send(sp->sess, pdu, proxy_got_response, netsnmp_create_delegated_cache(handler, reginfo, reqinfo, requests, (void *) sp)); /* Free any special parameters generated on the session */ proxy_free_filled_in_session_args(sp->sess, (void **)&configured); return SNMP_ERR_NOERROR; }
int handle_agentx_packet(int operation, netsnmp_session * session, int reqid, netsnmp_pdu *pdu, void *magic) { struct agent_netsnmp_set_info *asi = NULL; snmp_callback mycallback; netsnmp_pdu *internal_pdu = NULL; void *retmagic = NULL; ns_subagent_magic *smagic = NULL; if (operation == NETSNMP_CALLBACK_OP_DISCONNECT) { struct synch_state *state = (struct synch_state *) magic; int period = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL); DEBUGMSGTL(("agentx/subagent", "transport disconnect indication\n")); /* * deal with existing session. This happend if agentx sends * a message to the master, but the master goes away before * a response is sent. agentx will spin in snmp_synch_response_cb, * waiting for a response. At the very least, the waiting * flag must be set to break that loop. The rest is copied * from disconnect handling in snmp_sync_input. */ if(state) { state->waiting = 0; state->pdu = NULL; state->status = STAT_ERROR; session->s_snmp_errno = SNMPERR_ABORT; SET_SNMP_ERROR(SNMPERR_ABORT); } /* * Deregister the ping alarm, if any, and invalidate all other * references to this session. */ if (session->securityModel != SNMP_DEFAULT_SECMODEL) { snmp_alarm_unregister(session->securityModel); } snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_INDEX_STOP, (void *) session); agentx_unregister_callbacks(session); remove_trap_session(session); register_mib_detach(); main_session = NULL; if (period != 0) { /* * Pings are enabled, so periodically attempt to re-establish contact * with the master agent. Don't worry about the handle, * agentx_reopen_session unregisters itself if it succeeds in talking * to the master agent. */ snmp_alarm_register(period, SA_REPEAT, agentx_reopen_session, NULL); } return 0; } else if (operation != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) { DEBUGMSGTL(("agentx/subagent", "unexpected callback op %d\n", operation)); return 1; } /* * ok, we have a pdu from the net. Modify as needed */ DEBUGMSGTL(("agentx/subagent", "handling agentx request (req=0x%x,trans=" "0x%x,sess=0x%x)\n", pdu->reqid,pdu->transid, pdu->sessid)); pdu->version = AGENTX_VERSION_1; pdu->flags |= UCD_MSG_FLAG_ALWAYS_IN_VIEW; if (pdu->command == AGENTX_MSG_GET || pdu->command == AGENTX_MSG_GETNEXT || pdu->command == AGENTX_MSG_GETBULK) { smagic = (ns_subagent_magic *) calloc(1, sizeof(ns_subagent_magic)); if (smagic == NULL) { DEBUGMSGTL(("agentx/subagent", "couldn't malloc() smagic\n")); return 1; } smagic->original_command = pdu->command; smagic->session = session; smagic->ovars = NULL; retmagic = (void *) smagic; } switch (pdu->command) { case AGENTX_MSG_GET: DEBUGMSGTL(("agentx/subagent", " -> get\n")); pdu->command = SNMP_MSG_GET; mycallback = handle_subagent_response; break; case AGENTX_MSG_GETNEXT: DEBUGMSGTL(("agentx/subagent", " -> getnext\n")); pdu->command = SNMP_MSG_GETNEXT; /* * We have to save a copy of the original variable list here because * if the master agent has requested scoping for some of the varbinds * that information is stored there. */ smagic->ovars = snmp_clone_varbind(pdu->variables); DEBUGMSGTL(("agentx/subagent", "saved variables\n")); mycallback = handle_subagent_response; break; case AGENTX_MSG_GETBULK: /* * WWWXXX */ DEBUGMSGTL(("agentx/subagent", " -> getbulk\n")); pdu->command = SNMP_MSG_GETBULK; /* * We have to save a copy of the original variable list here because * if the master agent has requested scoping for some of the varbinds * that information is stored there. */ smagic->ovars = snmp_clone_varbind(pdu->variables); DEBUGMSGTL(("agentx/subagent", "saved variables at %p\n", smagic->ovars)); mycallback = handle_subagent_response; break; case AGENTX_MSG_RESPONSE: SNMP_FREE(smagic); DEBUGMSGTL(("agentx/subagent", " -> response\n")); return 1; case AGENTX_MSG_TESTSET: /* * XXXWWW we have to map this twice to both RESERVE1 and RESERVE2 */ DEBUGMSGTL(("agentx/subagent", " -> testset\n")); asi = save_set_vars(session, pdu); if (asi == NULL) { SNMP_FREE(smagic); snmp_log(LOG_WARNING, "save_set_vars() failed\n"); return 1; } asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_RESERVE1; mycallback = handle_subagent_set_response; retmagic = asi; break; case AGENTX_MSG_COMMITSET: DEBUGMSGTL(("agentx/subagent", " -> commitset\n")); asi = restore_set_vars(session, pdu); if (asi == NULL) { SNMP_FREE(smagic); snmp_log(LOG_WARNING, "restore_set_vars() failed\n"); return 1; } if (asi->mode != SNMP_MSG_INTERNAL_SET_RESERVE2) { SNMP_FREE(smagic); snmp_log(LOG_WARNING, "dropping bad AgentX request (wrong mode %d)\n", asi->mode); return 1; } asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_ACTION; mycallback = handle_subagent_set_response; retmagic = asi; break; case AGENTX_MSG_CLEANUPSET: DEBUGMSGTL(("agentx/subagent", " -> cleanupset\n")); asi = restore_set_vars(session, pdu); if (asi == NULL) { SNMP_FREE(smagic); snmp_log(LOG_WARNING, "restore_set_vars() failed\n"); return 1; } if (asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE1 || asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE2) { asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_FREE; } else if (asi->mode == SNMP_MSG_INTERNAL_SET_ACTION) { asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_COMMIT; } else { snmp_log(LOG_WARNING, "dropping bad AgentX request (wrong mode %d)\n", asi->mode); SNMP_FREE(retmagic); return 1; } mycallback = handle_subagent_set_response; retmagic = asi; break; case AGENTX_MSG_UNDOSET: DEBUGMSGTL(("agentx/subagent", " -> undoset\n")); asi = restore_set_vars(session, pdu); if (asi == NULL) { SNMP_FREE(smagic); snmp_log(LOG_WARNING, "restore_set_vars() failed\n"); return 1; } asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_UNDO; mycallback = handle_subagent_set_response; retmagic = asi; break; default: SNMP_FREE(smagic); DEBUGMSGTL(("agentx/subagent", " -> unknown command %d (%02x)\n", pdu->command, pdu->command)); return 0; } /* * submit the pdu to the internal handler */ /* * We have to clone the PDU here, because when we return from this * callback, sess_process_packet will free(pdu), but this call also * free()s its argument PDU. */ internal_pdu = snmp_clone_pdu(pdu); internal_pdu->contextName = internal_pdu->community; internal_pdu->contextNameLen = internal_pdu->community_len; internal_pdu->community = NULL; internal_pdu->community_len = 0; snmp_async_send(agentx_callback_sess, internal_pdu, mycallback, retmagic); return 1; }
int proxy_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_pdu *pdu; struct simple_proxy *sp; oid *ourname; size_t ourlength; netsnmp_request_info *request = requests; DEBUGMSGTL(("proxy", "proxy handler starting, mode = %d\n", reqinfo->mode)); switch (reqinfo->mode) { case MODE_GET: case MODE_GETNEXT: case MODE_GETBULK: /* WWWXXX */ pdu = snmp_pdu_create(reqinfo->mode); break; case MODE_SET_COMMIT: pdu = snmp_pdu_create(SNMP_MSG_SET); break; default: snmp_log(LOG_WARNING, "unsupported mode for proxy called\n"); return SNMP_ERR_NOERROR; } sp = (struct simple_proxy *) handler->myvoid; if (!pdu || !sp) { netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR); return SNMP_ERR_NOERROR; } while (request) { ourname = request->requestvb->name; ourlength = request->requestvb->name_length; if (sp->base_len > 0) { if ((ourlength - sp->name_len + sp->base_len) > MAX_OID_LEN) { /* * too large */ snmp_log(LOG_ERR, "proxy oid request length is too long\n"); return SNMP_ERR_NOERROR; } /* * suffix appended? */ DEBUGMSGTL(("proxy", "length=%d, base_len=%d, name_len=%d\n", ourlength, sp->base_len, sp->name_len)); if (ourlength > (int) sp->name_len) memcpy(&(sp->base[sp->base_len]), &(ourname[sp->name_len]), sizeof(oid) * (ourlength - sp->name_len)); ourlength = ourlength - sp->name_len + sp->base_len; ourname = sp->base; } snmp_pdu_add_variable(pdu, ourname, ourlength, request->requestvb->type, request->requestvb->val.string, request->requestvb->val_len); request->delegated = 1; request = request->next; } /* * send the request out */ DEBUGMSGTL(("proxy", "sending pdu\n")); snmp_async_send(sp->sess, pdu, proxy_got_response, netsnmp_create_delegated_cache(handler, reginfo, reqinfo, requests, (void *) sp)); return SNMP_ERR_NOERROR; }
if ( template_pdu->command == SNMP_MSG_INFORM #ifdef USING_AGENTX_PROTOCOL_MODULE || template_pdu->command == AGENTX_MSG_NOTIFY #endif ) { result = snmp_async_send(sess, pdu, &handle_inform_response, NULL); } else { if ((sess->version == SNMP_VERSION_3) && (pdu->command == SNMP_MSG_TRAP2) && (sess->securityEngineIDLen == 0)) { u_char tmp[SPRINT_MAX_LEN]; int len = snmpv3_get_engineID(tmp, sizeof(tmp)); memdup(&pdu->securityEngineID, tmp, len); pdu->securityEngineIDLen = len; } result = snmp_send(sess, pdu); }