]> git.sur5r.net Git - freertos/blob - Demo/Common/ethernet/lwIP/core/snmp/msg_out.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / Common / ethernet / lwIP / core / snmp / msg_out.c
1 /**\r
2  * @file\r
3  * SNMP output message processing (RFC1157).\r
4  *\r
5  * Output responses and traps are build in two passes:\r
6  *\r
7  * Pass 0: iterate over the output message backwards to determine encoding lengths\r
8  * Pass 1: the actual forward encoding of internal form into ASN1\r
9  *\r
10  * The single-pass encoding method described by Comer & Stevens\r
11  * requires extra buffer space and copying for reversal of the packet.\r
12  * The buffer requirement can be prohibitively large for big payloads\r
13  * (>= 484) therefore we use the two encoding passes.\r
14  */\r
15 \r
16 /*\r
17  * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.\r
18  * All rights reserved.\r
19  *\r
20  * Redistribution and use in source and binary forms, with or without modification,\r
21  * are permitted provided that the following conditions are met:\r
22  *\r
23  * 1. Redistributions of source code must retain the above copyright notice,\r
24  *    this list of conditions and the following disclaimer.\r
25  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
26  *    this list of conditions and the following disclaimer in the documentation\r
27  *    and/or other materials provided with the distribution.\r
28  * 3. The name of the author may not be used to endorse or promote products\r
29  *    derived from this software without specific prior written permission.\r
30  *\r
31  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
32  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
33  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\r
34  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
35  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\r
36  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
37  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
38  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
39  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\r
40  * OF SUCH DAMAGE.\r
41  *\r
42  * Author: Christiaan Simons <christiaan.simons@axon.tv>\r
43  */\r
44 \r
45 #include "lwip/opt.h"\r
46 \r
47 #if LWIP_SNMP\r
48 #include "arch/cc.h"\r
49 #include "lwip/udp.h"\r
50 #include "lwip/netif.h"\r
51 \r
52 #include "lwip/snmp.h"\r
53 #include "lwip/snmp_asn1.h"\r
54 #include "lwip/snmp_msg.h"\r
55 \r
56 struct snmp_trap_dst\r
57 {\r
58   /* destination IP address in network order */\r
59   struct ip_addr dip;\r
60   /* set to 0 when disabled, >0 when enabled */\r
61   u8_t enable;\r
62 };\r
63 #if (SNMP_TRAP_DESTINATIONS == 0)\r
64 #error "need at least one trap destination"\r
65 #endif\r
66 struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS];\r
67 \r
68 /** TRAP message structure */\r
69 struct snmp_msg_trap trap_msg;\r
70 \r
71 static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len);\r
72 static u16_t snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len);\r
73 static u16_t snmp_varbind_list_sum(struct snmp_varbind_root *root);\r
74 \r
75 static u16_t snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p);\r
76 static u16_t snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p);\r
77 static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs);\r
78 \r
79 /**\r
80  * Sets enable switch for this trap destination.\r
81  * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1\r
82  * @param enable switch if 0 destination is disabled >0 enabled.\r
83  */\r
84 void\r
85 snmp_trap_dst_enable(u8_t dst_idx, u8_t enable)\r
86 {\r
87   if (dst_idx < SNMP_TRAP_DESTINATIONS)\r
88   {\r
89     trap_dst[dst_idx].enable = enable;\r
90   }\r
91 }\r
92 \r
93 /**\r
94  * Sets IPv4 address for this trap destination.\r
95  * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1\r
96  * @param dst IPv4 address in host order.\r
97  */\r
98 void\r
99 snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst)\r
100 {\r
101   if (dst_idx < SNMP_TRAP_DESTINATIONS)\r
102   {\r
103     trap_dst[dst_idx].dip.addr = htonl(dst->addr);\r
104   }\r
105 }\r
106 \r
107 /**\r
108  * Sends a 'getresponse' message to the request originator.\r
109  *\r
110  * @param m_stat points to the current message request state source\r
111  * @return ERR_OK when success, ERR_MEM if we're out of memory\r
112  *\r
113  * @note the caller is responsible for filling in outvb in the m_stat\r
114  * and provide error-status and index (except for tooBig errors) ...\r
115  */\r
116 err_t\r
117 snmp_send_response(struct snmp_msg_pstat *m_stat)\r
118 {\r
119   struct snmp_varbind_root emptyvb = {NULL, NULL, 0, 0, 0};\r
120   struct pbuf *p;\r
121   u16_t tot_len;\r
122   err_t err;\r
123 \r
124   /* pass 0, calculate length fields */\r
125   tot_len = snmp_varbind_list_sum(&m_stat->outvb);\r
126   tot_len = snmp_resp_header_sum(m_stat, tot_len);\r
127 \r
128   /* try allocating pbuf(s) for complete response */\r
129   p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL);\r
130   if (p == NULL)\r
131   {\r
132     LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() tooBig\n"));\r
133 \r
134     /* can't construct reply, return error-status tooBig */\r
135     m_stat->error_status = SNMP_ES_TOOBIG;\r
136     m_stat->error_index = 0;\r
137     /* pass 0, recalculate lengths, for empty varbind-list */\r
138     tot_len = snmp_varbind_list_sum(&emptyvb);\r
139     tot_len = snmp_resp_header_sum(m_stat, tot_len);\r
140     /* retry allocation once for header and empty varbind-list */\r
141     p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL);\r
142   }\r
143   if (p != NULL)\r
144   {\r
145     /* first pbuf alloc try or retry alloc success */\r
146     u16_t ofs;\r
147 \r
148     LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() p != NULL\n"));\r
149 \r
150     /* pass 1, size error, encode packet ino the pbuf(s) */\r
151     ofs = snmp_resp_header_enc(m_stat, p);\r
152     if (m_stat->error_status == SNMP_ES_TOOBIG)\r
153     {\r
154       snmp_varbind_list_enc(&emptyvb, p, ofs);\r
155     }\r
156     else\r
157     {\r
158       snmp_varbind_list_enc(&m_stat->outvb, p, ofs);\r
159     }\r
160 \r
161     switch (m_stat->error_status)\r
162     {\r
163       case SNMP_ES_TOOBIG:\r
164         snmp_inc_snmpouttoobigs();\r
165         break;\r
166       case SNMP_ES_NOSUCHNAME:\r
167         snmp_inc_snmpoutnosuchnames();\r
168         break;\r
169       case SNMP_ES_BADVALUE:\r
170         snmp_inc_snmpoutbadvalues();\r
171         break;\r
172       case SNMP_ES_GENERROR:\r
173         snmp_inc_snmpoutgenerrs();\r
174         break;\r
175     }\r
176     snmp_inc_snmpoutgetresponses();\r
177     snmp_inc_snmpoutpkts();\r
178 \r
179     /** @todo do we need separate rx and tx pcbs for threaded case? */\r
180     /** connect to the originating source */\r
181     udp_connect(m_stat->pcb, &m_stat->sip, m_stat->sp);\r
182     err = udp_send(m_stat->pcb, p);\r
183     if (err == ERR_MEM)\r
184     {\r
185       /** @todo release some memory, retry and return tooBig? tooMuchHassle? */\r
186       err = ERR_MEM;\r
187     }\r
188     else\r
189     {\r
190       err = ERR_OK;\r
191     }\r
192     /** disassociate remote address and port with this pcb */\r
193     udp_disconnect(m_stat->pcb);\r
194 \r
195     pbuf_free(p);\r
196     LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() done\n"));\r
197     return err;\r
198   }\r
199   else\r
200   {\r
201     /* first pbuf alloc try or retry alloc failed\r
202        very low on memory, couldn't return tooBig */\r
203     return ERR_MEM;\r
204   }\r
205 }\r
206 \r
207 \r
208 /**\r
209  * Sends an generic or enterprise specific trap message.\r
210  *\r
211  * @param generic_trap is the trap code\r
212  * @param eoid points to enterprise object identifier\r
213  * @param specific_trap used for enterprise traps when generic_trap == 6\r
214  * @return ERR_OK when success, ERR_MEM if we're out of memory\r
215  *\r
216  * @note the caller is responsible for filling in outvb in the trap_msg\r
217  * @note the use of the enterpise identifier field\r
218  * is per RFC1215.\r
219  * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps\r
220  * and .iso.org.dod.internet.private.enterprises.yourenterprise\r
221  * (sysObjectID) for specific traps.\r
222  */\r
223 err_t\r
224 snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap)\r
225 {\r
226   struct snmp_trap_dst *td;\r
227   struct netif *dst_if;\r
228   struct ip_addr dst_ip;\r
229   struct pbuf *p;\r
230   u16_t i,tot_len;\r
231 \r
232   for (i=0, td = &trap_dst[0]; i<SNMP_TRAP_DESTINATIONS; i++, td++)\r
233   {\r
234     if ((td->enable != 0) && (td->dip.addr != 0))\r
235     {\r
236       /* network order trap destination */\r
237       trap_msg.dip.addr = td->dip.addr;\r
238       /* lookup current source address for this dst */\r
239       dst_if = ip_route(&td->dip);\r
240       dst_ip.addr = ntohl(dst_if->ip_addr.addr);\r
241       trap_msg.sip_raw[0] = dst_ip.addr >> 24;\r
242       trap_msg.sip_raw[1] = dst_ip.addr >> 16;\r
243       trap_msg.sip_raw[2] = dst_ip.addr >> 8;\r
244       trap_msg.sip_raw[3] = dst_ip.addr;\r
245       trap_msg.gen_trap = generic_trap;\r
246       trap_msg.spc_trap = specific_trap;\r
247       if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC)\r
248       {\r
249         /* enterprise-Specific trap */\r
250         trap_msg.enterprise = eoid;\r
251       }\r
252       else\r
253       {\r
254         /* generic (MIB-II) trap */\r
255         snmp_get_snmpgrpid_ptr(&trap_msg.enterprise);\r
256       }\r
257       snmp_get_sysuptime(&trap_msg.ts);\r
258 \r
259       /* pass 0, calculate length fields */\r
260       tot_len = snmp_varbind_list_sum(&trap_msg.outvb);\r
261       tot_len = snmp_trap_header_sum(&trap_msg, tot_len);\r
262 \r
263       /* allocate pbuf(s) */\r
264       p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL);\r
265       if (p != NULL)\r
266       {\r
267         u16_t ofs;\r
268 \r
269         /* pass 1, encode packet ino the pbuf(s) */\r
270         ofs = snmp_trap_header_enc(&trap_msg, p);\r
271         snmp_varbind_list_enc(&trap_msg.outvb, p, ofs);\r
272 \r
273         snmp_inc_snmpouttraps();\r
274         snmp_inc_snmpoutpkts();\r
275 \r
276         /** connect to the TRAP destination */\r
277         udp_connect(trap_msg.pcb, &trap_msg.dip, SNMP_TRAP_PORT);\r
278         udp_send(trap_msg.pcb, p);\r
279         /** disassociate remote address and port with this pcb */\r
280         udp_disconnect(trap_msg.pcb);\r
281 \r
282         pbuf_free(p);\r
283       }\r
284       else\r
285       {\r
286         return ERR_MEM;\r
287       }\r
288     }\r
289   }\r
290   return ERR_OK;\r
291 }\r
292 \r
293 void\r
294 snmp_coldstart_trap(void)\r
295 {\r
296   trap_msg.outvb.head = NULL;\r
297   trap_msg.outvb.tail = NULL;\r
298   trap_msg.outvb.count = 0;\r
299   snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0);\r
300 }\r
301 \r
302 void\r
303 snmp_authfail_trap(void)\r
304 {\r
305   u8_t enable;\r
306   snmp_get_snmpenableauthentraps(&enable);\r
307   if (enable == 1)\r
308   {\r
309     trap_msg.outvb.head = NULL;\r
310     trap_msg.outvb.tail = NULL;\r
311     trap_msg.outvb.count = 0;\r
312     snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0);\r
313   }\r
314 }\r
315 \r
316 /**\r
317  * Sums response header field lengths from tail to head and\r
318  * returns resp_header_lengths for second encoding pass.\r
319  *\r
320  * @param vb_len varbind-list length\r
321  * @param rhl points to returned header lengths\r
322  * @return the required lenght for encoding the response header\r
323  */\r
324 static u16_t\r
325 snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len)\r
326 {\r
327   u16_t tot_len;\r
328   struct snmp_resp_header_lengths *rhl;\r
329 \r
330   rhl = &m_stat->rhl;\r
331   tot_len = vb_len;\r
332   snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen);\r
333   snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen);\r
334   tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen;\r
335 \r
336   snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen);\r
337   snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen);\r
338   tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen;\r
339 \r
340   snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen);\r
341   snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen);\r
342   tot_len += 1 + rhl->ridlenlen + rhl->ridlen;\r
343 \r
344   rhl->pdulen = tot_len;\r
345   snmp_asn1_enc_length_cnt(rhl->pdulen, &rhl->pdulenlen);\r
346   tot_len += 1 + rhl->pdulenlen;\r
347 \r
348   rhl->comlen = m_stat->com_strlen;\r
349   snmp_asn1_enc_length_cnt(rhl->comlen, &rhl->comlenlen);\r
350   tot_len += 1 + rhl->comlenlen + rhl->comlen;\r
351 \r
352   snmp_asn1_enc_s32t_cnt(snmp_version, &rhl->verlen);\r
353   snmp_asn1_enc_length_cnt(rhl->verlen, &rhl->verlenlen);\r
354   tot_len += 1 + rhl->verlen + rhl->verlenlen;\r
355 \r
356   rhl->seqlen = tot_len;\r
357   snmp_asn1_enc_length_cnt(rhl->seqlen, &rhl->seqlenlen);\r
358   tot_len += 1 + rhl->seqlenlen;\r
359 \r
360   return tot_len;\r
361 }\r
362 \r
363 /**\r
364  * Sums trap header field lengths from tail to head and\r
365  * returns trap_header_lengths for second encoding pass.\r
366  *\r
367  * @param vb_len varbind-list length\r
368  * @param thl points to returned header lengths\r
369  * @return the required lenght for encoding the trap header\r
370  */\r
371 static u16_t\r
372 snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len)\r
373 {\r
374   u16_t tot_len;\r
375   struct snmp_trap_header_lengths *thl;\r
376 \r
377   thl = &m_trap->thl;\r
378   tot_len = vb_len;\r
379 \r
380   snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen);\r
381   snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen);\r
382   tot_len += 1 + thl->tslen + thl->tslenlen;\r
383 \r
384   snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen);\r
385   snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen);\r
386   tot_len += 1 + thl->strplen + thl->strplenlen;\r
387 \r
388   snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen);\r
389   snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen);\r
390   tot_len += 1 + thl->gtrplen + thl->gtrplenlen;\r
391 \r
392   thl->aaddrlen = 4;\r
393   snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen);\r
394   tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen;\r
395 \r
396   snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen);\r
397   snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen);\r
398   tot_len += 1 + thl->eidlen + thl->eidlenlen;\r
399 \r
400   thl->pdulen = tot_len;\r
401   snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen);\r
402   tot_len += 1 + thl->pdulenlen;\r
403 \r
404   thl->comlen = sizeof(snmp_publiccommunity) - 1;\r
405   snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen);\r
406   tot_len += 1 + thl->comlenlen + thl->comlen;\r
407 \r
408   snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen);\r
409   snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen);\r
410   tot_len += 1 + thl->verlen + thl->verlenlen;\r
411 \r
412   thl->seqlen = tot_len;\r
413   snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen);\r
414   tot_len += 1 + thl->seqlenlen;\r
415 \r
416   return tot_len;\r
417 }\r
418 \r
419 /**\r
420  * Sums varbind lengths from tail to head and\r
421  * annotates lengths in varbind for second encoding pass.\r
422  *\r
423  * @param root points to the root of the variable binding list\r
424  * @return the required lenght for encoding the variable bindings\r
425  */\r
426 static u16_t\r
427 snmp_varbind_list_sum(struct snmp_varbind_root *root)\r
428 {\r
429   struct snmp_varbind *vb;\r
430   u32_t *uint_ptr;\r
431   s32_t *sint_ptr;\r
432   u16_t tot_len;\r
433 \r
434   tot_len = 0;\r
435   vb = root->tail;\r
436   while ( vb != NULL )\r
437   {\r
438     /* encoded value lenght depends on type */\r
439     switch (vb->value_type)\r
440     {\r
441       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):\r
442         sint_ptr = vb->value;\r
443         snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen);\r
444         break;\r
445       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):\r
446       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):\r
447       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):\r
448         uint_ptr = vb->value;\r
449         snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen);\r
450         break;\r
451       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):\r
452       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):\r
453       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):\r
454       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):\r
455         vb->vlen = vb->value_len;\r
456         break;\r
457       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):\r
458         sint_ptr = vb->value;\r
459         snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen);\r
460         break;\r
461       default:\r
462         /* unsupported type */\r
463         vb->vlen = 0;\r
464         break;\r
465     };\r
466     /* encoding length of value length field */\r
467     snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen);\r
468     snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen);\r
469     snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen);\r
470 \r
471     vb->seqlen = 1 + vb->vlenlen + vb->vlen;\r
472     vb->seqlen += 1 + vb->olenlen + vb->olen;\r
473     snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen);\r
474 \r
475     /* varbind seq */\r
476     tot_len += 1 + vb->seqlenlen + vb->seqlen;\r
477 \r
478     vb = vb->prev;\r
479   }\r
480 \r
481   /* varbind-list seq */\r
482   root->seqlen = tot_len;\r
483   snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen);\r
484   tot_len += 1 + root->seqlenlen;\r
485 \r
486   return tot_len;\r
487 }\r
488 \r
489 /**\r
490  * Encodes response header from head to tail.\r
491  */\r
492 static u16_t\r
493 snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p)\r
494 {\r
495   u16_t ofs;\r
496 \r
497   ofs = 0;\r
498   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));\r
499   ofs += 1;\r
500   snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen);\r
501   ofs += m_stat->rhl.seqlenlen;\r
502 \r
503   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));\r
504   ofs += 1;\r
505   snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen);\r
506   ofs += m_stat->rhl.verlenlen;\r
507   snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_version);\r
508   ofs += m_stat->rhl.verlen;\r
509 \r
510   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR));\r
511   ofs += 1;\r
512   snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen);\r
513   ofs += m_stat->rhl.comlenlen;\r
514   snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community);\r
515   ofs += m_stat->rhl.comlen;\r
516 \r
517   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP));\r
518   ofs += 1;\r
519   snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen);\r
520   ofs += m_stat->rhl.pdulenlen;\r
521 \r
522   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));\r
523   ofs += 1;\r
524   snmp_asn1_enc_length(p, ofs, m_stat->rhl.ridlen);\r
525   ofs += m_stat->rhl.ridlenlen;\r
526   snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid);\r
527   ofs += m_stat->rhl.ridlen;\r
528 \r
529   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));\r
530   ofs += 1;\r
531   snmp_asn1_enc_length(p, ofs, m_stat->rhl.errstatlen);\r
532   ofs += m_stat->rhl.errstatlenlen;\r
533   snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status);\r
534   ofs += m_stat->rhl.errstatlen;\r
535 \r
536   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));\r
537   ofs += 1;\r
538   snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen);\r
539   ofs += m_stat->rhl.erridxlenlen;\r
540   snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index);\r
541   ofs += m_stat->rhl.erridxlen;\r
542 \r
543   return ofs;\r
544 }\r
545 \r
546 /**\r
547  * Encodes trap header from head to tail.\r
548  */\r
549 static u16_t\r
550 snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p)\r
551 {\r
552   u16_t ofs;\r
553 \r
554   ofs = 0;\r
555   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));\r
556   ofs += 1;\r
557   snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen);\r
558   ofs += m_trap->thl.seqlenlen;\r
559 \r
560   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));\r
561   ofs += 1;\r
562   snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen);\r
563   ofs += m_trap->thl.verlenlen;\r
564   snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version);\r
565   ofs += m_trap->thl.verlen;\r
566 \r
567   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR));\r
568   ofs += 1;\r
569   snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen);\r
570   ofs += m_trap->thl.comlenlen;\r
571   snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]);\r
572   ofs += m_trap->thl.comlen;\r
573 \r
574   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP));\r
575   ofs += 1;\r
576   snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen);\r
577   ofs += m_trap->thl.pdulenlen;\r
578 \r
579   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID));\r
580   ofs += 1;\r
581   snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen);\r
582   ofs += m_trap->thl.eidlenlen;\r
583   snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]);\r
584   ofs += m_trap->thl.eidlen;\r
585 \r
586   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR));\r
587   ofs += 1;\r
588   snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen);\r
589   ofs += m_trap->thl.aaddrlenlen;\r
590   snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]);\r
591   ofs += m_trap->thl.aaddrlen;\r
592 \r
593   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));\r
594   ofs += 1;\r
595   snmp_asn1_enc_length(p, ofs, m_trap->thl.gtrplen);\r
596   ofs += m_trap->thl.gtrplenlen;\r
597   snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap);\r
598   ofs += m_trap->thl.gtrplen;\r
599 \r
600   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));\r
601   ofs += 1;\r
602   snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen);\r
603   ofs += m_trap->thl.strplenlen;\r
604   snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap);\r
605   ofs += m_trap->thl.strplen;\r
606 \r
607   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS));\r
608   ofs += 1;\r
609   snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen);\r
610   ofs += m_trap->thl.tslenlen;\r
611   snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts);\r
612   ofs += m_trap->thl.tslen;\r
613 \r
614   return ofs;\r
615 }\r
616 \r
617 /**\r
618  * Encodes varbind list from head to tail.\r
619  */\r
620 static u16_t\r
621 snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs)\r
622 {\r
623   struct snmp_varbind *vb;\r
624   s32_t *sint_ptr;\r
625   u32_t *uint_ptr;\r
626   u8_t *raw_ptr;\r
627 \r
628   snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));\r
629   ofs += 1;\r
630   snmp_asn1_enc_length(p, ofs, root->seqlen);\r
631   ofs += root->seqlenlen;\r
632 \r
633   vb = root->head;\r
634   while ( vb != NULL )\r
635   {\r
636     snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));\r
637     ofs += 1;\r
638     snmp_asn1_enc_length(p, ofs, vb->seqlen);\r
639     ofs += vb->seqlenlen;\r
640 \r
641     snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID));\r
642     ofs += 1;\r
643     snmp_asn1_enc_length(p, ofs, vb->olen);\r
644     ofs += vb->olenlen;\r
645     snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]);\r
646     ofs += vb->olen;\r
647 \r
648     snmp_asn1_enc_type(p, ofs, vb->value_type);\r
649     ofs += 1;\r
650     snmp_asn1_enc_length(p, ofs, vb->vlen);\r
651     ofs += vb->vlenlen;\r
652 \r
653     switch (vb->value_type)\r
654     {\r
655       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):\r
656         sint_ptr = vb->value;\r
657         snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr);\r
658         break;\r
659       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):\r
660       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):\r
661       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):\r
662         uint_ptr = vb->value;\r
663         snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr);\r
664         break;\r
665       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):\r
666       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):\r
667       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):\r
668         raw_ptr = vb->value;\r
669         snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr);\r
670         break;\r
671       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):\r
672         break;\r
673       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):\r
674         sint_ptr = vb->value;\r
675         snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr);\r
676         break;\r
677       default:\r
678         /* unsupported type */\r
679         break;\r
680     };\r
681     ofs += vb->vlen;\r
682     vb = vb->next;\r
683   }\r
684   return ofs;\r
685 }\r
686 \r
687 #endif /* LWIP_SNMP */\r