uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
asn1_enc.c
Go to the documentation of this file.
1 
8 /*
9  * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without modification,
13  * are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  * this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright notice,
18  * this list of conditions and the following disclaimer in the documentation
19  * and/or other materials provided with the distribution.
20  * 3. The name of the author may not be used to endorse or promote products
21  * derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
26  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
28  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
31  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32  * OF SUCH DAMAGE.
33  *
34  * Author: Christiaan Simons <christiaan.simons@axon.tv>
35  */
36 
37 #include "lwip/opt.h"
38 
39 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
40 
41 #include "lwip/snmp_asn1.h"
42 
49 void
50 snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed)
51 {
52  if (length < 0x80U)
53  {
54  *octets_needed = 1;
55  }
56  else if (length < 0x100U)
57  {
58  *octets_needed = 2;
59  }
60  else
61  {
62  *octets_needed = 3;
63  }
64 }
65 
76 void
77 snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed)
78 {
79  if (value < 0x80UL)
80  {
81  *octets_needed = 1;
82  }
83  else if (value < 0x8000UL)
84  {
85  *octets_needed = 2;
86  }
87  else if (value < 0x800000UL)
88  {
89  *octets_needed = 3;
90  }
91  else if (value < 0x80000000UL)
92  {
93  *octets_needed = 4;
94  }
95  else
96  {
97  *octets_needed = 5;
98  }
99 }
100 
109 void
110 snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed)
111 {
112  if (value < 0)
113  {
114  value = ~value;
115  }
116  if (value < 0x80L)
117  {
118  *octets_needed = 1;
119  }
120  else if (value < 0x8000L)
121  {
122  *octets_needed = 2;
123  }
124  else if (value < 0x800000L)
125  {
126  *octets_needed = 3;
127  }
128  else
129  {
130  *octets_needed = 4;
131  }
132 }
133 
141 void
142 snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed)
143 {
144  s32_t sub_id;
145  u8_t cnt;
146 
147  cnt = 0;
148  if (ident_len > 1)
149  {
150  /* compressed prefix in one octet */
151  cnt++;
152  ident_len -= 2;
153  ident += 2;
154  }
155  while(ident_len > 0)
156  {
157  ident_len--;
158  sub_id = *ident;
159 
160  sub_id >>= 7;
161  cnt++;
162  while(sub_id > 0)
163  {
164  sub_id >>= 7;
165  cnt++;
166  }
167  ident++;
168  }
169  *octets_needed = cnt;
170 }
171 
180 err_t
181 snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type)
182 {
183  u16_t plen, base;
184  u8_t *msg_ptr;
185 
186  plen = 0;
187  while (p != NULL)
188  {
189  base = plen;
190  plen += p->len;
191  if (ofs < plen)
192  {
193  msg_ptr = (u8_t*)p->payload;
194  msg_ptr += ofs - base;
195  *msg_ptr = type;
196  return ERR_OK;
197  }
198  p = p->next;
199  }
200  /* p == NULL, ofs >= plen */
201  return ERR_ARG;
202 }
203 
212 err_t
213 snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
214 {
215  u16_t plen, base;
216  u8_t *msg_ptr;
217 
218  plen = 0;
219  while (p != NULL)
220  {
221  base = plen;
222  plen += p->len;
223  if (ofs < plen)
224  {
225  msg_ptr = (u8_t*)p->payload;
226  msg_ptr += ofs - base;
227 
228  if (length < 0x80)
229  {
230  *msg_ptr = (u8_t)length;
231  return ERR_OK;
232  }
233  else if (length < 0x100)
234  {
235  *msg_ptr = 0x81;
236  ofs += 1;
237  if (ofs >= plen)
238  {
239  /* next octet in next pbuf */
240  p = p->next;
241  if (p == NULL) { return ERR_ARG; }
242  msg_ptr = (u8_t*)p->payload;
243  }
244  else
245  {
246  /* next octet in same pbuf */
247  msg_ptr++;
248  }
249  *msg_ptr = (u8_t)length;
250  return ERR_OK;
251  }
252  else
253  {
254  u8_t i;
255 
256  /* length >= 0x100 && length <= 0xFFFF */
257  *msg_ptr = 0x82;
258  i = 2;
259  while (i > 0)
260  {
261  i--;
262  ofs += 1;
263  if (ofs >= plen)
264  {
265  /* next octet in next pbuf */
266  p = p->next;
267  if (p == NULL) { return ERR_ARG; }
268  msg_ptr = (u8_t*)p->payload;
269  plen += p->len;
270  }
271  else
272  {
273  /* next octet in same pbuf */
274  msg_ptr++;
275  }
276  if (i == 0)
277  {
278  /* least significant length octet */
279  *msg_ptr = (u8_t)length;
280  }
281  else
282  {
283  /* most significant length octet */
284  *msg_ptr = (u8_t)(length >> 8);
285  }
286  }
287  return ERR_OK;
288  }
289  }
290  p = p->next;
291  }
292  /* p == NULL, ofs >= plen */
293  return ERR_ARG;
294 }
295 
307 err_t
308 snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value)
309 {
310  u16_t plen, base;
311  u8_t *msg_ptr;
312 
313  plen = 0;
314  while (p != NULL)
315  {
316  base = plen;
317  plen += p->len;
318  if (ofs < plen)
319  {
320  msg_ptr = (u8_t*)p->payload;
321  msg_ptr += ofs - base;
322 
323  if (octets_needed == 5)
324  {
325  /* not enough bits in 'value' add leading 0x00 */
326  octets_needed--;
327  *msg_ptr = 0x00;
328  ofs += 1;
329  if (ofs >= plen)
330  {
331  /* next octet in next pbuf */
332  p = p->next;
333  if (p == NULL) { return ERR_ARG; }
334  msg_ptr = (u8_t*)p->payload;
335  plen += p->len;
336  }
337  else
338  {
339  /* next octet in same pbuf */
340  msg_ptr++;
341  }
342  }
343  while (octets_needed > 1)
344  {
345  octets_needed--;
346  *msg_ptr = (u8_t)(value >> (octets_needed << 3));
347  ofs += 1;
348  if (ofs >= plen)
349  {
350  /* next octet in next pbuf */
351  p = p->next;
352  if (p == NULL) { return ERR_ARG; }
353  msg_ptr = (u8_t*)p->payload;
354  plen += p->len;
355  }
356  else
357  {
358  /* next octet in same pbuf */
359  msg_ptr++;
360  }
361  }
362  /* (only) one least significant octet */
363  *msg_ptr = (u8_t)value;
364  return ERR_OK;
365  }
366  p = p->next;
367  }
368  /* p == NULL, ofs >= plen */
369  return ERR_ARG;
370 }
371 
383 err_t
384 snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value)
385 {
386  u16_t plen, base;
387  u8_t *msg_ptr;
388 
389  plen = 0;
390  while (p != NULL)
391  {
392  base = plen;
393  plen += p->len;
394  if (ofs < plen)
395  {
396  msg_ptr = (u8_t*)p->payload;
397  msg_ptr += ofs - base;
398 
399  while (octets_needed > 1)
400  {
401  octets_needed--;
402  *msg_ptr = (u8_t)(value >> (octets_needed << 3));
403  ofs += 1;
404  if (ofs >= plen)
405  {
406  /* next octet in next pbuf */
407  p = p->next;
408  if (p == NULL) { return ERR_ARG; }
409  msg_ptr = (u8_t*)p->payload;
410  plen += p->len;
411  }
412  else
413  {
414  /* next octet in same pbuf */
415  msg_ptr++;
416  }
417  }
418  /* (only) one least significant octet */
419  *msg_ptr = (u8_t)value;
420  return ERR_OK;
421  }
422  p = p->next;
423  }
424  /* p == NULL, ofs >= plen */
425  return ERR_ARG;
426 }
427 
437 err_t
438 snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
439 {
440  u16_t plen, base;
441  u8_t *msg_ptr;
442 
443  plen = 0;
444  while (p != NULL)
445  {
446  base = plen;
447  plen += p->len;
448  if (ofs < plen)
449  {
450  msg_ptr = (u8_t*)p->payload;
451  msg_ptr += ofs - base;
452 
453  if (ident_len > 1)
454  {
455  if ((ident[0] == 1) && (ident[1] == 3))
456  {
457  /* compressed (most common) prefix .iso.org */
458  *msg_ptr = 0x2b;
459  }
460  else
461  {
462  /* calculate prefix */
463  *msg_ptr = (u8_t)((ident[0] * 40) + ident[1]);
464  }
465  ofs += 1;
466  if (ofs >= plen)
467  {
468  /* next octet in next pbuf */
469  p = p->next;
470  if (p == NULL) { return ERR_ARG; }
471  msg_ptr = (u8_t*)p->payload;
472  plen += p->len;
473  }
474  else
475  {
476  /* next octet in same pbuf */
477  msg_ptr++;
478  }
479  ident_len -= 2;
480  ident += 2;
481  }
482  else
483  {
484 /* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */
485  /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */
486  return ERR_ARG;
487  }
488  while (ident_len > 0)
489  {
490  s32_t sub_id;
491  u8_t shift, tail;
492 
493  ident_len--;
494  sub_id = *ident;
495  tail = 0;
496  shift = 28;
497  while(shift > 0)
498  {
499  u8_t code;
500 
501  code = (u8_t)(sub_id >> shift);
502  if ((code != 0) || (tail != 0))
503  {
504  tail = 1;
505  *msg_ptr = code | 0x80;
506  ofs += 1;
507  if (ofs >= plen)
508  {
509  /* next octet in next pbuf */
510  p = p->next;
511  if (p == NULL) { return ERR_ARG; }
512  msg_ptr = (u8_t*)p->payload;
513  plen += p->len;
514  }
515  else
516  {
517  /* next octet in same pbuf */
518  msg_ptr++;
519  }
520  }
521  shift -= 7;
522  }
523  *msg_ptr = (u8_t)sub_id & 0x7F;
524  if (ident_len > 0)
525  {
526  ofs += 1;
527  if (ofs >= plen)
528  {
529  /* next octet in next pbuf */
530  p = p->next;
531  if (p == NULL) { return ERR_ARG; }
532  msg_ptr = (u8_t*)p->payload;
533  plen += p->len;
534  }
535  else
536  {
537  /* next octet in same pbuf */
538  msg_ptr++;
539  }
540  }
541  /* proceed to next sub-identifier */
542  ident++;
543  }
544  return ERR_OK;
545  }
546  p = p->next;
547  }
548  /* p == NULL, ofs >= plen */
549  return ERR_ARG;
550 }
551 
561 err_t
562 snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw)
563 {
564  u16_t plen, base;
565  u8_t *msg_ptr;
566 
567  plen = 0;
568  while (p != NULL)
569  {
570  base = plen;
571  plen += p->len;
572  if (ofs < plen)
573  {
574  msg_ptr = (u8_t*)p->payload;
575  msg_ptr += ofs - base;
576 
577  while (raw_len > 1)
578  {
579  /* copy raw_len - 1 octets */
580  raw_len--;
581  *msg_ptr = *raw;
582  raw++;
583  ofs += 1;
584  if (ofs >= plen)
585  {
586  /* next octet in next pbuf */
587  p = p->next;
588  if (p == NULL) { return ERR_ARG; }
589  msg_ptr = (u8_t*)p->payload;
590  plen += p->len;
591  }
592  else
593  {
594  /* next octet in same pbuf */
595  msg_ptr++;
596  }
597  }
598  if (raw_len > 0)
599  {
600  /* copy last or single octet */
601  *msg_ptr = *raw;
602  }
603  return ERR_OK;
604  }
605  p = p->next;
606  }
607  /* p == NULL, ofs >= plen */
608  return ERR_ARG;
609 }
610 
611 #endif /* LWIP_SNMP */