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
48int
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;
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
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 }
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
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}
188int
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;
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}
#define BER_DATA_TYPE_NO_SUCH_INSTANCE
No Such Instance.
Definition: snmp-ber.h:108
#define BER_DATA_TYPE_INTEGER
Integer.
Definition: snmp-ber.h:72
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
int snmp_ber_encode_timeticks(snmp_packet_t *snmp_packet, uint32_t timeticks)
Encodes a timeticks.
Definition: snmp-ber.c:146
#define BER_DATA_TYPE_PDU_GET_BULK
PDU Get Bulk.
Definition: snmp-ber.h:150
#define BER_DATA_TYPE_OBJECT_IDENTIFIER
Object Identifier.
Definition: snmp-ber.h:90
#define BER_DATA_TYPE_PDU_GET_RESPONSE
PDU Get Reponse.
Definition: snmp-ber.h:132
#define BER_DATA_TYPE_NULL
Null.
Definition: snmp-ber.h:84
int snmp_ber_encode_integer(snmp_packet_t *snmp_packet, uint32_t number)
Encodes an integer.
Definition: snmp-ber.c:152
int snmp_ber_decode_null(snmp_packet_t *snmp_packet)
Decodes a null.
Definition: snmp-ber.c:494
#define BER_DATA_TYPE_TIMETICKS
TimeTicks.
Definition: snmp-ber.h:102
int snmp_ber_decode_type(snmp_packet_t *snmp_packet, uint8_t *type)
Decodes a type.
Definition: snmp-ber.c:321
int snmp_ber_encode_null(snmp_packet_t *snmp_packet, uint8_t type)
Encodes a null.
Definition: snmp-ber.c:259
int snmp_ber_encode_oid(snmp_packet_t *snmp_packet, snmp_oid_t *oid)
Encodes a Oid.
Definition: snmp-ber.c:186
int snmp_ber_decode_oid(snmp_packet_t *snmp_packet, snmp_oid_t *oid)
Decodes an OID.
Definition: snmp-ber.c:432
#define BER_DATA_TYPE_PDU_GET_NEXT_REQUEST
PDU Get Next Request.
Definition: snmp-ber.h:126
int snmp_ber_decode_length(snmp_packet_t *snmp_packet, uint8_t *length)
Decodes a length.
Definition: snmp-ber.c:334
int snmp_ber_decode_integer(snmp_packet_t *snmp_packet, uint32_t *num)
Decodes an integer.
Definition: snmp-ber.c:353
int snmp_ber_encode_type(snmp_packet_t *snmp_packet, uint8_t type)
Encodes a type.
Definition: snmp-ber.c:83
#define BER_DATA_TYPE_PDU_SET_REQUEST
PDU Set Request.
Definition: snmp-ber.h:138
#define BER_DATA_TYPE_PDU_GET_REQUEST
PDU Get Request.
Definition: snmp-ber.h:120
int snmp_ber_encode_length(snmp_packet_t *snmp_packet, uint16_t length)
Encodes the length.
Definition: snmp-ber.c:96
#define BER_DATA_TYPE_EOC
End-of-Content.
Definition: snmp-ber.h:66
#define BER_DATA_TYPE_OCTET_STRING
Octet String.
Definition: snmp-ber.h:78
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:359
#define BER_DATA_TYPE_END_OF_MIB_VIEW
End of MIB View.
Definition: snmp-ber.h:114
int snmp_ber_decode_timeticks(snmp_packet_t *snmp_packet, uint32_t *timeticks)
Decodes a timeticks.
Definition: snmp-ber.c:347
#define BER_DATA_TYPE_SEQUENCE
Sequence.
Definition: snmp-ber.h:96
#define SNMP_MAX_NR_VALUES
Default maximum number of OIDs in one response.
Definition: snmp-conf.h:101
#define SNMP_VERSION_2C
SNMP Version 2c code.
Definition: snmp.h:83
#define SNMP_VERSION_1
SNMP Version 1 code.
Definition: snmp.h:79
int snmp_message_decode(snmp_packet_t *snmp_packet, snmp_header_t *header, snmp_varbind_t *varbinds)
Definition: snmp-message.c:189
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
SNMP Implementation of the BER encoding.
SNMP Implementation of the messages.
const char * community
A pointer to the community.
Definition: snmp.h:107
uint32_t length
The string length.
Definition: snmp.h:113
The SNMP header struct.
Definition: snmp.h:93
uint32_t request_id
The request ID.
Definition: snmp.h:122
uint8_t pdu_type
The PDU type.
Definition: snmp.h:118
uint32_t error_index
The error index.
Definition: snmp.h:134
uint32_t max_repetitions
The max repetitions.
Definition: snmp.h:138
uint32_t error_status
The error status.
Definition: snmp.h:126
uint32_t version
SNMP Version.
Definition: snmp.h:97
uint32_t non_repeaters
The non repeaters.
Definition: snmp.h:130
The packet struct.
Definition: snmp.h:206
uint8_t * in
The pointer used for the incoming packet.
Definition: snmp.h:221
uint8_t * out
The pointer used for the outgoing packet.
Definition: snmp.h:226
uint16_t used
The number of bytes used.
Definition: snmp.h:211
The varbind struct.
Definition: snmp.h:159
uint8_t value_type
The type in this varbind.
Definition: snmp.h:167
union snmp_varbind_s::@41 value
A union to represent the value in this varbind.
snmp_oid_t oid
The OID.
Definition: snmp.h:163
const char * string
A pointer to the string value from this varbind.
Definition: snmp.h:187
uint32_t integer
The integer value.
Definition: snmp.h:177