I have written and am testing software for a generic SNMP client module in C as well as an implementation using this generic module. I am having trouble getting a get request to work by passing in a MIB name(e.g. sysDescr) instead of an OID(e.g. 1.3.6.1.2.1.1.1).
I am successful when I pass in a character array containing the OID to _snmp_parse_oid()_ but not the name.
I have checked the MIB file to make sure I am using the correct name. When I run the command line SNMP translate on the name it gives me the OID listed above:
$ snmptranslate -m +<MIB File> -IR -On <MIB Name> .#.#.#.#.#.#.#####.#.#.#.#.#.#
(In the above command I replaced my actual mib file with <MIB File>
, mib name with <MIB Name>
, and OID numbers returned from the command with #
characters)
The following is my code for my generic SNMP get function, assume returned values are #define numbers and I have removed some error handling for brevity:
/// @Synopsis Function to send out get request since the /// SNMPOidData object has been setup /// /// @Param oid_name String containing the OID to set /// @Param value Value to set /// /// @Returns Error int snmpGet(SNMPAgent *this, char const * const oid_name, SNMPOidData * value) { netsnmp_pdu *pdu; netsnmp_pdu *response; netsnmp_variable_list *vars; oid *retrieved_oid; oidStruct oid_to_get; int status = 0; int result = ERROR_SUCCESS; // Create the PDU for the data for our request pdu = snmp_pdu_create(SNMP_MSG_GET); oid_to_get.OidLen = MAX_OID_LEN; // Set max length // Send out the request(s) retrieved_oid = snmp_parse_oid(oid_name, oid_to_get.Oid, &oid_to_get.OidLen); // Set the data snmp_add_null_var(pdu, oid_to_get.Oid, oid_to_get.OidLen)) // Send the request out status = snmp_synch_response(this->port.snmp_session_handle, pdu, &response); if (STAT_SUCCESS == status) { if (SNMP_ERR_NOERROR == response->errstat) { vars = response->variables; value->type = vars->type; if (vars->next_variable != NULL) { // There are more values, set return type to null value->type = ASN_NULL; } else if (!(CHECK_END(vars->type))) // Exception { result = ERROR_NOT_PRESENT; fprintf(stderr, "Warning: OID=%s gets snmp exception %d n", oid_name, vars->type); } else if ((vars->type == ASN_INTEGER) || (vars->type == ASN_COUNTER) || (vars->type == ASN_UNSIGNED)) { value->integer = *(vars->val.integer); value->str_len = sizeof(value->integer); } else { value->str_len = vars->val_len; if (value->str_len >= MAX_ASN_STR_LEN) value->str_len = MAX_ASN_STR_LEN; if (value->str_len > 0) memcpy(value->string, vars->val.string, value->str_len); // guarantee NULL terminated string value->string[value->str_len] = ''; } } } this->freePDU(response); // Clean up: free the response return result; }
The error I am getting:
oid_name: Unknown Object Identifier (Sub-id not found: (top) -> <MIB Name>)
Which comes from the following call:
retrieved_oid = snmp_parse_oid(oid_name, oid_to_get.Oid, &oid_to_get.OidLen);
I have made sure that the MIB files are on the machine in the configured place (snmptranslate wouldn’t work if this weren’t the case).
I have spent a good amount of time on Google results as well as directly searching here on Stack Overflow. The following is a good tutorial but does not address my issue (they directly reference the OID they want to get the value of): http://www.net-snmp.org/wiki/index.php/TUT:Simple_Application
Any help or insight would be much appreciated.
Some other info I can think of is that this is being compiled to run on an armv5tejl target running Linux communicating with an external device via ethernet.
Thanks,
Advertisement
Answer
When I call MIB variables by their string name I use the following net-snmp functions.
read_objid(OID, anOID, &anOID_len); snmp_add_null_var(pdu, anOID, anOID_len);
Where:
oid anOID[MAX_OID_LEN]; size_t anOID_len = MAX_OID_LEN;
In my program I pack this all into a single function call.
void packSingleGetOID(const char *OID, struct snmp_pdu *pdu){ // OID in / PDU out oid anOID[MAX_OID_LEN]; size_t anOID_len = MAX_OID_LEN; read_objid(OID, anOID, &anOID_len); snmp_add_null_var(pdu, anOID, anOID_len); }
I pass in the MIB OID string and the pointer to session pdu. Remember the OID string is MIB_Name::variable
.