📄 proxy.c
字号:
*configured = NULL;}voidinit_proxy(void){ snmpd_register_config_handler("proxy", proxy_parse_config, proxy_free_config, "[snmpcmd args] host oid [remoteoid]");}voidshutdown_proxy(void){ proxy_free_config();}intproxy_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;}intproxy_got_response(int operation, netsnmp_session * sess, int reqid, netsnmp_pdu *pdu, void *cb_data){ netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) cb_data; netsnmp_request_info *requests, *request = NULL; netsnmp_variable_list *vars, *var = NULL; struct simple_proxy *sp; oid myname[MAX_OID_LEN]; size_t myname_len = MAX_OID_LEN; cache = netsnmp_handler_check_cache(cache); if (!cache) { DEBUGMSGTL(("proxy", "a proxy request was no longer valid.\n")); return SNMP_ERR_NOERROR; } requests = cache->requests; sp = (struct simple_proxy *) cache->localinfo; if (!sp) { DEBUGMSGTL(("proxy", "a proxy request was no longer valid.\n")); return SNMP_ERR_NOERROR; } switch (operation) { case NETSNMP_CALLBACK_OP_TIMED_OUT: /* * WWWXXX: don't leave requests delayed if operation is * something like TIMEOUT */ DEBUGMSGTL(("proxy", "got timed out... requests = %08p\n", requests)); netsnmp_handler_mark_requests_as_delegated(requests, REQUEST_IS_NOT_DELEGATED); netsnmp_set_request_error(cache->reqinfo, requests, /* XXXWWW: should be index = 0 */ SNMP_ERR_GENERR); netsnmp_free_delegated_cache(cache); return 0; case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE: vars = pdu->variables; if (pdu->errstat != SNMP_ERR_NOERROR) { /* * If we receive an error from the proxy agent, pass it on up. * The higher-level processing seems to Do The Right Thing. */ DEBUGMSGTL(("proxy", "got error response (%d)\n", pdu->errstat)); netsnmp_set_request_error(cache->reqinfo, requests, pdu->errstat); /* * update the original request varbinds with the results */ } else for (var = vars, request = requests; request && var; request = request->next, var = var->next_variable) { /* * XXX - should this be done here? * Or wait until we know it's OK? */ snmp_set_var_typed_value(request->requestvb, var->type, var->val.string, var->val_len); DEBUGMSGTL(("proxy", "got response... ")); DEBUGMSGOID(("proxy", var->name, var->name_length)); DEBUGMSG(("proxy", "\n")); request->delegated = 0; /* * Check the response oid is legitimate, * and discard the value if not. * * XXX - what's the difference between these cases? */ if (sp->base_len && (var->name_length < sp->base_len || snmp_oid_compare(var->name, sp->base_len, sp->base, sp->base_len) != 0)) { DEBUGMSGTL(( "proxy", "out of registered range... ")); DEBUGMSGOID(("proxy", var->name, sp->base_len)); DEBUGMSG(( "proxy", " (%d) != ", sp->base_len)); DEBUGMSGOID(("proxy", sp->base, sp->base_len)); DEBUGMSG(( "proxy", "\n")); snmp_set_var_typed_value(request->requestvb, ASN_NULL, NULL, 0); continue; } else if (!sp->base_len && (var->name_length < sp->name_len || snmp_oid_compare(var->name, sp->name_len, sp->name, sp->name_len) != 0)) { DEBUGMSGTL(( "proxy", "out of registered base range... ")); DEBUGMSGOID(("proxy", var->name, sp->name_len)); DEBUGMSG(( "proxy", " (%d) != ", sp->name_len)); DEBUGMSGOID(("proxy", sp->name, sp->name_len)); DEBUGMSG(( "proxy", "\n")); snmp_set_var_typed_value(request->requestvb, ASN_NULL, NULL, 0); continue; } else { /* * If the returned OID is legitimate, then update * the original request varbind accordingly. */ if (sp->base_len) { /* * XXX: oid size maxed? */ memcpy(myname, sp->name, sizeof(oid) * sp->name_len); myname_len = sp->name_len + var->name_length - sp->base_len; if (myname_len > MAX_OID_LEN) { snmp_log(LOG_WARNING, "proxy OID return length too long.\n"); netsnmp_set_request_error(cache->reqinfo, requests, SNMP_ERR_GENERR); if (pdu) snmp_free_pdu(pdu); netsnmp_free_delegated_cache(cache); return 1; } if (var->name_length > sp->base_len) memcpy(&myname[sp->name_len], &var->name[sp->base_len], sizeof(oid) * (var->name_length - sp->base_len)); snmp_set_var_objid(request->requestvb, myname, myname_len); } else { snmp_set_var_objid(request->requestvb, var->name, var->name_length); } } } if (request || var) { /* * ack, this is bad. The # of varbinds don't match and * there is no way to fix the problem */ if (pdu) snmp_free_pdu(pdu); snmp_log(LOG_ERR, "response to proxy request illegal. We're screwed.\n"); netsnmp_set_request_error(cache->reqinfo, requests, SNMP_ERR_GENERR); } /* fix bulk_to_next operations */ if (cache->reqinfo->mode == MODE_GETBULK) netsnmp_bulk_to_next_fix_requests(requests); /* * free the response */ if (pdu && 0) snmp_free_pdu(pdu); break; default: DEBUGMSGTL(("proxy", "no response received: op = %d\n", operation)); break; } netsnmp_free_delegated_cache(cache); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -