/** * Sends an generic or enterprise specific trap message. * * @param generic_trap is the trap code * @param eoid points to enterprise object identifier * @param specific_trap used for enterprise traps when generic_trap == 6 * @return ERR_OK when success, ERR_MEM if we're out of memory * * @note the use of the enterprise identifier field * is per RFC1215. * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps * and .iso.org.dod.internet.private.enterprises.yourenterprise * (sysObjectID) for specific traps. */ static err_t snmp_send_trap(const struct snmp_obj_id *device_enterprise_oid, s32_t generic_trap, s32_t specific_trap) { struct snmp_msg_trap trap_msg; struct snmp_trap_dst *td; struct pbuf *p; u16_t i, tot_len; err_t err = ERR_OK; trap_msg.snmp_version = 0; for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) { if ((td->enable != 0) && !ip_addr_isany(&td->dip)) { /* lookup current source address for this dst */ if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) { if (device_enterprise_oid == NULL) { trap_msg.enterprise = snmp_get_device_enterprise_oid(); } else { trap_msg.enterprise = device_enterprise_oid; } trap_msg.gen_trap = generic_trap; if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) { trap_msg.spc_trap = specific_trap; } else { trap_msg.spc_trap = 0; } MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts); /* pass 0, calculate length fields */ tot_len = snmp_trap_header_sum(&trap_msg); /* allocate pbuf(s) */ p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM); if (p != NULL) { struct snmp_pbuf_stream pbuf_stream; snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len); /* pass 1, encode packet ino the pbuf(s) */ snmp_trap_header_enc(&trap_msg, &pbuf_stream); snmp_stats.outtraps++; snmp_stats.outpkts++; /** send to the TRAP destination */ snmp_sendto(snmp_traps_handle, p, &td->dip, SNMP_TRAP_PORT); } else { err = ERR_MEM; } } else { /* routing error */ err = ERR_RTE; } } } return err; }
void snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port) { err_t err; struct snmp_request request; memset(&request, 0, sizeof(request)); request.handle = handle; request.source_ip = source_ip; request.source_port = port; request.inbound_pbuf = p; snmp_stats.inpkts++; err = snmp_parse_inbound_frame(&request); if (err == ERR_OK) { err = snmp_prepare_outbound_frame(&request); if (err == ERR_OK) { if (request.error_status == SNMP_ERR_NOERROR) { /* only process frame if we do not already have an error to return (e.g. all readonly) */ if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_REQ) { err = snmp_process_get_request(&request); } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ) { err = snmp_process_getnext_request(&request); } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { err = snmp_process_getbulk_request(&request); } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { err = snmp_process_set_request(&request); } } if (err == ERR_OK) { err = snmp_complete_outbound_frame(&request); if (err == ERR_OK) { err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port); if ((request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) && (request.error_status == SNMP_ERR_NOERROR) && (snmp_write_callback != NULL)) { /* raise write notification for all written objects */ snmp_execute_write_callbacks(&request); } } } } if (request.outbound_pbuf != NULL) { pbuf_free(request.outbound_pbuf); } } }