1195972f6Sopenharmony_ci/**
2195972f6Sopenharmony_ci * @file
3195972f6Sopenharmony_ci * SNMPv1 traps implementation.
4195972f6Sopenharmony_ci */
5195972f6Sopenharmony_ci
6195972f6Sopenharmony_ci/*
7195972f6Sopenharmony_ci * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
8195972f6Sopenharmony_ci * All rights reserved.
9195972f6Sopenharmony_ci *
10195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
11195972f6Sopenharmony_ci * are permitted provided that the following conditions are met:
12195972f6Sopenharmony_ci *
13195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice,
14195972f6Sopenharmony_ci *    this list of conditions and the following disclaimer.
15195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice,
16195972f6Sopenharmony_ci *    this list of conditions and the following disclaimer in the documentation
17195972f6Sopenharmony_ci *    and/or other materials provided with the distribution.
18195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products
19195972f6Sopenharmony_ci *    derived from this software without specific prior written permission.
20195972f6Sopenharmony_ci *
21195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30195972f6Sopenharmony_ci * OF SUCH DAMAGE.
31195972f6Sopenharmony_ci *
32195972f6Sopenharmony_ci * This file is part of the lwIP TCP/IP stack.
33195972f6Sopenharmony_ci *
34195972f6Sopenharmony_ci * Author: Martin Hentschel
35195972f6Sopenharmony_ci *         Christiaan Simons <christiaan.simons@axon.tv>
36195972f6Sopenharmony_ci *
37195972f6Sopenharmony_ci */
38195972f6Sopenharmony_ci
39195972f6Sopenharmony_ci#include "lwip/apps/snmp_opts.h"
40195972f6Sopenharmony_ci
41195972f6Sopenharmony_ci#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
42195972f6Sopenharmony_ci
43195972f6Sopenharmony_ci#include <string.h>
44195972f6Sopenharmony_ci
45195972f6Sopenharmony_ci#include "lwip/snmp.h"
46195972f6Sopenharmony_ci#include "lwip/sys.h"
47195972f6Sopenharmony_ci#include "lwip/apps/snmp.h"
48195972f6Sopenharmony_ci#include "lwip/apps/snmp_core.h"
49195972f6Sopenharmony_ci#include "lwip/prot/iana.h"
50195972f6Sopenharmony_ci#include "snmp_msg.h"
51195972f6Sopenharmony_ci#include "snmp_asn1.h"
52195972f6Sopenharmony_ci#include "snmp_core_priv.h"
53195972f6Sopenharmony_ci
54195972f6Sopenharmony_cistruct snmp_msg_trap {
55195972f6Sopenharmony_ci  /* source enterprise ID (sysObjectID) */
56195972f6Sopenharmony_ci  const struct snmp_obj_id *enterprise;
57195972f6Sopenharmony_ci  /* source IP address, raw network order format */
58195972f6Sopenharmony_ci  ip_addr_t sip;
59195972f6Sopenharmony_ci  /* generic trap code */
60195972f6Sopenharmony_ci  u32_t gen_trap;
61195972f6Sopenharmony_ci  /* specific trap code */
62195972f6Sopenharmony_ci  u32_t spc_trap;
63195972f6Sopenharmony_ci  /* timestamp */
64195972f6Sopenharmony_ci  u32_t ts;
65195972f6Sopenharmony_ci  /* snmp_version */
66195972f6Sopenharmony_ci  u32_t snmp_version;
67195972f6Sopenharmony_ci
68195972f6Sopenharmony_ci  /* output trap lengths used in ASN encoding */
69195972f6Sopenharmony_ci  /* encoding pdu length */
70195972f6Sopenharmony_ci  u16_t pdulen;
71195972f6Sopenharmony_ci  /* encoding community length */
72195972f6Sopenharmony_ci  u16_t comlen;
73195972f6Sopenharmony_ci  /* encoding sequence length */
74195972f6Sopenharmony_ci  u16_t seqlen;
75195972f6Sopenharmony_ci  /* encoding varbinds sequence length */
76195972f6Sopenharmony_ci  u16_t vbseqlen;
77195972f6Sopenharmony_ci};
78195972f6Sopenharmony_ci
79195972f6Sopenharmony_cistatic u16_t snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds);
80195972f6Sopenharmony_cistatic u16_t snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len);
81195972f6Sopenharmony_cistatic err_t snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream);
82195972f6Sopenharmony_cistatic err_t snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds);
83195972f6Sopenharmony_ci
84195972f6Sopenharmony_ci#define BUILD_EXEC(code) \
85195972f6Sopenharmony_ci  if ((code) != ERR_OK) { \
86195972f6Sopenharmony_ci    LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound trap frame!")); \
87195972f6Sopenharmony_ci    return ERR_ARG; \
88195972f6Sopenharmony_ci  }
89195972f6Sopenharmony_ci
90195972f6Sopenharmony_ci/** Agent community string for sending traps */
91195972f6Sopenharmony_ciextern const char *snmp_community_trap;
92195972f6Sopenharmony_ci
93195972f6Sopenharmony_civoid *snmp_traps_handle;
94195972f6Sopenharmony_ci
95195972f6Sopenharmony_cistruct snmp_trap_dst {
96195972f6Sopenharmony_ci  /* destination IP address in network order */
97195972f6Sopenharmony_ci  ip_addr_t dip;
98195972f6Sopenharmony_ci  /* set to 0 when disabled, >0 when enabled */
99195972f6Sopenharmony_ci  u8_t enable;
100195972f6Sopenharmony_ci};
101195972f6Sopenharmony_cistatic struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS];
102195972f6Sopenharmony_ci
103195972f6Sopenharmony_cistatic u8_t snmp_auth_traps_enabled = 0;
104195972f6Sopenharmony_ci
105195972f6Sopenharmony_ci/**
106195972f6Sopenharmony_ci * @ingroup snmp_traps
107195972f6Sopenharmony_ci * Sets enable switch for this trap destination.
108195972f6Sopenharmony_ci * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1
109195972f6Sopenharmony_ci * @param enable switch if 0 destination is disabled >0 enabled.
110195972f6Sopenharmony_ci */
111195972f6Sopenharmony_civoid
112195972f6Sopenharmony_cisnmp_trap_dst_enable(u8_t dst_idx, u8_t enable)
113195972f6Sopenharmony_ci{
114195972f6Sopenharmony_ci  LWIP_ASSERT_CORE_LOCKED();
115195972f6Sopenharmony_ci  if (dst_idx < SNMP_TRAP_DESTINATIONS) {
116195972f6Sopenharmony_ci    trap_dst[dst_idx].enable = enable;
117195972f6Sopenharmony_ci  }
118195972f6Sopenharmony_ci}
119195972f6Sopenharmony_ci
120195972f6Sopenharmony_ci/**
121195972f6Sopenharmony_ci * @ingroup snmp_traps
122195972f6Sopenharmony_ci * Sets IPv4 address for this trap destination.
123195972f6Sopenharmony_ci * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1
124195972f6Sopenharmony_ci * @param dst IPv4 address in host order.
125195972f6Sopenharmony_ci */
126195972f6Sopenharmony_civoid
127195972f6Sopenharmony_cisnmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst)
128195972f6Sopenharmony_ci{
129195972f6Sopenharmony_ci  LWIP_ASSERT_CORE_LOCKED();
130195972f6Sopenharmony_ci  if (dst_idx < SNMP_TRAP_DESTINATIONS) {
131195972f6Sopenharmony_ci    ip_addr_set(&trap_dst[dst_idx].dip, dst);
132195972f6Sopenharmony_ci  }
133195972f6Sopenharmony_ci}
134195972f6Sopenharmony_ci
135195972f6Sopenharmony_ci/**
136195972f6Sopenharmony_ci * @ingroup snmp_traps
137195972f6Sopenharmony_ci * Enable/disable authentication traps
138195972f6Sopenharmony_ci */
139195972f6Sopenharmony_civoid
140195972f6Sopenharmony_cisnmp_set_auth_traps_enabled(u8_t enable)
141195972f6Sopenharmony_ci{
142195972f6Sopenharmony_ci  snmp_auth_traps_enabled = enable;
143195972f6Sopenharmony_ci}
144195972f6Sopenharmony_ci
145195972f6Sopenharmony_ci/**
146195972f6Sopenharmony_ci * @ingroup snmp_traps
147195972f6Sopenharmony_ci * Get authentication traps enabled state
148195972f6Sopenharmony_ci */
149195972f6Sopenharmony_ciu8_t
150195972f6Sopenharmony_cisnmp_get_auth_traps_enabled(void)
151195972f6Sopenharmony_ci{
152195972f6Sopenharmony_ci  return snmp_auth_traps_enabled;
153195972f6Sopenharmony_ci}
154195972f6Sopenharmony_ci
155195972f6Sopenharmony_ci
156195972f6Sopenharmony_ci/**
157195972f6Sopenharmony_ci * @ingroup snmp_traps
158195972f6Sopenharmony_ci * Sends a generic or enterprise specific trap message.
159195972f6Sopenharmony_ci *
160195972f6Sopenharmony_ci * @param eoid points to enterprise object identifier
161195972f6Sopenharmony_ci * @param generic_trap is the trap code
162195972f6Sopenharmony_ci * @param specific_trap used for enterprise traps when generic_trap == 6
163195972f6Sopenharmony_ci * @param varbinds linked list of varbinds to be sent
164195972f6Sopenharmony_ci * @return ERR_OK when success, ERR_MEM if we're out of memory
165195972f6Sopenharmony_ci *
166195972f6Sopenharmony_ci * @note the use of the enterprise identifier field
167195972f6Sopenharmony_ci * is per RFC1215.
168195972f6Sopenharmony_ci * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps
169195972f6Sopenharmony_ci * and .iso.org.dod.internet.private.enterprises.yourenterprise
170195972f6Sopenharmony_ci * (sysObjectID) for specific traps.
171195972f6Sopenharmony_ci */
172195972f6Sopenharmony_cierr_t
173195972f6Sopenharmony_cisnmp_send_trap(const struct snmp_obj_id *eoid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds)
174195972f6Sopenharmony_ci{
175195972f6Sopenharmony_ci  struct snmp_msg_trap trap_msg;
176195972f6Sopenharmony_ci  struct snmp_trap_dst *td;
177195972f6Sopenharmony_ci  struct pbuf *p;
178195972f6Sopenharmony_ci  u16_t i, tot_len;
179195972f6Sopenharmony_ci  err_t err = ERR_OK;
180195972f6Sopenharmony_ci
181195972f6Sopenharmony_ci  LWIP_ASSERT_CORE_LOCKED();
182195972f6Sopenharmony_ci
183195972f6Sopenharmony_ci  trap_msg.snmp_version = 0;
184195972f6Sopenharmony_ci
185195972f6Sopenharmony_ci  for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) {
186195972f6Sopenharmony_ci    if ((td->enable != 0) && !ip_addr_isany(&td->dip)) {
187195972f6Sopenharmony_ci      /* lookup current source address for this dst */
188195972f6Sopenharmony_ci      if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) {
189195972f6Sopenharmony_ci        if (eoid == NULL) {
190195972f6Sopenharmony_ci          trap_msg.enterprise = snmp_get_device_enterprise_oid();
191195972f6Sopenharmony_ci        } else {
192195972f6Sopenharmony_ci          trap_msg.enterprise = eoid;
193195972f6Sopenharmony_ci        }
194195972f6Sopenharmony_ci
195195972f6Sopenharmony_ci        trap_msg.gen_trap = generic_trap;
196195972f6Sopenharmony_ci        if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) {
197195972f6Sopenharmony_ci          trap_msg.spc_trap = specific_trap;
198195972f6Sopenharmony_ci        } else {
199195972f6Sopenharmony_ci          trap_msg.spc_trap = 0;
200195972f6Sopenharmony_ci        }
201195972f6Sopenharmony_ci
202195972f6Sopenharmony_ci        MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts);
203195972f6Sopenharmony_ci
204195972f6Sopenharmony_ci        /* pass 0, calculate length fields */
205195972f6Sopenharmony_ci        tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds);
206195972f6Sopenharmony_ci        tot_len = snmp_trap_header_sum(&trap_msg, tot_len);
207195972f6Sopenharmony_ci
208195972f6Sopenharmony_ci        /* allocate pbuf(s) */
209195972f6Sopenharmony_ci        p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM);
210195972f6Sopenharmony_ci        if (p != NULL) {
211195972f6Sopenharmony_ci          struct snmp_pbuf_stream pbuf_stream;
212195972f6Sopenharmony_ci          snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len);
213195972f6Sopenharmony_ci
214195972f6Sopenharmony_ci          /* pass 1, encode packet into the pbuf(s) */
215195972f6Sopenharmony_ci          snmp_trap_header_enc(&trap_msg, &pbuf_stream);
216195972f6Sopenharmony_ci          snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds);
217195972f6Sopenharmony_ci
218195972f6Sopenharmony_ci          snmp_stats.outtraps++;
219195972f6Sopenharmony_ci          snmp_stats.outpkts++;
220195972f6Sopenharmony_ci
221195972f6Sopenharmony_ci          /** send to the TRAP destination */
222195972f6Sopenharmony_ci          snmp_sendto(snmp_traps_handle, p, &td->dip, LWIP_IANA_PORT_SNMP_TRAP);
223195972f6Sopenharmony_ci          pbuf_free(p);
224195972f6Sopenharmony_ci        } else {
225195972f6Sopenharmony_ci          err = ERR_MEM;
226195972f6Sopenharmony_ci        }
227195972f6Sopenharmony_ci      } else {
228195972f6Sopenharmony_ci        /* routing error */
229195972f6Sopenharmony_ci        err = ERR_RTE;
230195972f6Sopenharmony_ci      }
231195972f6Sopenharmony_ci    }
232195972f6Sopenharmony_ci  }
233195972f6Sopenharmony_ci  return err;
234195972f6Sopenharmony_ci}
235195972f6Sopenharmony_ci
236195972f6Sopenharmony_ci/**
237195972f6Sopenharmony_ci * @ingroup snmp_traps
238195972f6Sopenharmony_ci * Send generic SNMP trap
239195972f6Sopenharmony_ci */
240195972f6Sopenharmony_cierr_t
241195972f6Sopenharmony_cisnmp_send_trap_generic(s32_t generic_trap)
242195972f6Sopenharmony_ci{
243195972f6Sopenharmony_ci  static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } };
244195972f6Sopenharmony_ci  return snmp_send_trap(&oid, generic_trap, 0, NULL);
245195972f6Sopenharmony_ci}
246195972f6Sopenharmony_ci
247195972f6Sopenharmony_ci/**
248195972f6Sopenharmony_ci * @ingroup snmp_traps
249195972f6Sopenharmony_ci * Send specific SNMP trap with variable bindings
250195972f6Sopenharmony_ci */
251195972f6Sopenharmony_cierr_t
252195972f6Sopenharmony_cisnmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds)
253195972f6Sopenharmony_ci{
254195972f6Sopenharmony_ci  return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds);
255195972f6Sopenharmony_ci}
256195972f6Sopenharmony_ci
257195972f6Sopenharmony_ci/**
258195972f6Sopenharmony_ci * @ingroup snmp_traps
259195972f6Sopenharmony_ci * Send coldstart trap
260195972f6Sopenharmony_ci */
261195972f6Sopenharmony_civoid
262195972f6Sopenharmony_cisnmp_coldstart_trap(void)
263195972f6Sopenharmony_ci{
264195972f6Sopenharmony_ci  snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART);
265195972f6Sopenharmony_ci}
266195972f6Sopenharmony_ci
267195972f6Sopenharmony_ci/**
268195972f6Sopenharmony_ci * @ingroup snmp_traps
269195972f6Sopenharmony_ci * Send authentication failure trap (used internally by agent)
270195972f6Sopenharmony_ci */
271195972f6Sopenharmony_civoid
272195972f6Sopenharmony_cisnmp_authfail_trap(void)
273195972f6Sopenharmony_ci{
274195972f6Sopenharmony_ci  if (snmp_auth_traps_enabled != 0) {
275195972f6Sopenharmony_ci    snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE);
276195972f6Sopenharmony_ci  }
277195972f6Sopenharmony_ci}
278195972f6Sopenharmony_ci
279195972f6Sopenharmony_cistatic u16_t
280195972f6Sopenharmony_cisnmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds)
281195972f6Sopenharmony_ci{
282195972f6Sopenharmony_ci  struct snmp_varbind *varbind;
283195972f6Sopenharmony_ci  u16_t tot_len;
284195972f6Sopenharmony_ci  u8_t tot_len_len;
285195972f6Sopenharmony_ci
286195972f6Sopenharmony_ci  tot_len = 0;
287195972f6Sopenharmony_ci  varbind = varbinds;
288195972f6Sopenharmony_ci  while (varbind != NULL) {
289195972f6Sopenharmony_ci    struct snmp_varbind_len len;
290195972f6Sopenharmony_ci
291195972f6Sopenharmony_ci    if (snmp_varbind_length(varbind, &len) == ERR_OK) {
292195972f6Sopenharmony_ci      tot_len += 1 + len.vb_len_len + len.vb_value_len;
293195972f6Sopenharmony_ci    }
294195972f6Sopenharmony_ci
295195972f6Sopenharmony_ci    varbind = varbind->next;
296195972f6Sopenharmony_ci  }
297195972f6Sopenharmony_ci
298195972f6Sopenharmony_ci  trap->vbseqlen = tot_len;
299195972f6Sopenharmony_ci  snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len);
300195972f6Sopenharmony_ci  tot_len += 1 + tot_len_len;
301195972f6Sopenharmony_ci
302195972f6Sopenharmony_ci  return tot_len;
303195972f6Sopenharmony_ci}
304195972f6Sopenharmony_ci
305195972f6Sopenharmony_ci/**
306195972f6Sopenharmony_ci * Sums trap header field lengths from tail to head and
307195972f6Sopenharmony_ci * returns trap_header_lengths for second encoding pass.
308195972f6Sopenharmony_ci *
309195972f6Sopenharmony_ci * @param trap Trap message
310195972f6Sopenharmony_ci * @param vb_len varbind-list length
311195972f6Sopenharmony_ci * @return the required length for encoding the trap header
312195972f6Sopenharmony_ci */
313195972f6Sopenharmony_cistatic u16_t
314195972f6Sopenharmony_cisnmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len)
315195972f6Sopenharmony_ci{
316195972f6Sopenharmony_ci  u16_t tot_len;
317195972f6Sopenharmony_ci  u16_t len;
318195972f6Sopenharmony_ci  u8_t lenlen;
319195972f6Sopenharmony_ci
320195972f6Sopenharmony_ci  tot_len = vb_len;
321195972f6Sopenharmony_ci
322195972f6Sopenharmony_ci  snmp_asn1_enc_u32t_cnt(trap->ts, &len);
323195972f6Sopenharmony_ci  snmp_asn1_enc_length_cnt(len, &lenlen);
324195972f6Sopenharmony_ci  tot_len += 1 + len + lenlen;
325195972f6Sopenharmony_ci
326195972f6Sopenharmony_ci  snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len);
327195972f6Sopenharmony_ci  snmp_asn1_enc_length_cnt(len, &lenlen);
328195972f6Sopenharmony_ci  tot_len += 1 + len + lenlen;
329195972f6Sopenharmony_ci
330195972f6Sopenharmony_ci  snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len);
331195972f6Sopenharmony_ci  snmp_asn1_enc_length_cnt(len, &lenlen);
332195972f6Sopenharmony_ci  tot_len += 1 + len + lenlen;
333195972f6Sopenharmony_ci
334195972f6Sopenharmony_ci  if (IP_IS_V6_VAL(trap->sip)) {
335195972f6Sopenharmony_ci#if LWIP_IPV6
336195972f6Sopenharmony_ci    len = sizeof(ip_2_ip6(&trap->sip)->addr);
337195972f6Sopenharmony_ci#endif
338195972f6Sopenharmony_ci  } else {
339195972f6Sopenharmony_ci#if LWIP_IPV4
340195972f6Sopenharmony_ci    len = sizeof(ip_2_ip4(&trap->sip)->addr);
341195972f6Sopenharmony_ci#endif
342195972f6Sopenharmony_ci  }
343195972f6Sopenharmony_ci  snmp_asn1_enc_length_cnt(len, &lenlen);
344195972f6Sopenharmony_ci  tot_len += 1 + len + lenlen;
345195972f6Sopenharmony_ci
346195972f6Sopenharmony_ci  snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len);
347195972f6Sopenharmony_ci  snmp_asn1_enc_length_cnt(len, &lenlen);
348195972f6Sopenharmony_ci  tot_len += 1 + len + lenlen;
349195972f6Sopenharmony_ci
350195972f6Sopenharmony_ci  trap->pdulen = tot_len;
351195972f6Sopenharmony_ci  snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen);
352195972f6Sopenharmony_ci  tot_len += 1 + lenlen;
353195972f6Sopenharmony_ci
354195972f6Sopenharmony_ci  trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF);
355195972f6Sopenharmony_ci  snmp_asn1_enc_length_cnt(trap->comlen, &lenlen);
356195972f6Sopenharmony_ci  tot_len += 1 + lenlen + trap->comlen;
357195972f6Sopenharmony_ci
358195972f6Sopenharmony_ci  snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len);
359195972f6Sopenharmony_ci  snmp_asn1_enc_length_cnt(len, &lenlen);
360195972f6Sopenharmony_ci  tot_len += 1 + len + lenlen;
361195972f6Sopenharmony_ci
362195972f6Sopenharmony_ci  trap->seqlen = tot_len;
363195972f6Sopenharmony_ci  snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen);
364195972f6Sopenharmony_ci  tot_len += 1 + lenlen;
365195972f6Sopenharmony_ci
366195972f6Sopenharmony_ci  return tot_len;
367195972f6Sopenharmony_ci}
368195972f6Sopenharmony_ci
369195972f6Sopenharmony_cistatic err_t
370195972f6Sopenharmony_cisnmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds)
371195972f6Sopenharmony_ci{
372195972f6Sopenharmony_ci  struct snmp_asn1_tlv tlv;
373195972f6Sopenharmony_ci  struct snmp_varbind *varbind;
374195972f6Sopenharmony_ci
375195972f6Sopenharmony_ci  varbind = varbinds;
376195972f6Sopenharmony_ci
377195972f6Sopenharmony_ci  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen);
378195972f6Sopenharmony_ci  BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
379195972f6Sopenharmony_ci
380195972f6Sopenharmony_ci  while (varbind != NULL) {
381195972f6Sopenharmony_ci    BUILD_EXEC( snmp_append_outbound_varbind(pbuf_stream, varbind) );
382195972f6Sopenharmony_ci
383195972f6Sopenharmony_ci    varbind = varbind->next;
384195972f6Sopenharmony_ci  }
385195972f6Sopenharmony_ci
386195972f6Sopenharmony_ci  return ERR_OK;
387195972f6Sopenharmony_ci}
388195972f6Sopenharmony_ci
389195972f6Sopenharmony_ci/**
390195972f6Sopenharmony_ci * Encodes trap header from head to tail.
391195972f6Sopenharmony_ci */
392195972f6Sopenharmony_cistatic err_t
393195972f6Sopenharmony_cisnmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream)
394195972f6Sopenharmony_ci{
395195972f6Sopenharmony_ci  struct snmp_asn1_tlv tlv;
396195972f6Sopenharmony_ci
397195972f6Sopenharmony_ci  /* 'Message' sequence */
398195972f6Sopenharmony_ci  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen);
399195972f6Sopenharmony_ci  BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
400195972f6Sopenharmony_ci
401195972f6Sopenharmony_ci  /* version */
402195972f6Sopenharmony_ci  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
403195972f6Sopenharmony_ci  snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len);
404195972f6Sopenharmony_ci  BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
405195972f6Sopenharmony_ci  BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version) );
406195972f6Sopenharmony_ci
407195972f6Sopenharmony_ci  /* community */
408195972f6Sopenharmony_ci  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen);
409195972f6Sopenharmony_ci  BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
410195972f6Sopenharmony_ci  BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream,  (const u8_t *)snmp_community_trap, trap->comlen) );
411195972f6Sopenharmony_ci
412195972f6Sopenharmony_ci  /* 'PDU' sequence */
413195972f6Sopenharmony_ci  SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen);
414195972f6Sopenharmony_ci  BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
415195972f6Sopenharmony_ci
416195972f6Sopenharmony_ci  /* object ID */
417195972f6Sopenharmony_ci  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0);
418195972f6Sopenharmony_ci  snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len);
419195972f6Sopenharmony_ci  BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
420195972f6Sopenharmony_ci  BUILD_EXEC( snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len) );
421195972f6Sopenharmony_ci
422195972f6Sopenharmony_ci  /* IP addr */
423195972f6Sopenharmony_ci  if (IP_IS_V6_VAL(trap->sip)) {
424195972f6Sopenharmony_ci#if LWIP_IPV6
425195972f6Sopenharmony_ci    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr));
426195972f6Sopenharmony_ci    BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
427195972f6Sopenharmony_ci    BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr)) );
428195972f6Sopenharmony_ci#endif
429195972f6Sopenharmony_ci  } else {
430195972f6Sopenharmony_ci#if LWIP_IPV4
431195972f6Sopenharmony_ci    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr));
432195972f6Sopenharmony_ci    BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
433195972f6Sopenharmony_ci    BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr)) );
434195972f6Sopenharmony_ci#endif
435195972f6Sopenharmony_ci  }
436195972f6Sopenharmony_ci
437195972f6Sopenharmony_ci  /* trap length */
438195972f6Sopenharmony_ci  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
439195972f6Sopenharmony_ci  snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len);
440195972f6Sopenharmony_ci  BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
441195972f6Sopenharmony_ci  BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap) );
442195972f6Sopenharmony_ci
443195972f6Sopenharmony_ci  /* specific trap */
444195972f6Sopenharmony_ci  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
445195972f6Sopenharmony_ci  snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len);
446195972f6Sopenharmony_ci  BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
447195972f6Sopenharmony_ci  BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap) );
448195972f6Sopenharmony_ci
449195972f6Sopenharmony_ci  /* timestamp */
450195972f6Sopenharmony_ci  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0);
451195972f6Sopenharmony_ci  snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len);
452195972f6Sopenharmony_ci  BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
453195972f6Sopenharmony_ci  BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts) );
454195972f6Sopenharmony_ci
455195972f6Sopenharmony_ci  return ERR_OK;
456195972f6Sopenharmony_ci}
457195972f6Sopenharmony_ci
458195972f6Sopenharmony_ci#endif /* LWIP_SNMP */
459