TRAP.C: /* TRAP NAME: TRAP SPECIFIC NUMBER: */ #define SN_REBOOTREASONSTARTUPTRAP 1 static const struct snmp_obj_id snmpEnterpriseOID = {8, {1,3,6,1,4,1,SNMP_ENTERPRISE, 1}}; /* Copied from REBOOTTRAPS_var.c */ static const struct snmp_obj_id rebootReasonStartupOid = {13, {1,3,6,1,4,1,SNMP_ENTERPRISE,2,4,1,2,0,1}}; /* The following OIDs are used for trap message variable bindings. */ static const struct snmp_obj_id rebootReasonStrOid = {13, {1,3,6,1,4,1,SNMP_ENTERPRISE,2,4,1,1,2,0}}; static const struct snmp_obj_id rebootReasonNumOid = {13, {1,3,6,1,4,1,SNMP_ENTERPRISE,2,4,1,1,1,0}}; static err_t send_trap_generic(const struct snmp_obj_id* trap_oid, s32_t specific_trap, struct snmp_varbind *varbind_list) { err_t err = ERR_ARG; // Our SNMPv1 and v2c traps implementation is not according to rfc3584, so we have to do // some tweaking. if (snmp_get_default_trap_version() == 0) { // For SNMPv1m, we use the trap defines in "trap_specific_numlist_com.h" and our specific snmpEnterpriseOID. err = snmp_send_trap(&snmpEnterpriseOID, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbind_list); } else { if (trap_oid->len > 2) { struct snmp_obj_id shortened_oid; // SNMPv2c, lwIP will extend the oid with "0,". So we strip the // the last two sub-identifiers of trap_oid. The specific_trap is set to the // value of the last sub-identifier of the original trap_oid. snmp_oid_assign(&shortened_oid, trap_oid->id, trap_oid->len-2); err = snmp_send_trap(&shortened_oid, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, trap_oid->id[trap_oid->len-1], varbind_list); } } return err; } int rebootReasonStartupTrap(void) { struct snmp_varbind *varbind_list = NULL; varbind_list_insert(&varbind_list, varbind_new_from_id(&rebootReasonNumOid)); varbind_list_insert(&varbind_list, varbind_new_from_id(&rebootReasonStrOid)); send_trap_generic(&rebootReasonStartupOid, SN_REBOOTREASONSTARTUPTRAP, varbind_list); varbind_list_free(varbind_list); return 0; } VARBIND.C: // Not a lwIP public function, yet. u8_t snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance *node_instance); struct snmp_varbind *varbind_new_from_id(const struct snmp_obj_id *oid) { struct snmp_varbind *varbind; struct snmp_node_instance node_instance; // Allocate space for varbind varbind = calloc(sizeof(*varbind)); if (!varbind) { return NULL; } // Get oid mode if (snmp_get_node_instance_from_oid(oid->id, oid->len, &node_instance)) { free(varbind); return NULL; } // Allocate space for varbind value varbind->value = malloc(SNMP_MAX_VALUE_SIZE); if (!varbind->value) { free(varbind); return NULL; } // Set varbind values varbind->oid = *oid; varbind->type = node_instance.asn1_type; varbind->value_len = node_instance.get_value(&node_instance, varbind->value); return varbind; } static void varbind_free(struct snmp_varbind *varbind) { if (varbind->value) { free(varbind->value); } free(varbind); } void varbind_list_insert(struct snmp_varbind **varbind_list, struct snmp_varbind *varbind) { if (!varbind) { // Nothing to add return; } if (*varbind_list) { // List not empty (*varbind_list)->prev = varbind; } // Insert to list varbind->next = *varbind_list; *varbind_list = varbind; } void varbind_list_free(struct snmp_varbind *varbind_list) { while (varbind_list) { struct snmp_varbind *next = varbind_list->next; varbind_free(varbind_list); varbind_list = next; } }