snmp_trap_pdu2.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /*
  2. * snmp_trap_pdu2.c
  3. *
  4. * Created on: 30.10.2017
  5. * Author: balbekova
  6. */
  7. #include "lwip/apps/snmp_opts.h"
  8. #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
  9. #include "snmp_msg.h"
  10. #include "snmp_asn1.h"
  11. #include "snmp_core_priv.h"
  12. #include "lwip/ip_addr.h"
  13. #include "lwip/stats.h"
  14. #if LWIP_SNMP_V3
  15. #include "lwip/apps/snmpv3.h"
  16. #include "snmpv3_priv.h"
  17. #ifdef LWIP_SNMPV3_INCLUDE_ENGINE
  18. #include LWIP_SNMPV3_INCLUDE_ENGINE
  19. #endif
  20. #endif
  21. #include <string.h>
  22. #define BUILD_EXEC_TRAP(code, retValue) \
  23. if ((code) != ERR_OK) { \
  24. LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound frame!: " # code)); \
  25. return retValue; \
  26. }
  27. #define OF_BUILD_EXEC_TRAP(code) BUILD_EXEC_TRAP(code, ERR_ARG)
  28. struct snmp_trap_pduv2_dst
  29. {
  30. /* destination IP address in network order */
  31. ip_addr_t dip;
  32. /* set to 0 when disabled, >0 when enabled */
  33. u8_t enable;
  34. };
  35. static struct snmp_trap_pduv2_dst trap_pduv2_dst[SNMP_TRAP_DESTINATIONS];
  36. void* snmp_traps_pdu2_handle;
  37. /**
  38. * @ingroup snmp_traps
  39. * Sets enable switch for this trap destination.
  40. * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1
  41. * @param enable switch if 0 destination is disabled >0 enabled.
  42. */
  43. void
  44. snmp_trap_pduv2_dst_enable(u8_t dst_idx, u8_t enable)
  45. {
  46. if (dst_idx < SNMP_TRAP_DESTINATIONS) {
  47. trap_pduv2_dst[dst_idx].enable = enable;
  48. }
  49. }
  50. static err_t
  51. snmp_complete_outbound_frame_trap_pduv2(struct snmp_request *request)
  52. {
  53. struct snmp_asn1_tlv tlv;
  54. u16_t frame_size;
  55. u8_t outbound_padding = 0;
  56. if (request->version == SNMP_VERSION_1) {
  57. if (request->error_status != SNMP_ERR_NOERROR) {
  58. /* map v2c error codes to v1 compliant error code (according to RFC 2089) */
  59. switch (request->error_status) {
  60. /* mapping of implementation specific "virtual" error codes
  61. * (during processing of frame we already stored them in error_status field,
  62. * so no need to check all varbinds here for those exceptions as suggested by RFC) */
  63. case SNMP_ERR_NOSUCHINSTANCE:
  64. case SNMP_ERR_NOSUCHOBJECT:
  65. case SNMP_ERR_ENDOFMIBVIEW:
  66. request->error_status = SNMP_ERR_NOSUCHNAME;
  67. break;
  68. /* mapping according to RFC */
  69. case SNMP_ERR_WRONGVALUE:
  70. case SNMP_ERR_WRONGENCODING:
  71. case SNMP_ERR_WRONGTYPE:
  72. case SNMP_ERR_WRONGLENGTH:
  73. case SNMP_ERR_INCONSISTENTVALUE:
  74. request->error_status = SNMP_ERR_BADVALUE;
  75. break;
  76. case SNMP_ERR_NOACCESS:
  77. case SNMP_ERR_NOTWRITABLE:
  78. case SNMP_ERR_NOCREATION:
  79. case SNMP_ERR_INCONSISTENTNAME:
  80. case SNMP_ERR_AUTHORIZATIONERROR:
  81. request->error_status = SNMP_ERR_NOSUCHNAME;
  82. break;
  83. case SNMP_ERR_RESOURCEUNAVAILABLE:
  84. case SNMP_ERR_COMMITFAILED:
  85. case SNMP_ERR_UNDOFAILED:
  86. default:
  87. request->error_status = SNMP_ERR_GENERROR;
  88. break;
  89. }
  90. }
  91. } else {
  92. if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
  93. /* map error codes to according to RFC 1905 (4.2.5. The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */
  94. switch (request->error_status) {
  95. case SNMP_ERR_NOSUCHINSTANCE:
  96. case SNMP_ERR_NOSUCHOBJECT:
  97. case SNMP_ERR_ENDOFMIBVIEW:
  98. request->error_status = SNMP_ERR_NOTWRITABLE;
  99. break;
  100. default:
  101. break;
  102. }
  103. }
  104. if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) {
  105. /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */
  106. LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n"));
  107. return ERR_ARG;
  108. }
  109. }
  110. if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) {
  111. /* all inbound vars are returned in response without any modification for error responses and successful set requests*/
  112. struct snmp_pbuf_stream inbound_stream;
  113. OF_BUILD_EXEC_TRAP( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) );
  114. OF_BUILD_EXEC_TRAP( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, request->outbound_varbind_offset, request->outbound_pbuf->tot_len - request->outbound_varbind_offset) );
  115. snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0);
  116. }
  117. frame_size = request->outbound_pbuf_stream.offset;
  118. #if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO
  119. /* Calculate padding for encryption */
  120. if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) {
  121. u8_t i;
  122. outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07;
  123. for (i = 0; i < outbound_padding; i++) {
  124. snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0);
  125. }
  126. }
  127. #endif
  128. /* complete missing length in 'Message' sequence ; 'Message' tlv is located at the beginning (offset 0) */
  129. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 2, frame_size + outbound_padding - 1 - 2); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
  130. OF_BUILD_EXEC_TRAP( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) );
  131. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
  132. #if LWIP_SNMP_V3
  133. if (request->version == SNMP_VERSION_3) {
  134. /* complete missing length in 'globalData' sequence */
  135. /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
  136. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_global_data_end
  137. - request->outbound_msg_global_data_offset - 1 - 1);
  138. OF_BUILD_EXEC_TRAP(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_global_data_offset));
  139. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
  140. /* complete missing length in 'msgSecurityParameters' sequence */
  141. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, request->outbound_msg_security_parameters_end
  142. - request->outbound_msg_security_parameters_str_offset - 1 - 1);
  143. OF_BUILD_EXEC_TRAP(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_str_offset));
  144. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
  145. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_security_parameters_end
  146. - request->outbound_msg_security_parameters_seq_offset - 1 - 1);
  147. OF_BUILD_EXEC_TRAP(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_seq_offset));
  148. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
  149. /* complete missing length in scoped PDU sequence */
  150. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_scoped_pdu_seq_offset - 1 - 3);
  151. OF_BUILD_EXEC_TRAP(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_seq_offset));
  152. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
  153. }
  154. #endif
  155. /* complete missing length in 'PDU' sequence */
  156. SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ | SNMP_ASN1_CONTEXT_PDU_GET_RESP | SNMP_ASN1_CONTEXT_PDU_TRAP), 2,
  157. frame_size - request->outbound_pdu_offset - 1 - 2); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
  158. OF_BUILD_EXEC_TRAP( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) );
  159. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
  160. /* process and encode final error status */
  161. if (request->error_status != 0) {
  162. u16_t len;
  163. snmp_asn1_enc_s32t_cnt(request->error_status, &len);
  164. if (len != 1) {
  165. /* error, we only reserved one byte for it */
  166. return ERR_ARG;
  167. }
  168. OF_BUILD_EXEC_TRAP( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) );
  169. OF_BUILD_EXEC_TRAP( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) );
  170. /* for compatibility to v1, log statistics; in v2 (RFC 1907) these statistics are obsoleted */
  171. switch (request->error_status) {
  172. case SNMP_ERR_TOOBIG:
  173. snmp_stats.outtoobigs++;
  174. break;
  175. case SNMP_ERR_NOSUCHNAME:
  176. snmp_stats.outnosuchnames++;
  177. break;
  178. case SNMP_ERR_BADVALUE:
  179. snmp_stats.outbadvalues++;
  180. break;
  181. case SNMP_ERR_GENERROR:
  182. default:
  183. snmp_stats.outgenerrs++;
  184. break;
  185. }
  186. if (request->error_status == SNMP_ERR_TOOBIG) {
  187. request->error_index = 0; /* defined by RFC 1157 */
  188. } else if (request->error_index == 0) {
  189. /* set index to varbind where error occured (if not already set before, e.g. during GetBulk processing) */
  190. request->error_index = request->inbound_varbind_enumerator.varbind_count;
  191. }
  192. } else {
  193. if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
  194. snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count;
  195. } else {
  196. snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count;
  197. }
  198. }
  199. /* encode final error index*/
  200. if (request->error_index != 0) {
  201. u16_t len;
  202. snmp_asn1_enc_s32t_cnt(request->error_index, &len);
  203. if (len != 1) {
  204. /* error, we only reserved one byte for it */
  205. return ERR_VAL;
  206. }
  207. OF_BUILD_EXEC_TRAP( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) );
  208. OF_BUILD_EXEC_TRAP( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) );
  209. }
  210. /* complete missing length in 'VarBindList' sequence ; 'VarBindList' tlv is located directly before varbind offset */
  211. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, frame_size - request->outbound_varbind_offset);
  212. OF_BUILD_EXEC_TRAP( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_varbind_offset - 1 - 1) ); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
  213. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
  214. /* Authenticate response */
  215. #if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO
  216. /* Encrypt response */
  217. if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) {
  218. u8_t key[20];
  219. u8_t algo;
  220. /* complete missing length in PDU sequence */
  221. OF_BUILD_EXEC_TRAP(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
  222. OF_BUILD_EXEC_TRAP(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_string_offset));
  223. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, frame_size + outbound_padding
  224. - request->outbound_scoped_pdu_string_offset - 1 - 3);
  225. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
  226. OF_BUILD_EXEC_TRAP(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key));
  227. OF_BUILD_EXEC_TRAP(snmpv3_crypt(&request->outbound_pbuf_stream, tlv.value_len, key,
  228. request->msg_privacy_parameters, request->msg_authoritative_engine_boots,
  229. request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_ENCRYPT));
  230. }
  231. if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_AUTH_FLAG)) {
  232. u8_t key[20];
  233. u8_t algo;
  234. u8_t hmac[20];
  235. OF_BUILD_EXEC_TRAP(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL));
  236. OF_BUILD_EXEC_TRAP(snmp_pbuf_stream_init(&(request->outbound_pbuf_stream),
  237. request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
  238. OF_BUILD_EXEC_TRAP(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac));
  239. MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
  240. OF_BUILD_EXEC_TRAP(snmp_pbuf_stream_init(&request->outbound_pbuf_stream,
  241. request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
  242. OF_BUILD_EXEC_TRAP(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream,
  243. request->outbound_msg_authentication_parameters_offset));
  244. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
  245. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(&request->outbound_pbuf_stream, &tlv));
  246. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_raw(&request->outbound_pbuf_stream,
  247. request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH));
  248. }
  249. #endif
  250. pbuf_realloc(request->outbound_pbuf, frame_size + outbound_padding);
  251. snmp_stats.outgetresponses++;
  252. snmp_stats.outpkts++;
  253. return ERR_OK;
  254. }
  255. /**
  256. * @ingroup snmp_traps
  257. * Sets IPv4 address for this trap destination.
  258. * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1
  259. * @param dst IPv4 address in host order.
  260. */
  261. void
  262. snmp_trap_pduv2_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst)
  263. {
  264. if (dst_idx < SNMP_TRAP_DESTINATIONS) {
  265. ip_addr_set(&trap_pduv2_dst[dst_idx].dip, dst);
  266. }
  267. }
  268. static err_t
  269. snmp_prepare_outbound_frame_trap_pduv2(struct snmp_request *request)
  270. {
  271. struct snmp_asn1_tlv tlv;
  272. struct snmp_pbuf_stream* pbuf_stream = &(request->outbound_pbuf_stream);
  273. /* try allocating pbuf(s) for maximum response size */
  274. request->outbound_pbuf = pbuf_alloc(PBUF_TRANSPORT, 1472, PBUF_RAM);
  275. if (request->outbound_pbuf == NULL) {
  276. return ERR_MEM;
  277. }
  278. snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len);
  279. /* 'Message' sequence */
  280. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 2, 0);
  281. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  282. /* version */
  283. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
  284. snmp_asn1_enc_s32t_cnt(request->version, &tlv.value_len);
  285. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  286. OF_BUILD_EXEC_TRAP( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) );
  287. #if LWIP_SNMP_V3
  288. if (request->version < SNMP_VERSION_3) {
  289. #endif
  290. /* community */
  291. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen);
  292. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  293. OF_BUILD_EXEC_TRAP( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) );
  294. #if LWIP_SNMP_V3
  295. } else {
  296. const char* id;
  297. /* globalData */
  298. request->outbound_msg_global_data_offset = pbuf_stream->offset;
  299. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0);
  300. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  301. /* msgID */
  302. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
  303. snmp_asn1_enc_s32t_cnt(request->msg_id, &tlv.value_len);
  304. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  305. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_id));
  306. /* msgMaxSize */
  307. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
  308. snmp_asn1_enc_s32t_cnt(request->msg_max_size, &tlv.value_len);
  309. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  310. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_max_size));
  311. /* msgFlags */
  312. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 1);
  313. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  314. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_raw(pbuf_stream, &request->msg_flags, 1));
  315. /* msgSecurityModel */
  316. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
  317. snmp_asn1_enc_s32t_cnt(request->msg_security_model, &tlv.value_len);
  318. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  319. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_security_model));
  320. /* end of msgGlobalData */
  321. request->outbound_msg_global_data_end = pbuf_stream->offset;
  322. /* msgSecurityParameters */
  323. request->outbound_msg_security_parameters_str_offset = pbuf_stream->offset;
  324. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, 0);
  325. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  326. request->outbound_msg_security_parameters_seq_offset = pbuf_stream->offset;
  327. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0);
  328. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  329. /* msgAuthoritativeEngineID */
  330. snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len);
  331. MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len);
  332. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len);
  333. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  334. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len));
  335. request->msg_authoritative_engine_time = snmpv3_get_engine_time();
  336. request->msg_authoritative_engine_boots = snmpv3_get_engine_boots();
  337. /* msgAuthoritativeEngineBoots */
  338. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
  339. snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_boots, &tlv.value_len);
  340. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  341. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_boots));
  342. /* msgAuthoritativeEngineTime */
  343. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
  344. snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_time, &tlv.value_len);
  345. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  346. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_time));
  347. /* msgUserName */
  348. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_user_name_len);
  349. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  350. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_raw(pbuf_stream, request->msg_user_name, request->msg_user_name_len));
  351. #if LWIP_SNMP_V3_CRYPTO
  352. /* msgAuthenticationParameters */
  353. if (request->msg_flags & SNMP_V3_AUTH_FLAG) {
  354. memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
  355. request->outbound_msg_authentication_parameters_offset = pbuf_stream->offset;
  356. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
  357. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  358. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_raw(pbuf_stream, request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH));
  359. } else
  360. #endif
  361. {
  362. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0);
  363. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  364. }
  365. #if LWIP_SNMP_V3_CRYPTO
  366. /* msgPrivacyParameters */
  367. if (request->msg_flags & SNMP_V3_PRIV_FLAG) {
  368. snmpv3_build_priv_param(request->msg_privacy_parameters);
  369. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH);
  370. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  371. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_raw(pbuf_stream, request->msg_privacy_parameters, SNMP_V3_MAX_PRIV_PARAM_LENGTH));
  372. } else
  373. #endif
  374. {
  375. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0);
  376. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  377. }
  378. /* End of msgSecurityParameters, so we can calculate the length of this sequence later */
  379. request->outbound_msg_security_parameters_end = pbuf_stream->offset;
  380. #if LWIP_SNMP_V3_CRYPTO
  381. /* For encryption we have to encapsulate the payload in an octet string */
  382. if (request->msg_flags & SNMP_V3_PRIV_FLAG) {
  383. request->outbound_scoped_pdu_string_offset = pbuf_stream->offset;
  384. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, 0);
  385. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  386. }
  387. #endif
  388. /* Scoped PDU
  389. * Encryption context
  390. */
  391. request->outbound_scoped_pdu_seq_offset = pbuf_stream->offset;
  392. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
  393. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  394. /* contextEngineID */
  395. snmpv3_get_engine_id(&id, &request->context_engine_id_len);
  396. MEMCPY(request->context_engine_id, id, request->context_engine_id_len);
  397. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len);
  398. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  399. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len));
  400. /* contextName */
  401. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_name_len);
  402. OF_BUILD_EXEC_TRAP(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
  403. OF_BUILD_EXEC_TRAP(snmp_asn1_enc_raw(pbuf_stream, request->context_name, request->context_name_len));
  404. }
  405. #endif
  406. /* 'PDU' sequence */
  407. request->outbound_pdu_offset = pbuf_stream->offset;
  408. // SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 3, 0);
  409. SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 2, 0);
  410. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  411. /* request ID */
  412. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
  413. snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len);
  414. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  415. OF_BUILD_EXEC_TRAP( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) );
  416. /* error status */
  417. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
  418. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  419. request->outbound_error_status_offset = pbuf_stream->offset;
  420. OF_BUILD_EXEC_TRAP( snmp_pbuf_stream_write(pbuf_stream, 0) );
  421. /* error index */
  422. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
  423. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  424. request->outbound_error_index_offset = pbuf_stream->offset;
  425. OF_BUILD_EXEC_TRAP( snmp_pbuf_stream_write(pbuf_stream, 0) );
  426. /* 'VarBindList' sequence */
  427. SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 1);
  428. OF_BUILD_EXEC_TRAP( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  429. request->outbound_varbind_offset = pbuf_stream->offset;
  430. return ERR_OK;
  431. }
  432. err_t
  433. snmp_send_trap_pduv2(struct snmp_varbind *varbinds)
  434. {
  435. err_t err = ERR_OK;
  436. struct snmp_request request;
  437. struct snmp_trap_pduv2_dst *td;
  438. u16_t i;
  439. ip_addr_t sip;
  440. memset(&request, 0, sizeof(request));
  441. request.handle = snmp_traps_handle;
  442. for (i = 0, td = &trap_pduv2_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) {
  443. if ((td->enable != 0) && !ip_addr_isany(&td->dip)) {
  444. /* lookup current source address for this dst */
  445. if (snmp_get_local_ip_for_dst(request.handle, &td->dip, &sip)) {//request.source_ip
  446. request.source_ip = &td->dip;
  447. request.source_port = SNMP_TRAP_PORT;
  448. request.version = SNMP_VERSION_2c;
  449. strcpy((char*)request.community, "public");//snmp_get_community_trap
  450. request.community_strlen = strlen(request.community);
  451. request.request_type = SNMP_ASN1_CONTEXT_PDU_TRAP;
  452. request.request_id = 0x54dc84ac;
  453. err = snmp_prepare_outbound_frame_trap_pduv2(&request);
  454. while (varbinds != NULL) {
  455. err = snmp_append_outbound_varbind(&(request.outbound_pbuf_stream), varbinds);
  456. varbinds = varbinds->next;
  457. }
  458. if (err == ERR_OK) {
  459. /* we stored the exception in varbind -> go on */
  460. request.error_status = SNMP_ERR_NOERROR;
  461. } else if (err == ERR_BUF) {
  462. request.error_status = SNMP_ERR_TOOBIG;
  463. } else {
  464. request.error_status = SNMP_ERR_GENERROR;
  465. }
  466. if (err == ERR_OK) {
  467. err = snmp_complete_outbound_frame_trap_pduv2(&request);
  468. if (err == ERR_OK) {
  469. err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port);
  470. snmp_stats.outtraps++;
  471. }
  472. }
  473. if (request.outbound_pbuf != NULL) {
  474. pbuf_free(request.outbound_pbuf);
  475. }
  476. }
  477. }
  478. }
  479. }
  480. #endif