static int snmptool_get(struct snmp_toolinfo *snmptoolctx) { struct snmp_pdu req, resp; snmp_pdu_create(&req, GET_PDUTYPE(snmptoolctx)); while ((snmp_pdu_add_bindings(snmptoolctx, snmpget_verify_vbind, snmptool_add_vbind, &req, SNMP_MAX_BINDINGS)) > 0) { if (GET_PDUTYPE(snmptoolctx) == SNMP_PDU_GETBULK) snmpget_fix_getbulk(&req, GET_MAXREP(snmptoolctx), GET_NONREP(snmptoolctx)); if (snmp_dialog(&req, &resp) == -1) { warnx("Snmp dialog - %s", strerror(errno)); break; } if (snmp_parse_resp(&resp, &req) >= 0) { snmp_output_resp(snmptoolctx, &resp, NULL); break; } snmp_output_err_resp(snmptoolctx, &resp); if (GET_PDUTYPE(snmptoolctx) == SNMP_PDU_GETBULK || !ISSET_RETRY(snmptoolctx)) break; /* * Loop through the object list and set object->error to the * varbinding that caused the error. */ if (snmp_object_seterror(snmptoolctx, &(resp.bindings[resp.error_index - 1]), resp.error_status) <= 0) break; fprintf(stderr, "Retrying...\n"); snmp_pdu_free(&resp); snmp_pdu_create(&req, GET_PDUTYPE(snmptoolctx)); } snmp_pdu_free(&resp); return (0); }
void dump_pdu(snmp_pdu_t* pdu, enum snmp_version version, u_int type) { char hextable[] = "0123456789abcdef"; char buf[10000]; int i; asn_buf_t buffer; pdu->version = version; pdu->pdu_type = type; pdu->request_id = 234; append_bindings(pdu, oid1, sizeof(oid1)/sizeof(asn_subid_t), SNMP_SYNTAX_NULL); append_bindings(pdu, oid1, sizeof(oid1)/sizeof(asn_subid_t), SNMP_SYNTAX_INTEGER); pdu->bindings[pdu->nbindings-1].v.integer = 12; append_bindings(pdu, oid1, sizeof(oid1)/sizeof(asn_subid_t), SNMP_SYNTAX_OCTETSTRING); pdu->bindings[pdu->nbindings-1].v.octetstring.octets = strdup("1234567890"); pdu->bindings[pdu->nbindings-1].v.octetstring.len = strlen("1234567890"); append_bindings(pdu, oid1, sizeof(oid1)/sizeof(asn_subid_t), SNMP_SYNTAX_OID); memcpy(pdu->bindings[pdu->nbindings-1].v.oid.subs, oid2, sizeof(oid2)); pdu->bindings[pdu->nbindings-1].v.oid.len = sizeof(oid2)/sizeof(asn_subid_t); append_bindings(pdu, oid1, sizeof(oid1)/sizeof(asn_subid_t), SNMP_SYNTAX_IPADDRESS); memcpy(pdu->bindings[pdu->nbindings-1].v.ipaddress, "\1\2\3\4", 4); append_bindings(pdu, oid1, sizeof(oid1)/sizeof(asn_subid_t), SNMP_SYNTAX_COUNTER); pdu->bindings[pdu->nbindings-1].v.uint32 = 2235683; append_bindings(pdu, oid1, sizeof(oid1)/sizeof(asn_subid_t), SNMP_SYNTAX_GAUGE); pdu->bindings[pdu->nbindings-1].v.uint32 = 1235683; append_bindings(pdu, oid1, sizeof(oid1)/sizeof(asn_subid_t), SNMP_SYNTAX_TIMETICKS); pdu->bindings[pdu->nbindings-1].v.uint32 = 1235683; append_bindings(pdu, oid1, sizeof(oid1)/sizeof(asn_subid_t), SNMP_SYNTAX_COUNTER64); pdu->bindings[pdu->nbindings-1].v.counter64 = 12352121212122683; snmp_printf("\r\n------------------\r\n"); snmp_pdu_dump(pdu); snmp_printf("\r\n------------------\r\n"); buffer.asn_len = sizeof(buf); buffer.asn_ptr = (u_char*) buf; snmp_pdu_encode(pdu, &buffer); for(i = 0;i < (buffer.asn_ptr - (u_char*)buf); ++i) { char v1 = (buf[i]>>4)&0x0f; char v2 = buf[i]&0x0f; snmp_printf("%c", hextable[v1]); snmp_printf("%c", hextable[v2]); } snmp_printf("\r\n\r\n"); snmp_pdu_free(pdu); }
/* static */ SNMP_pdu *request_create(char *community, int type, char *error_label) { SNMP_pdu *request; error_label[0] = '\0'; switch(type) { case GET_REQ_MSG: case GETNEXT_REQ_MSG: case SET_REQ_MSG: break; default: sprintf(error_label, "BUG: request_create(): bad type (0x%x)", type); return NULL; } request = snmp_pdu_new(error_label); if(request == NULL) { return NULL; } request->version = SNMP_VERSION_1; request->community = strdup(community); if(request->community == NULL) { sprintf(error_label, ERR_MSG_ALLOC); snmp_pdu_free(request); return NULL; } request->type = type; request->request_id = request_id++; return request; }
void dump_snmpv3_user(snmp_pdu_t* pdu, u_int type, snmp_user_t* user) { snmp_pdu_init(pdu); strcpy(pdu->context_name, "testcontextname"); strcpy((char*)pdu->context_engine, "testcontextengine"); pdu->context_engine_len = strlen("testcontextengine"); memcpy(pdu->engine.engine_id, "01234567890123456789012345678901234567890123456789", SNMP_ENGINE_ID_SIZ); pdu->engine.engine_len = SNMP_ENGINE_ID_SIZ; pdu->engine.engine_boots = 3; pdu->engine.engine_time = 1234; pdu->engine.max_msg_size = 10007; pdu->security_model = SNMP_SECMODEL_USM; snmp_auth_to_localization_keys(user, pdu->engine.engine_id, pdu->engine.engine_len); snmp_priv_to_localization_keys(user, pdu->engine.engine_id, pdu->engine.engine_len); memcpy(&pdu->user, user, sizeof(*user)); snmp_pdu_init_secparams(pdu); dump_pdu(pdu, SNMP_V3, type); snmp_pdu_free(pdu); }
void dump_snmpv1orv2(snmp_pdu_t* pdu, enum snmp_version version, u_int type) { snmp_pdu_init(pdu); strcpy(pdu->community, "123987"); dump_pdu(pdu, version, type); snmp_pdu_free(pdu); }
int request_snmpEnableAuthTraps(char *error_label) { static int my_ip_address_initialized = False; static IPAddress my_ip_address; SNMP_pdu *request; SNMP_pdu *response; SNMP_variable *variable; int snmpEnableAuthTraps; struct timeval timeout; timeout.tv_sec = 5; timeout.tv_usec = 0; error_label[0] = '\0'; if(my_ip_address_initialized == False) { if(get_my_ip_address(&my_ip_address, error_label)) { return -1; } my_ip_address_initialized = True; } request = request_create("public", GET_REQ_MSG, error_label); if(request == NULL) { return -1; } if(snmp_pdu_append_null_variable(request, &snmpEnableAuthTraps_name, error_label) == NULL) { snmp_pdu_free(request); return -1; } response = request_send_to_port_time_out_blocking(&my_ip_address, \ SNMP_PORT, &timeout, request, error_label); if(response == NULL) { snmp_pdu_free(request); return -1; } snmp_pdu_free(request); if(response->error_status) { sprintf(error_label, "%s", error_status_string(response->error_status)); snmp_pdu_free(response); return -1; } variable = response->first_variable; if(variable->next_variable || SSAOidCmp(&(variable->name), &snmpEnableAuthTraps_name) || (variable->type != INTEGER) || (variable->val.integer == NULL) || (variable->val_len != sizeof(int32_t)) ) { sprintf(error_label, ERR_MSG_BAD_RESPONSE); snmp_pdu_free(response); return -1; } snmpEnableAuthTraps = *(variable->val.integer); snmp_pdu_free(response); if(trace_level > 0) { trace("snmpAuthTraps: %s\n\n", (snmpEnableAuthTraps == 1)? "enabled(1)": "disabled(2)"); } switch(snmpEnableAuthTraps) { case 1: /* enabled(1) */ return TRUE; case 2: /* disable(2) */ return FALSE; default: sprintf(error_label, ERR_MSG_BAD_VALUE); return -1; } }
int32_t request_sysUpTime(char *error_label, char *community_name) { static int my_ip_address_initialized = False; static IPAddress my_ip_address; SNMP_pdu *request; SNMP_pdu *response; SNMP_variable *variable; static int32_t sysUpTime = 0; static clock_t last = 0; clock_t now; struct tms buffer; error_label[0] = '\0'; now = times(&buffer); if( (last == 0) || ((now - last) > 360000) ) /* 1 hour */ { if(my_ip_address_initialized == False) { if(get_my_ip_address(&my_ip_address, error_label)) { return 0; } my_ip_address_initialized = True; } if(community_name == NULL) request = request_create("public", GET_REQ_MSG, error_label); else request = request_create(community_name, GET_REQ_MSG, error_label); if(request == NULL) { return 0; } if(snmp_pdu_append_null_variable(request, &sysUptime_instance, error_label) == NULL) { snmp_pdu_free(request); return 0; } response = request_send_blocking(&my_ip_address, request, error_label); if(response == NULL) { snmp_pdu_free(request); return 0; } snmp_pdu_free(request); if(response->error_status) { sprintf(error_label, "%s", error_status_string(response->error_status)); snmp_pdu_free(response); return 0; } variable = response->first_variable; if(variable->next_variable || SSAOidCmp(&(variable->name), &sysUptime_instance) || (variable->type != TIMETICKS) || (variable->val.integer == NULL) || (variable->val_len != sizeof(int32_t)) ) { sprintf(error_label, ERR_MSG_BAD_RESPONSE); snmp_pdu_free(response); return 0; } sysUpTime = *(variable->val.integer); last = now; snmp_pdu_free(response); if(trace_level > 0) { trace("sysUpTime: %d\n\n", sysUpTime); } return sysUpTime; } /* LINTED */ return (sysUpTime + (int32_t)(now - last)); }
/* * Fetch a table. Returns 0 if ok, -1 on errors. * This is the synchronous variant. */ int snmp_table_fetch(const struct snmp_table *descr, void *list) { struct snmp_pdu resp; struct tabwork work; int ret; work.descr = descr; work.table = (struct table *)list; work.iter = 0; TAILQ_INIT(work.table); TAILQ_INIT(&work.worklist); work.callback = NULL; work.arg = NULL; again: /* * We come to this label when the code detects that the table * has changed while fetching it. */ work.first = 1; work.last_change = 0; table_init_pdu(descr, &work.pdu); for (;;) { if (snmp_dialog(&work.pdu, &resp)) { table_free(&work, 1); return (-1); } if ((ret = table_check_response(&work, &resp)) == 0) { snmp_pdu_free(&resp); break; } if (ret == -1) { snmp_pdu_free(&resp); table_free(&work, 1); return (-1); } if (ret == -2) { snmp_pdu_free(&resp); goto again; } work.pdu.bindings[work.pdu.nbindings - 1].var = resp.bindings[resp.nbindings - 1].var; snmp_pdu_free(&resp); } if ((ret = table_check_cons(&work)) == -1) { table_free(&work, 1); return (-1); } if (ret == -2) { table_free(&work, 1); goto again; } /* * Free index list */ table_free(&work, 0); return (0); }
/* * Do a 'snmp walk' - according to command line options request for values lexicographically * subsequent and subrooted at a common node. Send a GetNext PDU requesting the value for each * next variable and print the responce. Stop when a Responce PDU is received that contains * the value of a variable not subrooted at the variable the walk started. */ int main(int argc, char ** argv) { struct snmp_toolinfo *tool; struct snmp_client *client_context; struct asn_oid root; /* keep the inital oid */ struct snmp_pdu pdu_to_send, pdu_to_recv; int oid, opt_num, outputs; tool = snmptool_init(helptxt); client_context = tool->client; if ((opt_num = snmpwalk_parse_options(tool, argc, argv)) < 0) { snmp_tool_freeall(tool); exit(0); } if (snmp_import_all(tool) < 0) { snmp_tool_freeall(tool); exit(0); } oid = argc - opt_num - 1; switch (oid) { case 0: if (snmp_object_add(tool, snmpwalk_add_default, NULL) < 0) { snmp_tool_freeall(tool); errx(1, "Error setting default tree OID to walk"); } break; case 1: /* last command line argument will always be the OID to start the walk from */ if ((snmp_object_add(tool, snmpwalk_parse_oid, argv[argc - 1])) < 0) { snmp_tool_freeall(tool); exit(1); } break; default: snmp_tool_freeall(tool); errx(1, "Only one OID allowed"); } snmp_pdu_create(client_context, &pdu_to_send, SNMP_PDU_GETNEXT); if (snmp_pdu_add_bindings(tool, (snmp_verify_vbind_f) NULL, snmpwalk_add_vbind, &pdu_to_send) < 0) { snmp_tool_freeall(tool); exit(1); } if (snmp_open(client_context, NULL, NULL, NULL, NULL)) { snmp_tool_freeall(tool); err(1, "Failed to open snmp session"); } /* remember the root where the walk started from */ memset(&root, 0 ,sizeof(struct asn_oid)); asn_append_oid(&root, &(pdu_to_send.bindings[0].var)); outputs = 0; while (snmp_dialog(client_context, &pdu_to_send, &pdu_to_recv) >= 0) { if ((snmp_parse_resp(client_context, &pdu_to_recv, &pdu_to_send)) < 0) { snmp_output_err_resp(tool, &pdu_to_recv); snmp_pdu_free(&pdu_to_recv); outputs = -1; break; } if (!(asn_is_suboid(&root, &(pdu_to_recv.bindings[0].var)))) { snmp_pdu_free(&pdu_to_recv); break; } snmp_output_resp(tool, &pdu_to_recv); outputs++; snmp_pdu_free(&pdu_to_recv); snmpwalk_nextpdu_create(client_context, SNMP_PDU_GETNEXT, &(pdu_to_recv.bindings[0].var), &pdu_to_send); } /* Just a case our root was a leaf */ if (outputs == 0) { snmpwalk_nextpdu_create(client_context, SNMP_PDU_GET, &root, &pdu_to_send); if (snmp_dialog(client_context, &pdu_to_send, &pdu_to_recv) == SNMP_CODE_OK /* 0 */) { if(snmp_parse_resp(client_context, &pdu_to_recv,&pdu_to_send) < 0) snmp_output_err_resp(tool, &pdu_to_recv); else snmp_output_resp(tool, &(pdu_to_recv)); snmp_pdu_free(&pdu_to_recv); } else err(1, "Snmp dialog"); } snmp_tool_freeall(tool); exit(0); }
struct snmp_pdu *snmp_fix_pdu(struct snmp_pdu *pdu, int command) { struct variable_list *var, *newvar; struct snmp_pdu *newpdu; int index; int copied = 0; #ifdef DEBUG_PDU printf("PDU %x: Fixing. Err index is %d\n", (unsigned int)pdu, (unsigned int)pdu->errindex); #endif if (pdu->command != SNMP_PDU_RESPONSE || pdu->errstat == SNMP_ERR_NOERROR || pdu->errindex <= 0) { snmp_set_api_error(SNMPERR_UNABLE_TO_FIX); return(NULL); } /* clone the pdu */ newpdu = snmp_pdu_clone(pdu); if (newpdu == NULL) return(NULL); newpdu->variables = 0; newpdu->command = command; newpdu->reqid = SNMP_DEFAULT_REQID; newpdu->errstat = SNMP_ERR_NOERROR; newpdu->errindex = 0; /* XXXXX Is this right? */ /* Loop through the variables, removing whatever isn't necessary */ var = pdu->variables; index = 1; /* skip first variable if necessary*/ if (pdu->errindex == index) { var = var->next_variable; index++; } if (var != NULL) { /* VAR is the first uncopied variable */ /* Clone this variable */ newpdu->variables = snmp_var_clone(var); if (newpdu->variables == NULL) { snmp_pdu_free(newpdu); return(NULL); } copied++; newvar = newpdu->variables; /* VAR has been copied to NEWVAR. */ while(var->next_variable) { /* Skip the item that was bad */ if (++index == pdu->errindex) { var = var->next_variable; continue; } /* Copy this var */ newvar->next_variable = snmp_var_clone(var->next_variable); if (newvar->next_variable == NULL) { snmp_pdu_free(newpdu); return(NULL); } /* Move to the next one */ newvar = newvar->next_variable; var = var->next_variable; copied++; } newvar->next_variable = NULL; } /* If we didn't copy anything, free the new pdu. */ if (index < pdu->errindex || copied == 0) { snmp_free_pdu(newpdu); snmp_set_api_error(SNMPERR_UNABLE_TO_FIX); return(NULL); } #ifdef DEBUG_PDU printf("PDU %x: Fixed PDU is %x\n", (unsigned int)pdu, (unsigned int)newpdu); #endif return(newpdu); }