Contiki-NG
snmp-ber.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019 Yago Fontoura do Rosario <yago.rosario@hotmail.com.br>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 /*---------------------------------------------------------------------------*/
32 
33 /**
34  * \file
35  * An implementation of the Simple Network Management Protocol (RFC 3411-3418)
36  * \author
37  * Yago Fontoura do Rosario <yago.rosario@hotmail.com.br
38  */
39 
40 #include "contiki.h"
41 
42 #include "snmp.h"
43 #include "snmp-ber.h"
44 
45 #define LOG_MODULE "SNMP [ber]"
46 #define LOG_LEVEL LOG_LEVEL_SNMP
47 
48 /*---------------------------------------------------------------------------*/
49 unsigned char *
50 snmp_ber_encode_type(unsigned char *out, uint32_t *out_len, uint8_t type)
51 {
52  *out-- = type;
53  (*out_len)++;
54  return out;
55 }
56 /*---------------------------------------------------------------------------*/
57 unsigned char *
58 snmp_ber_encode_length(unsigned char *out, uint32_t *out_len, uint8_t length)
59 {
60  *out-- = length;
61  (*out_len)++;
62  return out;
63 }
64 /*---------------------------------------------------------------------------*/
65 unsigned char *
66 snmp_ber_encode_integer(unsigned char *out, uint32_t *out_len, uint32_t number)
67 {
68  uint32_t original_out_len;
69 
70  original_out_len = *out_len;
71  do {
72  (*out_len)++;
73  *out-- = (uint8_t)(number & 0xFF);
74  number >>= 8;
75  } while(number);
76 
77  out = snmp_ber_encode_length(out, out_len, ((*out_len - original_out_len) & 0xFF));
78  out = snmp_ber_encode_type(out, out_len, BER_DATA_TYPE_INTEGER);
79 
80  return out;
81 }
82 /*---------------------------------------------------------------------------*/
83 unsigned char *
84 snmp_ber_encode_unsigned_integer(unsigned char *out, uint32_t *out_len, uint8_t type, uint32_t number)
85 {
86  uint32_t original_out_len;
87 
88  original_out_len = *out_len;
89  do {
90  (*out_len)++;
91  *out-- = (uint8_t)(number & 0xFF);
92  number >>= 8;
93  } while(number);
94 
95  out = snmp_ber_encode_length(out, out_len, ((*out_len - original_out_len) & 0xFF));
96  out = snmp_ber_encode_type(out, out_len, type);
97 
98  return out;
99 }
100 /*---------------------------------------------------------------------------*/
101 unsigned char *
102 snmp_ber_encode_string_len(unsigned char *out, uint32_t *out_len, const char *str, uint32_t length)
103 {
104  uint32_t i;
105 
106  str += length - 1;
107  for(i = 0; i < length; ++i) {
108  (*out_len)++;
109  *out-- = (uint8_t)*str--;
110  }
111 
112  out = snmp_ber_encode_length(out, out_len, length);
113  out = snmp_ber_encode_type(out, out_len, BER_DATA_TYPE_OCTET_STRING);
114 
115  return out;
116 }
117 /*---------------------------------------------------------------------------*/
118 unsigned char *
119 snmp_ber_encode_null(unsigned char *out, uint32_t *out_len, uint8_t type)
120 {
121  (*out_len)++;
122  *out-- = 0x00;
123  out = snmp_ber_encode_type(out, out_len, type);
124 
125  return out;
126 }
127 /*---------------------------------------------------------------------------*/
128 unsigned char *
129 snmp_ber_decode_type(unsigned char *buff, uint32_t *buff_len, uint8_t *type)
130 {
131  *type = *buff++;
132  (*buff_len)--;
133 
134  return buff;
135 }
136 /*---------------------------------------------------------------------------*/
137 unsigned char *
138 snmp_ber_decode_length(unsigned char *buff, uint32_t *buff_len, uint8_t *length)
139 {
140  *length = *buff++;
141  (*buff_len)--;
142 
143  return buff;
144 }
145 /*---------------------------------------------------------------------------*/
146 unsigned char *
147 snmp_ber_decode_integer(unsigned char *buf, uint32_t *buff_len, uint32_t *num)
148 {
149  uint8_t i, len, type;
150 
151  buf = snmp_ber_decode_type(buf, buff_len, &type);
152 
153  if(type != BER_DATA_TYPE_INTEGER) {
154  /*
155  * Sanity check
156  * Invalid type in buffer
157  */
158  return NULL;
159  }
160 
161  buf = snmp_ber_decode_length(buf, buff_len, &len);
162 
163  if(len > 4) {
164  /*
165  * Sanity check
166  * It will not fit in the uint32_t
167  */
168  return NULL;
169  }
170 
171  *num = (uint32_t)(*buf++ & 0xFF);
172  (*buff_len)--;
173  for(i = 1; i < len; ++i) {
174  *num <<= 8;
175  *num |= (uint8_t)(*buf++ & 0xFF);
176  (*buff_len)--;
177  }
178 
179  return buf;
180 }
181 /*---------------------------------------------------------------------------*/
182 unsigned char *
183 snmp_ber_decode_unsigned_integer(unsigned char *buf, uint32_t *buff_len, uint8_t expected_type, uint32_t *num)
184 {
185  uint8_t i, len, type;
186 
187  buf = snmp_ber_decode_type(buf, buff_len, &type);
188 
189  if(type != expected_type) {
190  /*
191  * Sanity check
192  * Invalid type in buffer
193  */
194  return NULL;
195  }
196 
197  buf = snmp_ber_decode_length(buf, buff_len, &len);
198 
199  if(len > 4) {
200  /*
201  * Sanity check
202  * It will not fit in the uint32_t
203  */
204  return NULL;
205  }
206 
207  *num = (uint32_t)(*buf++ & 0xFF);
208  (*buff_len)--;
209  for(i = 1; i < len; ++i) {
210  *num <<= 8;
211  *num |= (uint8_t)(*buf++ & 0xFF);
212  (*buff_len)--;
213  }
214 
215  return buf;
216 }
217 /*---------------------------------------------------------------------------*/
218 unsigned char *
219 snmp_ber_decode_string_len_buffer(unsigned char *buf, uint32_t *buff_len, const char **str, uint32_t *length)
220 {
221  uint8_t type, i, length_bytes;
222 
223  buf = snmp_ber_decode_type(buf, buff_len, &type);
224 
225  if(type != BER_DATA_TYPE_OCTET_STRING) {
226  /*
227  * Sanity check
228  * Invalid type in buffer
229  */
230  return NULL;
231  }
232 
233  if((*buf & 0x80) == 0) {
234  *length = (uint32_t)*buf++;
235  (*buff_len)--;
236  } else {
237 
238  length_bytes = (uint8_t)(*buf++ & 0x7F);
239  (*buff_len)--;
240  if(length_bytes > 4) {
241  /*
242  * Sanity check
243  * It will not fit in the uint32_t
244  */
245  return NULL;
246  }
247 
248  *length = (uint32_t)*buf++;
249  (*buff_len)--;
250  for(i = 1; i < length_bytes; ++i) {
251  *length <<= 8;
252  *length |= *buf++;
253  (*buff_len)--;
254  }
255  }
256 
257  *str = (const char *)buf;
258  *buff_len -= *length;
259 
260  return buf + *length;
261 }
262 /*---------------------------------------------------------------------------*/
263 unsigned char *
264 snmp_ber_decode_null(unsigned char *buf, uint32_t *buff_len)
265 {
266  buf++;
267  (*buff_len)--;
268 
269  buf++;
270  (*buff_len)--;
271 
272  return buf;
273 }
274 /*---------------------------------------------------------------------------*/
unsigned char * snmp_ber_encode_string_len(unsigned char *out, uint32_t *out_len, const char *str, uint32_t length)
Encodes a string.
Definition: snmp-ber.c:102
An implementation of the Simple Network Management Protocol (RFC 3411-3418)
unsigned char * snmp_ber_decode_type(unsigned char *buff, uint32_t *buff_len, uint8_t *type)
Decodes a type.
Definition: snmp-ber.c:129
An implementation of the Simple Network Management Protocol (RFC 3411-3418)
unsigned char * snmp_ber_encode_null(unsigned char *out, uint32_t *out_len, uint8_t type)
Encodes a null.
Definition: snmp-ber.c:119
unsigned char * snmp_ber_decode_null(unsigned char *buf, uint32_t *buff_len)
Decodes a null.
Definition: snmp-ber.c:264
unsigned char * snmp_ber_encode_length(unsigned char *out, uint32_t *out_len, uint8_t length)
Encodes the length.
Definition: snmp-ber.c:58
unsigned char * snmp_ber_decode_length(unsigned char *buff, uint32_t *buff_len, uint8_t *length)
Decodes a length.
Definition: snmp-ber.c:138
unsigned char * snmp_ber_encode_integer(unsigned char *out, uint32_t *out_len, uint32_t number)
Encodes an integer.
Definition: snmp-ber.c:66
unsigned char * snmp_ber_decode_unsigned_integer(unsigned char *buf, uint32_t *buff_len, uint8_t expected_type, uint32_t *num)
Decodes an unsigned number.
Definition: snmp-ber.c:183
unsigned char * snmp_ber_encode_unsigned_integer(unsigned char *out, uint32_t *out_len, uint8_t type, uint32_t number)
Encodes an unsigned integer.
Definition: snmp-ber.c:84
unsigned char * snmp_ber_decode_integer(unsigned char *buf, uint32_t *buff_len, uint32_t *num)
Decodes an integer.
Definition: snmp-ber.c:147
unsigned char * snmp_ber_decode_string_len_buffer(unsigned char *buf, uint32_t *buff_len, const char **str, uint32_t *length)
Decodes a string.
Definition: snmp-ber.c:219
unsigned char * snmp_ber_encode_type(unsigned char *out, uint32_t *out_len, uint8_t type)
Encodes a type.
Definition: snmp-ber.c:50