Contiki-NG
snmp-message.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019-2020 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  * SNMP Implementation of the messages
36  * \author
37  * Yago Fontoura do Rosario <yago.rosario@hotmail.com.br
38  */
39 
40 #include "contiki.h"
41 
42 #include "snmp-message.h"
43 #include "snmp-ber.h"
44 
45 #define LOG_MODULE "SNMP [message]"
46 #define LOG_LEVEL LOG_LEVEL_SNMP
47 
48 int
50 {
51  uint32_t last_out_len;
52  int8_t i;
53 
54  for(i = SNMP_MAX_NR_VALUES - 1; i >= 0; i--) {
55  if(varbinds[i].value_type == BER_DATA_TYPE_EOC) {
56  continue;
57  }
58 
59  last_out_len = snmp_packet->used;
60 
61  switch(varbinds[i].value_type) {
63  if(!snmp_ber_encode_integer(snmp_packet, varbinds[i].value.integer)) {
64  LOG_DBG("Could not encode integer type\n");
65  return 0;
66  }
67  break;
69  if(!snmp_ber_encode_timeticks(snmp_packet, varbinds[i].value.integer)) {
70  LOG_DBG("Could not encode timeticks type\n");
71  return 0;
72  }
73  break;
75  if(!snmp_ber_encode_string_len(snmp_packet, varbinds[i].value.string.string, varbinds[i].value.string.length)) {
76  LOG_DBG("Could not encode octet string type\n");
77  return 0;
78  }
79  break;
81  if(!snmp_ber_encode_oid(snmp_packet, &varbinds[i].value.oid)) {
82  LOG_DBG("Could not encode oid type\n");
83  return 0;
84  }
85  break;
86  case BER_DATA_TYPE_NULL:
89  if(!snmp_ber_encode_null(snmp_packet, varbinds[i].value_type)) {
90  LOG_DBG("Could not encode null type\n");
91  return 0;
92  }
93  break;
94  default:
95  LOG_DBG("Could not encode invlid type\n");
96  return 0;
97  }
98 
99  if(!snmp_ber_encode_oid(snmp_packet, &varbinds[i].oid)) {
100  LOG_DBG("Could not encode oid\n");
101  return 0;
102  }
103 
104  if(!snmp_ber_encode_length(snmp_packet, (snmp_packet->used - last_out_len))) {
105  LOG_DBG("Could not encode length\n");
106  return 0;
107  }
108 
109  if(!snmp_ber_encode_type(snmp_packet, BER_DATA_TYPE_SEQUENCE)) {
110  LOG_DBG("Could not encode type\n");
111  return 0;
112  }
113  }
114 
115  if(!snmp_ber_encode_length(snmp_packet, snmp_packet->used)) {
116  LOG_DBG("Could not encode length\n");
117  return 0;
118  }
119  if(!snmp_ber_encode_type(snmp_packet, BER_DATA_TYPE_SEQUENCE)) {
120  LOG_DBG("Could not encode type\n");
121  return 0;
122  }
123 
124  switch(header->pdu_type) {
126  if(!snmp_ber_encode_integer(snmp_packet, header->max_repetitions)) {
127  LOG_DBG("Could not encode max repetition\n");
128  return 0;
129  }
130 
131  if(!snmp_ber_encode_integer(snmp_packet, header->non_repeaters)) {
132  LOG_DBG("Could not encode non repeaters\n");
133  return 0;
134  }
135  break;
136  default:
137  if(!snmp_ber_encode_integer(snmp_packet, header->error_index)) {
138  LOG_DBG("Could not encode error index\n");
139  return 0;
140  }
141 
142  if(!snmp_ber_encode_integer(snmp_packet, header->error_status)) {
143  LOG_DBG("Could not encode error status\n");
144  return 0;
145  }
146  break;
147  }
148 
149  if(!snmp_ber_encode_integer(snmp_packet, header->request_id)) {
150  LOG_DBG("Could not encode request id\n");
151  return 0;
152  }
153 
154  if(!snmp_ber_encode_length(snmp_packet, snmp_packet->used)) {
155  LOG_DBG("Could not encode length\n");
156  return 0;
157  }
158 
159  if(!snmp_ber_encode_type(snmp_packet, header->pdu_type)) {
160  LOG_DBG("Could not encode pdu type\n");
161  return 0;
162  }
163 
164  if(!snmp_ber_encode_string_len(snmp_packet, header->community.community, header->community.length)) {
165  LOG_DBG("Could not encode community\n");
166  return 0;
167  }
168 
169  if(!snmp_ber_encode_integer(snmp_packet, header->version)) {
170  LOG_DBG("Could not encode version\n");
171  return 0;
172  }
173 
174  if(!snmp_ber_encode_length(snmp_packet, snmp_packet->used)) {
175  LOG_DBG("Could not encode length\n");
176  return 0;
177  }
178 
179  if(!snmp_ber_encode_type(snmp_packet, BER_DATA_TYPE_SEQUENCE)) {
180  LOG_DBG("Could not encode type\n");
181  return 0;
182  }
183 
184  /* Move the pointer to the last position */
185  snmp_packet->out++;
186  return 1;
187 }
188 int
190 {
191  uint8_t type, len, i;
192 
193  if(!snmp_ber_decode_type(snmp_packet, &type)) {
194  LOG_DBG("Could not decode type\n");
195  return 0;
196  }
197 
198  if(type != BER_DATA_TYPE_SEQUENCE) {
199  LOG_DBG("Invalid type\n");
200  return 0;
201  }
202 
203  if(!snmp_ber_decode_length(snmp_packet, &len)) {
204  LOG_DBG("Could not decode length\n");
205  return 0;
206  }
207 
208  if(!snmp_ber_decode_integer(snmp_packet, &header->version)) {
209  LOG_DBG("Could not decode version\n");
210  return 0;
211  }
212 
213  switch(header->version) {
214  case SNMP_VERSION_1:
215  case SNMP_VERSION_2C:
216  break;
217  default:
218  LOG_DBG("Invalid version\n");
219  return 0;
220  }
221 
222  if(!snmp_ber_decode_string_len_buffer(snmp_packet, &header->community.community, &header->community.length)) {
223  LOG_DBG("Could not decode community\n");
224  return 0;
225  }
226 
227  if(!snmp_ber_decode_type(snmp_packet, &header->pdu_type)) {
228  LOG_DBG("Could not decode pdu type\n");
229  return 0;
230  }
231 
232  switch(header->pdu_type) {
238  break;
239  default:
240  LOG_DBG("Invalid version\n");
241  return 0;
242  }
243 
244  if(!snmp_ber_decode_length(snmp_packet, &len)) {
245  LOG_DBG("Could not decode length\n");
246  return 0;
247  }
248 
249  if(!snmp_ber_decode_integer(snmp_packet, &header->request_id)) {
250  LOG_DBG("Could not decode request id\n");
251  return 0;
252  }
253 
254  switch(header->pdu_type) {
256  if(!snmp_ber_decode_integer(snmp_packet, &header->non_repeaters)) {
257  LOG_DBG("Could not decode non repeaters\n");
258  return 0;
259  }
260 
261  if(!snmp_ber_decode_integer(snmp_packet, &header->max_repetitions)) {
262  LOG_DBG("Could not decode max repetition\n");
263  return 0;
264  }
265  break;
266  default:
267  if(!snmp_ber_decode_integer(snmp_packet, &header->error_status)) {
268  LOG_DBG("Could not decode error status\n");
269  return 0;
270  }
271 
272  if(!snmp_ber_decode_integer(snmp_packet, &header->error_index)) {
273  LOG_DBG("Could not decode error index\n");
274  return 0;
275  }
276  break;
277  }
278 
279  if(!snmp_ber_decode_type(snmp_packet, &type)) {
280  LOG_DBG("Could not decode type\n");
281  return 0;
282  }
283 
284  if(type != BER_DATA_TYPE_SEQUENCE) {
285  LOG_DBG("Invalid type\n");
286  return 0;
287  }
288 
289  if(!snmp_ber_decode_length(snmp_packet, &len)) {
290  LOG_DBG("Could not decode length\n");
291  return 0;
292  }
293 
294  for(i = 0; snmp_packet->used > 0; ++i) {
295  if(i >= SNMP_MAX_NR_VALUES) {
296  LOG_DBG("OID's overflow\n");
297  return 0;
298  }
299 
300  if(!snmp_ber_decode_type(snmp_packet, &type)) {
301  LOG_DBG("Could not decode type\n");
302  return 0;
303  }
304 
305  if(type != BER_DATA_TYPE_SEQUENCE) {
306  LOG_DBG("Invalid (%X) type\n", type);
307  return 0;
308  }
309 
310  if(!snmp_ber_decode_length(snmp_packet, &len)) {
311  LOG_DBG("Could not decode length\n");
312  return 0;
313  }
314 
315  if(!snmp_ber_decode_oid(snmp_packet, &varbinds[i].oid)) {
316  LOG_DBG("Could not decode oid\n");
317  return 0;
318  }
319 
320  varbinds[i].value_type = *snmp_packet->in;
321 
322  switch(varbinds[i].value_type) {
324  if(!snmp_ber_decode_integer(snmp_packet, &varbinds[i].value.integer)) {
325  LOG_DBG("Could not decode integer type\n");
326  return 0;
327  }
328  break;
330  if(!snmp_ber_decode_timeticks(snmp_packet, &varbinds[i].value.integer)) {
331  LOG_DBG("Could not decode timeticks type\n");
332  return 0;
333  }
334  break;
336  if(!snmp_ber_decode_string_len_buffer(snmp_packet, &varbinds[i].value.string.string, &varbinds[i].value.string.length)) {
337  LOG_DBG("Could not decode octed string type\n");
338  return 0;
339  }
340  break;
341  case BER_DATA_TYPE_NULL:
342  if(!snmp_ber_decode_null(snmp_packet)) {
343  LOG_DBG("Could not decode null type\n");
344  return 0;
345  }
346  break;
347  default:
348  LOG_DBG("Invalid varbind type\n");
349  return 0;
350  }
351  }
352 
353  return 1;
354 }
union snmp_varbind_s::@34 value
A union to represent the value in this varbind.
uint32_t error_status
The error status.
Definition: snmp.h:126
uint32_t version
SNMP Version.
Definition: snmp.h:97
uint32_t error_index
The error index.
Definition: snmp.h:134
#define BER_DATA_TYPE_TIMETICKS
TimeTicks.
Definition: snmp-ber.h:102
int snmp_ber_decode_null(snmp_packet_t *snmp_packet)
Decodes a null.
Definition: snmp-ber.c:492
const char * community
A pointer to the community.
Definition: snmp.h:107
snmp_oid_t oid
The OID.
Definition: snmp.h:163
The packet struct.
Definition: snmp.h:206
int snmp_ber_decode_integer(snmp_packet_t *snmp_packet, uint32_t *num)
Decodes an integer.
Definition: snmp-ber.c:351
int snmp_ber_decode_type(snmp_packet_t *snmp_packet, uint8_t *type)
Decodes a type.
Definition: snmp-ber.c:319
The varbind struct.
Definition: snmp.h:159
#define BER_DATA_TYPE_NULL
Null.
Definition: snmp-ber.h:84
uint32_t max_repetitions
The max repetitions.
Definition: snmp.h:138
int snmp_ber_encode_integer(snmp_packet_t *snmp_packet, uint32_t number)
Encodes an integer.
Definition: snmp-ber.c:152
uint32_t integer
The integer value.
Definition: snmp.h:177
#define BER_DATA_TYPE_SEQUENCE
Sequence.
Definition: snmp-ber.h:96
#define BER_DATA_TYPE_OCTET_STRING
Octet String.
Definition: snmp-ber.h:78
#define SNMP_VERSION_1
SNMP Version 1 code.
Definition: snmp.h:79
The SNMP header struct.
Definition: snmp.h:93
const char * string
A pointer to the string value from this varbind.
Definition: snmp.h:187
int snmp_ber_encode_timeticks(snmp_packet_t *snmp_packet, uint32_t timeticks)
Encodes a timeticks.
Definition: snmp-ber.c:146
SNMP Implementation of the BER encoding
int snmp_ber_encode_type(snmp_packet_t *snmp_packet, uint8_t type)
Encodes a type.
Definition: snmp-ber.c:83
int snmp_ber_decode_length(snmp_packet_t *snmp_packet, uint8_t *length)
Decodes a length.
Definition: snmp-ber.c:332
#define BER_DATA_TYPE_NO_SUCH_INSTANCE
No Such Instance.
Definition: snmp-ber.h:108
int snmp_ber_decode_string_len_buffer(snmp_packet_t *snmp_packet, const char **str, uint32_t *length)
Decodes a string.
Definition: snmp-ber.c:357
int snmp_ber_decode_oid(snmp_packet_t *snmp_packet, snmp_oid_t *oid)
Decodes an OID.
Definition: snmp-ber.c:430
int snmp_ber_encode_string_len(snmp_packet_t *snmp_packet, const char *str, uint32_t length)
Encodes a string.
Definition: snmp-ber.c:158
uint8_t * in
The pointer used for the incoming packet.
Definition: snmp.h:221
int snmp_ber_encode_oid(snmp_packet_t *snmp_packet, snmp_oid_t *oid)
Encodes a Oid.
Definition: snmp-ber.c:184
#define BER_DATA_TYPE_EOC
End-of-Content.
Definition: snmp-ber.h:66
uint8_t * out
The pointer used for the outgoing packet.
Definition: snmp.h:226
int snmp_ber_encode_length(snmp_packet_t *snmp_packet, uint16_t length)
Encodes the length.
Definition: snmp-ber.c:96
uint8_t pdu_type
The PDU type.
Definition: snmp.h:118
int snmp_message_decode(snmp_packet_t *snmp_packet, snmp_header_t *header, snmp_varbind_t *varbinds)
Definition: snmp-message.c:189
SNMP Implementation of the messages
#define BER_DATA_TYPE_PDU_GET_NEXT_REQUEST
PDU Get Next Request.
Definition: snmp-ber.h:126
uint8_t value_type
The type in this varbind.
Definition: snmp.h:167
uint16_t used
The number of bytes used.
Definition: snmp.h:211
#define BER_DATA_TYPE_PDU_SET_REQUEST
PDU Set Request.
Definition: snmp-ber.h:138
#define BER_DATA_TYPE_END_OF_MIB_VIEW
End of MIB View.
Definition: snmp-ber.h:114
uint32_t length
The string length.
Definition: snmp.h:113
int snmp_message_encode(snmp_packet_t *snmp_packet, snmp_header_t *header, snmp_varbind_t *varbinds)
Encodes a SNMP message.
Definition: snmp-message.c:49
#define BER_DATA_TYPE_INTEGER
Integer.
Definition: snmp-ber.h:72
#define SNMP_VERSION_2C
SNMP Version 2c code.
Definition: snmp.h:83
#define BER_DATA_TYPE_PDU_GET_REQUEST
PDU Get Request.
Definition: snmp-ber.h:120
uint32_t request_id
The request ID.
Definition: snmp.h:122
uint32_t non_repeaters
The non repeaters.
Definition: snmp.h:130
snmp_oid_t oid
A OID struct.
Definition: snmp-mib.h:85
#define BER_DATA_TYPE_OBJECT_IDENTIFIER
Object Identifier.
Definition: snmp-ber.h:90
int snmp_ber_encode_null(snmp_packet_t *snmp_packet, uint8_t type)
Encodes a null.
Definition: snmp-ber.c:257
#define BER_DATA_TYPE_PDU_GET_RESPONSE
PDU Get Reponse.
Definition: snmp-ber.h:132
#define SNMP_MAX_NR_VALUES
Default maximum number of OIDs in one response.
Definition: snmp-conf.h:101
int snmp_ber_decode_timeticks(snmp_packet_t *snmp_packet, uint32_t *timeticks)
Decodes a timeticks.
Definition: snmp-ber.c:345
#define BER_DATA_TYPE_PDU_GET_BULK
PDU Get Bulk.
Definition: snmp-ber.h:150