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) { warn("Snmp dialog"); 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); }
/* * 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); }