int asmp_sess_login(netsnmp_session *session, const char *user, const char *passwd) { oid val = 0; int status; netsnmp_pdu *pdu; netsnmp_pdu *response; netsnmp_transport *transport; struct asmp_connection *asmp; transport = snmp_sess_transport(snmp_sess_pointer(session)); if (transport == NULL || transport->data == NULL) return -1; asmp = transport->data; pdu = snmp_pdu_create(ASMP_LOGIN_REQUEST); snmp_add_var(pdu, &val, 1, 's', user == NULL ? "" : user); snmp_add_var(pdu, &val, 1, 's', passwd == NULL ? "" : passwd); asmp->user = user == NULL ? "" : strdup(user); status = asmp_synch_response(session, pdu, &response); return status; }
static int _hook_build(netsnmp_session * sp, netsnmp_pdu *pdu, u_char * pkt, size_t * len) { int i, k; int rc = 0; size_t offset = 0; size_t sz_payload = 0; netsnmp_variable_list *vp; netsnmp_transport *transport; struct asmp_connection *asmp; transport = snmp_sess_transport(snmp_sess_pointer(sp)); if (transport == NULL || transport->data == NULL) return -1; asmp = transport->data; memset(pkt, 0, 0x100); pkt[offset++] = ASMP_SOH; switch (asmp->proto) { case ASMP_PROTO_AIDP: memcpy(pkt+offset, "AIDP", 4); break; case ASMP_PROTO_ASMP: case ASMP_PROTO_ASMPS: memcpy(pkt+offset, "ASMP", 4); break; default: return -1; } offset += 4; /* Fix Request ID by locally stored value */ pdu->msgid = pdu->reqid = ++asmp->seq; if (asmp->seq == 0xffff) asmp->seq = 0; if (pdu->version == SNMP_VERSION_3) { pkt[offset++] = (pdu->msgid >> 8) & 0xff; pkt[offset++] = pdu->msgid & 0xff; } else {
static int _invalid_op_and_magic (int op, ns_subagent_magic * smagic) { int invalid = 0; if (smagic && (snmp_sess_pointer (smagic->session) == NULL || op == NETSNMP_CALLBACK_OP_TIMED_OUT)) { if (smagic->ovars != NULL) { snmp_free_varbind (smagic->ovars); } free (smagic); invalid = 1; } if (op != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE || smagic == NULL) invalid = 1; return invalid; }
int notifyTable_register_notifications(int major, int minor, void *serverarg, void *clientarg) { struct targetAddrTable_struct *ptr; struct targetParamTable_struct *pptr; struct snmpNotifyTable_data *nptr; int confirm, i; char buf[SNMP_MAXBUF_SMALL]; netsnmp_transport *t = NULL; struct agent_add_trap_args *args = (struct agent_add_trap_args *) serverarg; netsnmp_session *ss; if (!args || !(args->ss)) { return (0); } confirm = args->confirm; ss = args->ss; /* * XXX: START move target creation to target code */ for (i = 0; i < MAX_ENTRIES; i++) { sprintf(buf, "internal%d", i); if (get_addrForName(buf) == NULL && get_paramEntry(buf) == NULL) break; } if (i == MAX_ENTRIES) { snmp_log(LOG_ERR, "Can't register new trap destination: max limit reached: %d", MAX_ENTRIES); snmp_sess_close(ss); return (0); } /* * address */ ptr = snmpTargetAddrTable_create(); ptr->name = strdup(buf); t = snmp_sess_transport(snmp_sess_pointer(ss)); memcpy(ptr->tDomain, t->domain, t->domain_length * sizeof(oid)); ptr->tDomainLen = t->domain_length; ptr->tAddressLen = t->remote_length; ptr->tAddress = t->remote; ptr->timeout = ss->timeout / 1000; ptr->retryCount = ss->retries; SNMP_FREE(ptr->tagList); ptr->tagList = strdup(ptr->name); ptr->params = strdup(ptr->name); ptr->storageType = ST_READONLY; ptr->rowStatus = RS_ACTIVE; ptr->sess = ss; DEBUGMSGTL(("trapsess", "adding to trap table\n")); snmpTargetAddrTable_add(ptr); /* * param */ pptr = snmpTargetParamTable_create(); pptr->paramName = strdup(buf); pptr->mpModel = ss->version; if (ss->version == SNMP_VERSION_3) { pptr->secModel = ss->securityModel; pptr->secLevel = ss->securityLevel; pptr->secName = (char *) malloc(ss->securityNameLen + 1); memcpy((void *) pptr->secName, (void *) ss->securityName, ss->securityNameLen); pptr->secName[ss->securityNameLen] = 0; } else { pptr->secModel = ss->version == SNMP_VERSION_1 ? SNMP_SEC_MODEL_SNMPv1 : SNMP_SEC_MODEL_SNMPv2c; pptr->secLevel = SNMP_SEC_LEVEL_NOAUTH; pptr->secName = NULL; if (ss->community && (ss->community_len > 0)) { pptr->secName = (char *) malloc(ss->community_len + 1); memcpy((void *) pptr->secName, (void *) ss->community, ss->community_len); pptr->secName[ss->community_len] = 0; } } pptr->storageType = ST_READONLY; pptr->rowStatus = RS_ACTIVE; snmpTargetParamTable_add(pptr); /* * XXX: END move target creation to target code */ /* * notify table */ nptr = SNMP_MALLOC_STRUCT(snmpNotifyTable_data); nptr->snmpNotifyName = strdup(buf); nptr->snmpNotifyNameLen = strlen(buf); nptr->snmpNotifyTag = strdup(buf); nptr->snmpNotifyTagLen = strlen(buf); nptr->snmpNotifyType = confirm ? SNMPNOTIFYTYPE_INFORM : SNMPNOTIFYTYPE_TRAP; nptr->snmpNotifyStorageType = ST_READONLY; nptr->snmpNotifyRowStatus = RS_ACTIVE; snmpNotifyTable_add(nptr); return 0; }
/* * Handle the response from an AgentX subagent, * merging the answers back into the original query */ int agentx_got_response(int operation, netsnmp_session * session, int reqid, netsnmp_pdu *pdu, void *magic) { netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) magic; int i, ret; netsnmp_request_info *requests, *request; netsnmp_variable_list *var; netsnmp_session *ax_session; cache = netsnmp_handler_check_cache(cache); if (!cache) { DEBUGMSGTL(("agentx/master", "response too late on session %8p\n", session)); return 0; } requests = cache->requests; switch (operation) { case NETSNMP_CALLBACK_OP_TIMED_OUT:{ void *s = snmp_sess_pointer(session); DEBUGMSGTL(("agentx/master", "timeout on session %8p\n", session)); 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); /* * This is a bit sledgehammer because the other sessions on this * transport may be okay (e.g. some thread in the subagent has * wedged, but the others are alright). OTOH the overwhelming * probability is that the whole agent has died somehow. */ if (s != NULL) { netsnmp_transport *t = snmp_sess_transport(s); close_agentx_session(session, -1); if (t != NULL) { DEBUGMSGTL(("agentx/master", "close transport\n")); t->f_close(t); } else { DEBUGMSGTL(("agentx/master", "NULL transport??\n")); } } else { DEBUGMSGTL(("agentx/master", "NULL sess_pointer??\n")); } ax_session = (netsnmp_session *) cache->localinfo; netsnmp_free_agent_snmp_session_by_session(ax_session, NULL); netsnmp_free_delegated_cache(cache); return 0; } case NETSNMP_CALLBACK_OP_DISCONNECT: case NETSNMP_CALLBACK_OP_SEND_FAILED: if (operation == NETSNMP_CALLBACK_OP_DISCONNECT) { DEBUGMSGTL(("agentx/master", "disconnect on session %8p\n", session)); } else { DEBUGMSGTL(("agentx/master", "send failed on session %8p\n", session)); } close_agentx_session(session, -1); 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: /* * This session is alive */ CLEAR_SNMP_STRIKE_FLAGS(session->flags); break; default: snmp_log(LOG_ERR, "Unknown operation %d in agentx_got_response\n", operation); netsnmp_free_delegated_cache(cache); return 0; } DEBUGMSGTL(("agentx/master", "got response errstat=%ld, (req=0x%x,trans=" "0x%x,sess=0x%x)\n", pdu->errstat, (unsigned)pdu->reqid, (unsigned)pdu->transid, (unsigned)pdu->sessid)); if (pdu->errstat != AGENTX_ERR_NOERROR) { /* [RFC 2471 - 7.2.5.2.] * * 1) For any received AgentX response PDU, if res.error is * not `noError', the SNMP response PDU's error code is * set to this value. If res.error contains an AgentX * specific value (e.g. `parseError'), the SNMP response * PDU's error code is set to a value of genErr instead. * Also, the SNMP response PDU's error index is set to * the index of the variable binding corresponding to the * failed VarBind in the subagent's AgentX response PDU. * * All other AgentX response PDUs received due to * processing this SNMP request are ignored. Processing * is complete; the SNMP Response PDU is ready to be sent * (see section 7.2.6, "Sending the SNMP Response-PDU"). */ int err; DEBUGMSGTL(("agentx/master", "agentx_got_response() error branch\n")); switch (pdu->errstat) { case AGENTX_ERR_PARSE_FAILED: case AGENTX_ERR_REQUEST_DENIED: case AGENTX_ERR_PROCESSING_ERROR: err = SNMP_ERR_GENERR; break; default: err = pdu->errstat; } ret = 0; for (request = requests, i = 1; request; request = request->next, i++) { if (i == pdu->errindex) { /* * Mark this varbind as the one generating the error. * Note that the AgentX errindex may not match the * position in the original SNMP PDU (request->index) */ netsnmp_set_request_error(cache->reqinfo, request, err); ret = 1; } request->delegated = REQUEST_IS_NOT_DELEGATED; } if (!ret) { /* * ack, unknown, mark the first one */ netsnmp_set_request_error(cache->reqinfo, requests, SNMP_ERR_GENERR); } netsnmp_free_delegated_cache(cache); DEBUGMSGTL(("agentx/master", "end error branch\n")); return 1; } else if (cache->reqinfo->mode == MODE_GET || cache->reqinfo->mode == MODE_GETNEXT || cache->reqinfo->mode == MODE_GETBULK) { /* * Replace varbinds for data request types, but not SETs. */ DEBUGMSGTL(("agentx/master", "agentx_got_response() beginning...\n")); for (var = pdu->variables, request = requests; request && var; request = request->next, var = var->next_variable) { /* * Otherwise, process successful requests */ DEBUGMSGTL(("agentx/master", " handle_agentx_response: processing: ")); DEBUGMSGOID(("agentx/master", var->name, var->name_length)); DEBUGMSG(("agentx/master", "\n")); if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_VERBOSE)) { DEBUGMSGTL(("snmp_agent", " >> ")); DEBUGMSGVAR(("snmp_agent", var)); DEBUGMSG(("snmp_agent", "\n")); } /* * update the oid in the original request */ if (var->type != SNMP_ENDOFMIBVIEW) { snmp_set_var_typed_value(request->requestvb, var->type, var->val.string, var->val_len); snmp_set_var_objid(request->requestvb, var->name, var->name_length); } request->delegated = REQUEST_IS_NOT_DELEGATED; } if (request || var) { /* * ack, this is bad. The # of varbinds don't match and * there is no way to fix the problem */ snmp_log(LOG_ERR, "response to agentx request illegal. bailing out.\n"); netsnmp_set_request_error(cache->reqinfo, requests, SNMP_ERR_GENERR); } if (cache->reqinfo->mode == MODE_GETBULK) netsnmp_bulk_to_next_fix_requests(requests); } else { /* * mark set requests as handled */ for (request = requests; request; request = request->next) { request->delegated = REQUEST_IS_NOT_DELEGATED; } } DEBUGMSGTL(("agentx/master", "handle_agentx_response() finishing...\n")); netsnmp_free_delegated_cache(cache); return 1; }
static int _hook_parse(netsnmp_session * sp, netsnmp_pdu * pdu, u_char * pkt, size_t len) { int i; int rc; u_char *p; oid val; int payload_len; netsnmp_transport *transport; struct asmp_connection *asmp; transport = snmp_sess_transport(snmp_sess_pointer(sp)); if (transport == NULL || transport->data == NULL) return -1; asmp = transport->data; pdu->msgid = pdu->reqid = (pkt[5] << 8) | pkt[6]; pdu->command = pkt[7]; if (pdu->command == 0x90 || pdu->command == 0x91) rc = 1; else rc = SNMP_ERR_NOERROR; p = pkt+12; payload_len = ntohl(*((uint32_t *)(pkt+8))); while (payload_len > 1) { uint16_t vlen; if (*p == ASMP_FIELD_TERM) break; val = *p; vlen = ntohs(*((uint16_t *)(p+1))); if (asmp->proto != ASMP_PROTO_AIDP) { switch (val) { case 1: if (pdu->command >= 0x90 && pdu->command <= 0x92) pdu->errstat = ntohs(*((uint16_t *)(p+3))); break; case 2: if (pdu->command >= 0x90 && pdu->command <= 0x92) pdu->errindex = ntohs(*((uint16_t *)(p+3))); break; case 3: if (pdu->command >= 0x90 && pdu->command <= 0x92) { int nlen; oid *name = NULL; netsnmp_variable_list *var = NULL; p += 3; if (*p != ASN_OBJECT_ID) { fprintf(stderr, "Wrong VarBind data\n"); return rc; } while (vlen > 0) { nlen = (*(p+1) << 8 | *(p+2)); switch (*p) { case ASN_OBJECT_ID: name = calloc(1, nlen); //fprintf(stderr, "OID: "); for (p += 3, i=0; i<nlen/sizeof(oid); i++, p += 4) { name[i] = *p << 24 | *(p+1) << 16 | *(p+2) << 8 | *(p+3); //fprintf(stderr, ".%d", name[i]); } //fprintf(stderr, "\n"); /* move pointer back */ p -= nlen+3; #if 0 if (pkt[16] == 6 && pkt[21] == 1) snmp_pdu_add_variable(pdu, name, nlen, SNMP_ENDOFMIBVIEW, NULL, 0); #endif if (var == NULL) { /* First OID is name OID */ var = snmp_add_null_var(pdu, name, nlen/sizeof(oid)); } else { /* Second OID is value OID */ var->type = *p; snmp_set_var_value(var, (u_char *)name, nlen); } free(name); break; case ASN_COUNTER: case ASN_TIMETICKS: case ASN_GAUGE: case ASN_INTEGER: { int32_t v; v = ntohl(*((int32_t *)(p+3))); var->type = *p; snmp_set_var_value(var, (u_char *)&v, nlen); } break; case ASN_OCTET_STR: var->type = *p; snmp_set_var_value(var, p+3, nlen); break; case ASN_IPADDRESS: var->type = *p; snmp_set_var_value(var, p+3, nlen); break; case ASN_NULL: var->type = *p; snmp_set_var_value(var, NULL, 0); break; default: fprintf(stderr, "AAA: %d\n", *p); break; } p += nlen+3; vlen -= nlen+3; payload_len -= nlen+3; } pdu->command = SNMP_MSG_RESPONSE; rc = SNMP_ERR_NOERROR; } break; default: break; } } else { fprintf(stderr, "Flen: %04x\n", vlen); snmp_pdu_add_variable(pdu, &val, 1, ASN_OCTET_STR, p+3, vlen); } p += vlen+3; payload_len -= vlen+3; } return rc; }